linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] Device Resource Management
@ 2004-12-11  5:45 Adam Belay
  2004-12-16  4:14 ` Greg KH
  0 siblings, 1 reply; 7+ messages in thread
From: Adam Belay @ 2004-12-11  5:45 UTC (permalink / raw)
  To: linux-kernel; +Cc: greg, rml, mochel, len.brown, shaohua.li, Bjorn Helgaas


Hi All,

This patch is a draft for the core infustructure of driver model based
resource management.  Buses capable of dynamically allocating resources (such
as PCI or pcmcia), and recent developments with linux ACPI support have
incited the need for the kernel to keep track of system resources, and assist
in the allocation process.  Eventually I'd like to move on to more complex
problems like resource rebalancing.  This patch simply lays out some
foundation.

We currently have some infustructure, but it is more or less incomplete.  For
example, it doesn't show how resources and the devices that consume them are
related.  Also it isn't flexable enough to track all types of bus resources.
ACPI, PnP, and PCI have to allocate interrupts somewhat blindly because
request_irq happens too late in the game, and really is used to register
interrupt handlers, not track interrupt usage.

My implementation is not based on the existing "struct resource" stuff because
quite frankly, even making small changes would break a large number of
drivers.  Instead it uses "struct iores"  My hope is that we can gradually
phase the old implementation out.

With that in mind, I'd like to work out a solid new API, and would appreciate
any comments or suggestions, both on the code in this patch and the overall
design of the API.

A few issues need to be discussed.  The most important is probably how sysfs
will display resource usage?  "struct kobject" is actually larger then "struct
iores" so I don't feel very comfortable embedding it.  But, if a kobject based
sysfs resource tree would be needed, then I'd be happy to implement it.  If
not what would be a good alternative?  Does the user have to read resources
from each device like one would with this current patch?

Thanks,
Adam

This patch was only tested for compilation so it may have a few bugs/typos.
Once again I'd really appreciate any comments or suggestions.


diff -urN a/drivers/base/Makefile b/drivers/base/Makefile
--- a/drivers/base/Makefile	2004-10-18 17:54:55.000000000 -0400
+++ b/drivers/base/Makefile	2004-12-10 14:55:46.000000000 -0500
@@ -3,7 +3,7 @@
 obj-y			:= core.o sys.o interface.o bus.o \
 			   driver.o class.o class_simple.o platform.o \
 			   cpu.o firmware.o init.o map.o dmapool.o
-obj-y			+= power/
+obj-y			+= power/ resource/
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
 
diff -urN a/drivers/base/resource/bars.c b/drivers/base/resource/bars.c
--- a/drivers/base/resource/bars.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/base/resource/bars.c	2004-12-10 15:56:11.000000000 -0500
@@ -0,0 +1,42 @@
+/*
+ * bars.c - functions for manipulating device resource sets
+ *
+ * Copyright (c) 2004 Adam Belay
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+
+struct iores * device_get_iores(struct device *dev, unsigned int idx)
+{
+	if (idx < dev->num_resources)
+		return &dev->res[idx];
+	else
+		return NULL;
+}
+
+EXPORT_SYMBOL(device_get_iores);
+
+struct iores * device_find_iores(struct device *dev, unsigned int type,
+				 unsigned int n)
+{
+	int i;
+
+	for (i = 0; i < dev->num_resources; i++) {
+		struct iores *slot = &dev->res[i];
+
+		if (slot->type == type) {
+			if (n-- == 0) {
+				if (iores_disabled(slot))
+					return NULL;
+				else
+					return slot;
+			}
+		}
+	}
+	return NULL;
+}
+
+EXPORT_SYMBOL(device_find_iores);
diff -urN a/drivers/base/resource/base.h b/drivers/base/resource/base.h
--- a/drivers/base/resource/base.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/base/resource/base.h	2004-12-10 17:28:16.000000000 -0500
@@ -0,0 +1,19 @@
+/*
+ * base.h - internal resource management header
+ *
+ * Copyright (c) 2004 Adam Belay
+ *
+ * This file is released under the GPLv2
+ */
+
+struct iores_type {
+	char			*name;
+	spinlock_t		lock;
+	struct iores		*default_root;
+
+	struct iores * (*conflict) (struct iores *new, struct iores *root, 
+				    struct iores *from); 
+};
+
+extern struct iores_type * iores_get_type(struct iores *res);
+
diff -urN a/drivers/base/resource/device.c b/drivers/base/resource/device.c
--- a/drivers/base/resource/device.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/base/resource/device.c	2004-12-10 22:47:18.000000000 -0500
@@ -0,0 +1,69 @@
+/*
+ * device.c - device resource configuration
+ *
+ * Copyright (c) 2004 Adam Belay
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+
+static DECLARE_MUTEX(device_state_mutex);
+
+int device_assign_resources(struct device *dev)
+{
+	int ret;
+
+	down(&device_state_mutex);
+	if (dev->resource_state != DEVICE_DISABLED) {
+		up(&device_state_mutex);
+		return -EBUSY;
+	}
+	ret = dev->bus->assign(dev);
+	up(&device_state_mutex);
+	
+	if (ret)
+		printk(KERN_ERR "RES: unable to assign resource for '%s:%s'\n",
+		       dev->bus ? dev->bus->name : "no-bus", dev->kobj.name);
+	return ret;		
+}
+
+int device_enable(struct device *dev)
+{
+	int ret;
+
+	down(&device_state_mutex);
+	ret = dev->bus->enable(dev);
+	if (!ret)
+		dev->resource_state = DEVICE_ENABLED;
+	up(&device_state_mutex);
+
+	if (ret)
+		printk(KERN_ERR "RES: unable to enable '%s:%s'\n",
+		 dev->bus ? dev->bus->name : "no-bus", dev->kobj.name);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(device_enable);
+
+int device_disable(struct device *dev)
+{
+	int ret;
+
+	down(&device_state_mutex);
+	ret = dev->bus->disable(dev);
+	if (!ret)
+		dev->resource_state = DEVICE_DISABLED;
+	up(&device_state_mutex);
+
+	if (ret)
+		printk(KERN_ERR "RES: unable to disable '%s:%s'\n",
+		 dev->bus ? dev->bus->name : "no-bus", dev->kobj.name);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(device_disable);
diff -urN a/drivers/base/resource/iores.c b/drivers/base/resource/iores.c
--- a/drivers/base/resource/iores.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/base/resource/iores.c	2004-12-10 22:46:04.000000000 -0500
@@ -0,0 +1,306 @@
+/*
+ * iores.c - core resource management infustructure
+ *
+ * Copyright (c) 2004 Adam Belay
+ *
+ * This file is released under the GPLv2
+ *
+ * based on "kernel/resource.c"
+ * Copyright (c) 1999 Linus Torvalds and Martin Mares
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/iores.h>
+#include <linux/spinlock.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include "base.h"
+
+
+/* 
+ * Resource Types
+ */
+
+struct iores io_root = {
+	.type = IORES_TYPE_IO,
+	.start = 0x0000,
+	.end = IO_SPACE_LIMIT,
+};
+
+static struct iores * 
+io_detect_conflict(struct iores *new, struct iores *root, struct iores *from)
+{
+	unsigned long start, end, mask;
+	struct iores *tmp, **p;
+
+	mask = 0xffff;
+
+	if ((new->flags & IORES_IO_10DECODE))
+		mask = 0x03ff;
+	else if ((new->flags & IORES_IO_12DECODE))
+		mask = 0x0fff;
+
+	start = (new->start & mask);
+	end = (new->end & mask);
+
+	if ((start < root->start) || (end > root->end))
+		return root;
+
+	if (from)
+		p = &from->sibling;
+	else
+		p = &root->child;
+
+	for (;;) {
+		tmp = *p;
+		if (!tmp || tmp->start > end)
+			break;
+		p = &tmp->sibling;
+		if (tmp->end < start)
+			continue;
+		return tmp;
+	}
+
+	new->sibling = tmp;
+	new->start = start;
+	new->end = end;
+	*p = new;
+
+	return NULL;
+}
+
+struct iores mem_root = {
+	.type = IORES_TYPE_MEM,
+	.start = 0UL,
+	.end = ~0UL,
+};
+
+struct iores irq_root = {
+	.type = IORES_TYPE_IRQ,
+	.start = 0,
+	.end = NR_IRQS,
+};
+
+struct iores dma_root = {
+	.type = IORES_TYPE_DMA,
+	.start = 0,
+	.end = MAX_DMA_CHANNELS,
+};
+
+static struct iores_type iores_type_table[] = {
+	{ .name = "io", .default_root = &io_root,
+	  .lock = SPIN_LOCK_UNLOCKED, .conflict = io_detect_conflict },
+	{ .name = "mem", .default_root = &mem_root,
+	  .lock = SPIN_LOCK_UNLOCKED },
+	{ .name = "irq", .default_root = &irq_root,
+	  .lock = SPIN_LOCK_UNLOCKED },
+	{ .name = "dma", .default_root = &dma_root,
+	  .lock = SPIN_LOCK_UNLOCKED },
+	{ .name = "busnr", .default_root = NULL,
+	  .lock = SPIN_LOCK_UNLOCKED },
+	{}
+};
+
+#define NR_TYPES	5
+
+struct iores_type * iores_get_type(struct iores *res)
+{
+	if (res->type > (NR_TYPES - 1))
+		return NULL;
+
+	return &iores_type_table[res->type];
+}
+
+static struct iores * 
+iores_detect_conflict(struct iores *new, struct iores *root, struct iores *from)
+{
+	unsigned long start, end;
+	struct iores *tmp, **p;
+
+	start = new->start;
+	end = new->end;
+
+	if ((start < root->start) || (end > root->end))
+		return root;
+
+	if (from)
+		p = &from->sibling;
+	else
+		p = &root->child;
+
+	for (;;) {
+		tmp = *p;
+		if (!tmp || tmp->start > end)
+			break;
+		p = &tmp->sibling;
+		if (tmp->end < start)
+			continue;
+		return tmp;
+	}
+
+	new->sibling = tmp;
+	*p = new;
+
+	return NULL;
+}
+
+
+/*
+ * Resource Registration
+ */
+
+static int iores_init(struct iores *res, struct iores_type *type)
+{
+        if (!res->parent) {
+		if (type->default_root)
+			res->parent = type->default_root;
+		else
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct iores * 
+__iores_register(struct iores *res, struct iores_type *type, struct iores *from)
+{
+	if (type->conflict)
+		return type->conflict(res, res->parent, from);
+	else
+		return iores_detect_conflict(res, res->parent, from);
+}
+
+int iores_register(struct iores *res)
+{
+	struct iores_type *type;
+	struct iores *conflict;
+
+	if (!(type = iores_get_type(res)))
+		return -EINVAL;
+
+	if (iores_init(res, type))
+		return -EINVAL;
+
+	spin_lock(&type->lock);
+	conflict = __iores_register(res, type, NULL);
+	spin_unlock(&type->lock);
+
+	return conflict ? -EBUSY : 0;
+
+}
+
+EXPORT_SYMBOL(iores_register);
+
+void iores_unregister(struct iores *res)
+{
+	struct iores_type *type;
+	struct iores *tmp, **p;
+
+	if (!(type = iores_get_type(res)))
+		return;
+
+	spin_lock(&type->lock);
+	p = &res->parent->child;
+	for (;;) {
+		tmp = *p;
+		if (!tmp)
+			break;
+		if (tmp == res) {
+			*p = tmp->sibling;
+			res->parent = NULL;
+			break;
+		}
+		p = &tmp->sibling;
+	}
+	spin_unlock(&type->lock);
+}
+
+EXPORT_SYMBOL(iores_unregister);
+
+
+/*
+ * Resource Allocation
+ */
+
+int
+iores_assign_range(struct iores *res, unsigned long min, unsigned long max,
+		   unsigned long length, unsigned long align)
+{
+	struct iores *conflict;
+	struct iores_type *type;
+	
+	conflict = NULL;
+	
+	if (!(type = iores_get_type(res)))
+		return -EINVAL;		
+	if (iores_init(res, type))
+		return -EINVAL;
+		
+	res->start = min;
+	
+	spin_lock(&type->lock);
+
+	for (;;) {
+		res->end = res->start + length - 1;
+		
+		if (res->end > max)
+			break;
+		
+		if (!(conflict = __iores_register(res, type, conflict))) {
+			spin_unlock(&type->lock);
+			return 0;
+		}
+				
+                res->start = conflict->end + 1;
+		res->start = (res->start + align - 1) & ~(align - 1);
+	}
+	
+	spin_unlock(&type->lock);
+
+	return -EBUSY;
+}
+
+EXPORT_SYMBOL(iores_assign_range);
+
+int
+iores_assign_mask(struct iores *res, __u32 *p,  unsigned int count)
+{
+	int i;
+	struct iores *conflict;
+	struct iores_type *type;
+
+	conflict = NULL;
+	
+	if (!(type = iores_get_type(res)))
+		return -EINVAL;
+	if (iores_init(res, type))
+		return -EINVAL;
+
+	spin_lock(type->lock);
+	
+	while (--count) {
+		for (i = 0; i < 32; i++) {
+			if (*p & (1<<i)) {
+				res->start = res->end = i + count * 32;
+				conflict = __iores_register(res, type, conflict);
+
+				if (!conflict) {
+					spin_unlock(type->lock);
+					return 0;
+				}
+				
+			}
+		}
+		p += sizeof(__u32);
+	}
+
+	spin_unlock(type->lock);
+	
+	return -EINVAL;
+}
+
+EXPORT_SYMBOL(iores_assign_mask);
diff -urN a/drivers/base/resource/Makefile b/drivers/base/resource/Makefile
--- a/drivers/base/resource/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/base/resource/Makefile	2004-12-07 03:01:45.000000000 -0500
@@ -0,0 +1,9 @@
+#
+# Makefile for Linux Resource Management.
+#
+
+obj-y := bars.o device.o iores.o sysfs.o
+
+ifeq ($(CONFIG_DEBUG_DRIVER),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff -urN a/drivers/base/resource/sysfs.c b/drivers/base/resource/sysfs.c
--- a/drivers/base/resource/sysfs.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/base/resource/sysfs.c	2004-12-10 17:55:51.000000000 -0500
@@ -0,0 +1,145 @@
+/*
+ * sysfs.c - sysfs interface for userspace resource management.
+ *
+ *
+ * This file is released under the GPLv2
+ *
+ * Copyright (c) 2004 Adam Belay
+ *
+ * Based on drivers/base/power/sysfs.c
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/ctype.h>
+
+#include "base.h"
+
+static ssize_t state_show(struct device * dev, char * buf)
+{
+	char * state = dev->resource_state ? "enabled" : "disabled";
+	return sprintf(buf, "%s\n", state);
+}
+
+static ssize_t state_store(struct device * dev, const char * buf, size_t n)
+{
+	int ret = 0;
+
+	if (!strnicmp(buf,"enable",6)) {
+		ret = device_enable(dev);
+		goto done;
+	}
+
+	if (!strnicmp(buf,"disable",7))
+		ret = device_disable(dev);
+
+done:
+	return ret ? ret : n;
+}
+
+static DEVICE_ATTR(state, 0644, state_show, state_store);
+
+static ssize_t resources_show(struct device * dev, char * buf)
+{
+	char * str = buf;
+	int i;
+
+	for (i = 0; i < dev->num_resources; i++) {
+		struct iores *res = &dev->res[i];
+		struct iores_type *type = iores_get_type(res);
+
+		if (!type)
+			continue;
+		
+		str += sprintf(str, "%u %s ", i+1, type->name);
+		if (res->flags & IORESOURCE_UNSET)
+			str += sprintf(str, "unset\n");
+		else if (res->flags & IORESOURCE_DISABLED)
+			str += sprintf(str, "disabled\n");
+		else
+			str += sprintf(str, "0x%016lx-0x%016lx 0x%016lx\n",
+				       res->start, res->end, res->flags);
+	}
+
+	return (str - buf);
+}
+
+static ssize_t resources_store(struct device * dev, const char * buf, size_t n)
+{
+	int index;
+	char * rest;
+	int err = 0, registered;
+	struct iores *res;
+
+	index = simple_strtoul(buf, &rest, 10);
+	if (!index || index > dev->num_resources) {
+		err = -EINVAL;
+		goto done;
+	}
+
+	res = &dev->res[index-1];
+	registered = (res->flags & IORES_REGISTERED);
+
+	while (isspace(*buf))
+		++buf;
+
+	if (!strnicmp(buf,"disable",7)) {
+		if (registered)
+			iores_unregister(res);
+		res->flags |= IORES_DISABLED;
+		goto done;
+	}
+
+	if (!strnicmp(buf,"unset",5)) {
+		if (registered)
+			iores_unregister(res);
+		res->flags &= ~IORES_DISABLED;
+		goto done;
+	}
+
+	res->start = simple_strtoul(rest, &rest, 0);
+
+	while (isspace(*buf))
+		++buf;
+	if(*buf == '-') {
+		buf += 1;
+		while (isspace(*buf))
+			++buf;
+		res->end = simple_strtoul(rest, &rest, 0);
+	} else
+		res->end = res->start;
+
+	while (isspace(*buf))
+		++buf;
+	res->flags = simple_strtoul(rest, &rest, 0);
+
+	res->flags &= ~(IORES_DISABLED);
+	err = iores_register(res);
+
+done:
+	return err ? err : n;
+}
+
+static DEVICE_ATTR(resources, 0644, resources_show, resources_store);
+
+
+static struct attribute * resource_attrs[] = {
+	&dev_attr_state.attr,
+	&dev_attr_resources.attr,
+	NULL,
+};
+
+static struct attribute_group res_attr_group = {
+	.name	= "resource",
+	.attrs	= resource_attrs,
+};
+
+int res_sysfs_add(struct device * dev)
+{
+	return sysfs_create_group(&dev->kobj, &res_attr_group);
+}
+
+void res_sysfs_remove(struct device * dev)
+{
+	sysfs_remove_group(&dev->kobj, &res_attr_group);
+}
--- a/include/linux/device.h	2004-10-18 17:55:07.000000000 -0400
+++ b/include/linux/device.h	2004-12-10 17:54:22.000000000 -0500
@@ -13,6 +13,7 @@
 
 #include <linux/config.h>
 #include <linux/ioport.h>
+#include <linux/iores.h>
 #include <linux/kobject.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
@@ -41,6 +42,11 @@
 	RESUME_ENABLE,
 };
 
+enum {
+	DEVICE_DISABLED,
+	DEVICE_ENABLED,
+};
+
 struct device;
 struct device_driver;
 struct class;
@@ -63,6 +69,10 @@
 				    int num_envp, char *buffer, int buffer_size);
 	int		(*suspend)(struct device * dev, u32 state);
 	int		(*resume)(struct device * dev);
+
+	int		(*enable)(struct device *dev);
+	int		(*disable)(struct device *dev);
+	int		(*assign)(struct device *dev);
 };
 
 extern int bus_register(struct bus_type * bus);
@@ -282,6 +292,11 @@
 					     64 bit addresses for consistent
 					     allocations such descriptors. */
 
+	int		resource_state;	/* specifies whether the device is
+					   decoding resources */
+	unsigned int	num_resources;	/* number of resources in res */
+	struct iores	*res;		/* a table of resources */
+	
 	struct list_head	dma_pools;	/* dma pools (if dma'ble) */
 
 	struct dma_coherent_mem	*dma_mem; /* internal for coherent mem
--- a/include/linux/iores.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/linux/iores.h	2004-12-10 17:56:01.000000000 -0500
@@ -0,0 +1,148 @@
+/*
+ * busres.h - hardware resource management for the driver model
+ *
+ * Copyright (c) 2004 Adam Belay <abelay@novell.com>
+ */
+
+#ifndef _LINUX_IORES_H
+#define _LINUX_IORES_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+
+/*
+ * I/O Resources
+ */
+
+struct iores {
+	unsigned int type;	/* a resource class identifier that specifies a location
+				   in the resource type array, */
+	unsigned long start;	/* the starting vector */
+	unsigned long end;	/* the last vector in the range (inclusive) */
+	unsigned long flags;	/* flags (general and bus specific) */
+
+	struct iores *parent;	/* the parent resource */
+	struct iores *child;	/* the first consumer */
+	struct iores *sibling;	/* the next sibling consumer of this producer */
+	struct device *dev;	/* the device that owns this resource */
+};
+
+#define IORES_REGISTERED		0x00000001
+#define IORES_DISABLED			0x00000002
+#define IORES_SHARABLE			0x00000004
+
+static inline int iores_disabled(struct iores *res)
+{
+	return (res->flags & IORES_DISABLED);
+}
+
+static inline unsigned long iores_start(struct iores *res)
+{
+	return res->start;
+}
+
+static inline unsigned long iores_end(struct iores *res)
+{
+	return res->end;
+}
+
+static inline unsigned long iores_length(struct iores *res)
+{
+	return res->end - res->start + 1;
+}
+
+
+/*
+ * Resource Types
+ */
+
+enum {
+        IORES_TYPE_IO = 0,
+        IORES_TYPE_MEM,
+        IORES_TYPE_IRQ,
+        IORES_TYPE_DMA,
+	IORES_TYPE_BUSNR,
+};
+
+/* I/O Port */
+extern struct iores io_root;
+
+#define IORES_IO_10DECODE		0x00000100
+#define IORES_IO_12DECODE		0x00000200
+
+/* I/O Mem */
+extern struct iores mem_root;
+
+#define IORES_MEM_WIDTH_8		0x00000100
+#define IORES_MEM_WIDTH_16		0x00000200
+#define IORES_MEM_WIDTH_32		0x00000400
+#define IORES_MEM_WIDTH_64		0x00000800
+#define IORES_MEM_PREFETCH		0x00001000
+#define IORES_MEM_READONLY		0x00002000
+#define IORES_MEM_CACHEABLE		0x00004000
+
+/* Interrupts */
+extern struct iores irq_root;
+
+#define IORES_IRQ_EDGE_HIGH		0x00000100
+#define IORES_IRQ_EDGE_LOW		0x00000200
+#define IORES_IRQ_LEVEL_HIGH		0x00000400
+#define IORESOURCE_IRQ_LEVEL_LOW	0x00000800
+
+/* legacy DMA */
+extern struct iores dma_root;
+
+#define IORES_DMA_ISA_COMPAT		0x00000100
+#define IORES_DMA_TYPEA			0x00000200
+#define IORES_DMA_TYPEB			0x00000400
+#define IORES_DMA_TYPEF			0x00000800
+#define IORES_DMA_TRANS_8		0x00001000
+#define IORES_DMA_TRANS_8_16		0x00002000
+#define IORES_DMA_TRANS_16		0x00004000
+#define IORES_DMA_BUS_MASTER		0x00008000
+
+
+/*
+ * Resource Registration
+ */
+
+extern int iores_register(struct iores *res);
+extern void iores_unregister(struct iores *res);
+
+
+/*
+ * Resource Assignment Helpers
+ */
+
+extern int iores_assign_ranged(struct iores *res, unsigned long min,
+			       unsigned long max, unsigned long length,
+			       unsigned long align);
+extern int iores_assign_masked(struct iores *res, __u32 *p, 
+			       unsigned int count);
+
+
+/*
+ * Driver Utilities
+ */
+
+extern struct iores * device_get_iores(struct device *dev, unsigned int idx);
+extern struct iores * device_find_iores(struct device *dev, unsigned int type,
+				        unsigned int n);
+
+
+/*
+ * Device Control
+ */
+
+extern int device_assign_resources(struct device *dev);
+extern int device_enable(struct device *dev);
+extern int device_disable(struct device *dev);
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_IORES_H */
+

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Device Resource Management
  2004-12-11  5:45 [RFC] Device Resource Management Adam Belay
@ 2004-12-16  4:14 ` Greg KH
  2004-12-16  4:57   ` Adam Belay
  2004-12-16  5:05   ` Robert Love
  0 siblings, 2 replies; 7+ messages in thread
From: Greg KH @ 2004-12-16  4:14 UTC (permalink / raw)
  To: ambx1, linux-kernel, rml, mochel, len.brown, shaohua.li, Bjorn Helgaas

On Sat, Dec 11, 2004 at 12:45:09AM -0500, Adam Belay wrote:
> 
> Hi All,
> 
> This patch is a draft for the core infustructure of driver model based
> resource management.  Buses capable of dynamically allocating resources (such
> as PCI or pcmcia), and recent developments with linux ACPI support have
> incited the need for the kernel to keep track of system resources, and assist
> in the allocation process.  Eventually I'd like to move on to more complex
> problems like resource rebalancing.  This patch simply lays out some
> foundation.
> 
> We currently have some infustructure, but it is more or less incomplete.  For
> example, it doesn't show how resources and the devices that consume them are
> related.  Also it isn't flexable enough to track all types of bus resources.
> ACPI, PnP, and PCI have to allocate interrupts somewhat blindly because
> request_irq happens too late in the game, and really is used to register
> interrupt handlers, not track interrupt usage.

But the interrupts are assigned early in the process, right?  We still
need to do that.

> My implementation is not based on the existing "struct resource" stuff because
> quite frankly, even making small changes would break a large number of
> drivers.  Instead it uses "struct iores"  My hope is that we can gradually
> phase the old implementation out.

Ah, what's wrong with a little breakage :)

> With that in mind, I'd like to work out a solid new API, and would appreciate
> any comments or suggestions, both on the code in this patch and the overall
> design of the API.
> 
> A few issues need to be discussed.  The most important is probably how sysfs
> will display resource usage?  "struct kobject" is actually larger then "struct
> iores" so I don't feel very comfortable embedding it.  But, if a kobject based
> sysfs resource tree would be needed, then I'd be happy to implement it.  If
> not what would be a good alternative?  Does the user have to read resources
> from each device like one would with this current patch?

Why would it matter if we export this info to userspace?  Do any
userspace programs care about this information?

> This patch was only tested for compilation so it may have a few bugs/typos.
> Once again I'd really appreciate any comments or suggestions.

It looks good.  What's the main goals of this redesign (for those of us
who are old and forgot what you said at the last kernel summit...)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Device Resource Management
  2004-12-16  4:14 ` Greg KH
@ 2004-12-16  4:57   ` Adam Belay
  2004-12-17 19:21     ` Greg KH
  2004-12-16  5:05   ` Robert Love
  1 sibling, 1 reply; 7+ messages in thread
From: Adam Belay @ 2004-12-16  4:57 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, rml, mochel, len.brown, shaohua.li, Bjorn Helgaas

On Wed, Dec 15, 2004 at 08:14:05PM -0800, Greg KH wrote:
> On Sat, Dec 11, 2004 at 12:45:09AM -0500, Adam Belay wrote:
> > 
> > Hi All,
> > 
> > This patch is a draft for the core infustructure of driver model based
> > resource management.  Buses capable of dynamically allocating resources (such
> > as PCI or pcmcia), and recent developments with linux ACPI support have
> > incited the need for the kernel to keep track of system resources, and assist
> > in the allocation process.  Eventually I'd like to move on to more complex
> > problems like resource rebalancing.  This patch simply lays out some
> > foundation.
> > 
> > We currently have some infustructure, but it is more or less incomplete.  For
> > example, it doesn't show how resources and the devices that consume them are
> > related.  Also it isn't flexable enough to track all types of bus resources.
> > ACPI, PnP, and PCI have to allocate interrupts somewhat blindly because
> > request_irq happens too late in the game, and really is used to register
> > interrupt handlers, not track interrupt usage.
> 
> But the interrupts are assigned early in the process, right?  We still
> need to do that.

Yes, interrupts are usually assigned much earlier than they are serviced by
device drivers. 

> 
> > My implementation is not based on the existing "struct resource" stuff because
> > quite frankly, even making small changes would break a large number of
> > drivers.  Instead it uses "struct iores"  My hope is that we can gradually
> > phase the old implementation out.
> 
> Ah, what's wrong with a little breakage :)

I can work with that approach too :)  I was just concerned with some of the
not so testable legacy drivers.

> 
> > With that in mind, I'd like to work out a solid new API, and would appreciate
> > any comments or suggestions, both on the code in this patch and the overall
> > design of the API.
> > 
> > A few issues need to be discussed.  The most important is probably how sysfs
> > will display resource usage?  "struct kobject" is actually larger then "struct
> > iores" so I don't feel very comfortable embedding it.  But, if a kobject based
> > sysfs resource tree would be needed, then I'd be happy to implement it.  If
> > not what would be a good alternative?  Does the user have to read resources
> > from each device like one would with this current patch?
> 
> Why would it matter if we export this info to userspace?  Do any
> userspace programs care about this information?

It depends if we want userspace to handle any resource management policy.
If it doesn't, then more complex PnP algorithms will have to be implemented
in kernel.  Userspace control is more important for old technology where
resource assignment can be less flexable.  Examples would include ISAPnP and
PCMCIA.  The majority of systems could probably get by without userspace
control if we are able to map out tricky things like the 10-bit decode VGA I/O
in kernel.

Pat suggested a resource tree in sysfs with each item in the tree linking back
to the device that consumes it.  Kobject size, and strange locking/lifetime
challenges would be the major disadvantages.  Also a method for making the
actual assignments would have to be worked out.

Another reason userspace would care about this information is that it could be
really useful for debugging hardware problems.

> 
> > This patch was only tested for compilation so it may have a few bugs/typos.
> > Once again I'd really appreciate any comments or suggestions.
> 
> It looks good.  What's the main goals of this redesign (for those of us
> who are old and forgot what you said at the last kernel summit...)

Basically there are three goals:

1.) To solve the resource allocation problems we currently see with ACPI and
other bus/firmware technologies and fullfill their requirements.

2.) To integrate the tracking of bus resources into the driver model--  This
will allow us to more accurately track device dependencies.  Just like there
are power parents/domains in power management, there are resource producers in
resource management.  Also it should allow us to remove a bunch of duplicate 
code between bus drivers.

3.) To support resource rebalancing-- This will likely become necessary as PCI
express gains wider usage because it will allow for more complex PCI bridge
hierarchies.  A device could be paused, and it's resources could be adjusted
to accommodate a newly hotplugged device etc.

I appreciate the comments.

Thanks,
Adam

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Device Resource Management
  2004-12-16  4:14 ` Greg KH
  2004-12-16  4:57   ` Adam Belay
@ 2004-12-16  5:05   ` Robert Love
  2004-12-16 15:21     ` Kumar Gala
  2004-12-17 19:18     ` Greg KH
  1 sibling, 2 replies; 7+ messages in thread
From: Robert Love @ 2004-12-16  5:05 UTC (permalink / raw)
  To: Greg KH; +Cc: ambx1, linux-kernel, mochel, len.brown, shaohua.li, Bjorn Helgaas

On Wed, 2004-12-15 at 20:14 -0800, Greg KH wrote:

> Why would it matter if we export this info to userspace?  Do any
> userspace programs care about this information?

We'd love to be able to view and manipulate resource information from
HAL.  As HAL replaces vendor-specific solutions such as, say, kudzu, it
will need to make device/driver decisions and implement work arounds, so
this information is incredibly invaluable, let alone just neat to have.

Note _requiring_ user-space to implement the resource allocation
strategy is an entirely different path, and I am not arguing that.  We'd
like to read it, if nothing else.

	Robert Love



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Device Resource Management
  2004-12-16  5:05   ` Robert Love
@ 2004-12-16 15:21     ` Kumar Gala
  2004-12-17 19:18     ` Greg KH
  1 sibling, 0 replies; 7+ messages in thread
From: Kumar Gala @ 2004-12-16 15:21 UTC (permalink / raw)
  To: Robert Love
  Cc: mochel, Greg KH, ambx1, len.brown, shaohua.li, Bjorn Helgaas,
	linux-kernel

Two issues that we have discussed for embedded usage would be making 
resources 64-bit always.  We are starting to see more and more systems 
with greater than 32-bits of physical address space while still having 
32-bit effective.  The second is sharing resources.  On several devices 
the IO memory region for one device may reside inside another.  One 
example of this is the registers used to control ethernet MII PHYs 
exist inside of an ethernet controllers register block.

Also, I liked having a name in resource.  It allows us to find the 
specific resource we need if we have multiple resources of a given type 
without assuming order.  And thus adding a device_find_iores_bynames().

- kumar


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Device Resource Management
  2004-12-16  5:05   ` Robert Love
  2004-12-16 15:21     ` Kumar Gala
@ 2004-12-17 19:18     ` Greg KH
  1 sibling, 0 replies; 7+ messages in thread
From: Greg KH @ 2004-12-17 19:18 UTC (permalink / raw)
  To: Robert Love
  Cc: ambx1, linux-kernel, mochel, len.brown, shaohua.li, Bjorn Helgaas

On Thu, Dec 16, 2004 at 12:05:05AM -0500, Robert Love wrote:
> On Wed, 2004-12-15 at 20:14 -0800, Greg KH wrote:
> 
> > Why would it matter if we export this info to userspace?  Do any
> > userspace programs care about this information?
> 
> We'd love to be able to view and manipulate resource information from
> HAL.  As HAL replaces vendor-specific solutions such as, say, kudzu, it
> will need to make device/driver decisions and implement work arounds, so
> this information is incredibly invaluable, let alone just neat to have.

Ok, fair enough.  I keep forgetting about the PnP resource mess, I guess
I just want to block that nastiness out of my brain...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC] Device Resource Management
  2004-12-16  4:57   ` Adam Belay
@ 2004-12-17 19:21     ` Greg KH
  0 siblings, 0 replies; 7+ messages in thread
From: Greg KH @ 2004-12-17 19:21 UTC (permalink / raw)
  To: ambx1, linux-kernel, rml, mochel, len.brown, shaohua.li, Bjorn Helgaas

On Wed, Dec 15, 2004 at 11:57:41PM -0500, Adam Belay wrote:
> On Wed, Dec 15, 2004 at 08:14:05PM -0800, Greg KH wrote:
> > On Sat, Dec 11, 2004 at 12:45:09AM -0500, Adam Belay wrote:
> > > My implementation is not based on the existing "struct resource" stuff because
> > > quite frankly, even making small changes would break a large number of
> > > drivers.  Instead it uses "struct iores"  My hope is that we can gradually
> > > phase the old implementation out.
> > 
> > Ah, what's wrong with a little breakage :)
> 
> I can work with that approach too :)  I was just concerned with some of the
> not so testable legacy drivers.

Well, if they build properly, that's good enough to start with...  You
know the drill, you did it before...

> > > With that in mind, I'd like to work out a solid new API, and would appreciate
> > > any comments or suggestions, both on the code in this patch and the overall
> > > design of the API.
> > > 
> > > A few issues need to be discussed.  The most important is probably how sysfs
> > > will display resource usage?  "struct kobject" is actually larger then "struct
> > > iores" so I don't feel very comfortable embedding it.  But, if a kobject based
> > > sysfs resource tree would be needed, then I'd be happy to implement it.  If
> > > not what would be a good alternative?  Does the user have to read resources
> > > from each device like one would with this current patch?
> > 
> > Why would it matter if we export this info to userspace?  Do any
> > userspace programs care about this information?
> 
> It depends if we want userspace to handle any resource management policy.
> If it doesn't, then more complex PnP algorithms will have to be implemented
> in kernel.  Userspace control is more important for old technology where
> resource assignment can be less flexable.  Examples would include ISAPnP and
> PCMCIA.  The majority of systems could probably get by without userspace
> control if we are able to map out tricky things like the 10-bit decode VGA I/O
> in kernel.
> 
> Pat suggested a resource tree in sysfs with each item in the tree linking back
> to the device that consumes it.  Kobject size, and strange locking/lifetime
> challenges would be the major disadvantages.  Also a method for making the
> actual assignments would have to be worked out.

Ok, that makes sense.  I wouldn't worry about the kobject size.  I don't
think that we will run into a lot of different resources on a lot of
different devices.  Today, the only kobject size issue is for thousands
of storage devices, and those issues are already taken care of.

We can always work on shrinking the kobject size (it's on my todo list)
if it gets too big and becomes an issue here.

So in short, add it to your structure and we can go from there.

> > > This patch was only tested for compilation so it may have a few bugs/typos.
> > > Once again I'd really appreciate any comments or suggestions.
> > 
> > It looks good.  What's the main goals of this redesign (for those of us
> > who are old and forgot what you said at the last kernel summit...)
> 
> Basically there are three goals:
> 
> 1.) To solve the resource allocation problems we currently see with ACPI and
> other bus/firmware technologies and fullfill their requirements.
> 
> 2.) To integrate the tracking of bus resources into the driver model--  This
> will allow us to more accurately track device dependencies.  Just like there
> are power parents/domains in power management, there are resource producers in
> resource management.  Also it should allow us to remove a bunch of duplicate 
> code between bus drivers.
> 
> 3.) To support resource rebalancing-- This will likely become necessary as PCI
> express gains wider usage because it will allow for more complex PCI bridge
> hierarchies.  A device could be paused, and it's resources could be adjusted
> to accommodate a newly hotplugged device etc.

Thanks for reminding me.  All good goals to have.

There is a PCI Express patch on lkml that you might want to take a look
at if you are concerned as to how that might play out.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2004-12-17 19:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-12-11  5:45 [RFC] Device Resource Management Adam Belay
2004-12-16  4:14 ` Greg KH
2004-12-16  4:57   ` Adam Belay
2004-12-17 19:21     ` Greg KH
2004-12-16  5:05   ` Robert Love
2004-12-16 15:21     ` Kumar Gala
2004-12-17 19:18     ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).