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

Bug#601187: linux-image-2.6.32-5-amd64: Please apply patch for shared I/O region support



Package: linux-2.6
Version: 2.6.32-26
Severity: wishlist

This is a followup from bug 597820. I would like to get the watchdog
support for f71889fg with a squeeze kernel. The support for that chip
isn't yet upstream, and I understand that you wouldn't want to include
it (yet). However, it would be much easier for me if I only had to rebuild
the module after each security release instead of the kernel, and this
means it would be nice if the squeeze kernel supported shared I/O region
for that module to be buildable and useable.

Please note that there are patches against hwmon/f71882fg.c in bug 597820
that would be better applied, too, but it's not that much a problem for me
to patch that module as well, though if someone builds the watchdog driver
without modifying the hwmon one, they will have troubles.

Please also note the patch makes the ABI check script barf, but there is
technically no function signature change.

Attached here is the backported patch (trivial context difference in the
header file).

Thanks

Mike
commit 85a6dce87df872e22fbcd4c0f7c66fafc16a531c
Author: Alan Cox <alan@linux.intel.com>
Date:   Mon Mar 29 19:38:00 2010 +0200

    resource: shared I/O region support
    
    SuperIO devices share regions and use lock/unlock operations to chip
    select.  We therefore need to be able to request a resource and wait for
    it to be freed by whichever other SuperIO device currently hogs it.
    Right now you have to poll which is horrible.
    
    Add a MUXED field to IO port resources. If the MUXED field is set on the
    resource and on the request (via request_muxed_region) then we block
    until the previous owner of the muxed resource releases their region.
    
    This allows us to implement proper resource sharing and locking for
    superio chips using code of the form
    
    enable_my_superio_dev() {
    	request_muxed_region(0x44, 0x02, "superio:watchdog");
    	outb() ..sequence to enable chip
    }
    
    disable_my_superio_dev() {
    	outb() .. sequence of disable chip
    	release_region(0x44, 0x02);
    }
    
    Signed-off-by: Giel van Schijndel <me@mortis.eu>
    Signed-off-by: Alan Cox <alan@linux.intel.com>
    Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 83aa812..140b00d 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -50,6 +50,7 @@ struct resource_list {
 #define IORESOURCE_STARTALIGN	0x00040000	/* start field is alignment */
 
 #define IORESOURCE_MEM_64	0x00100000
+#define IORESOURCE_MUXED	0x00400000	/* Resource is software muxed */
 
 #define IORESOURCE_EXCLUSIVE	0x08000000	/* Userland may not map this resource */
 #define IORESOURCE_DISABLED	0x10000000
@@ -136,7 +137,8 @@ static inline unsigned long resource_type(struct resource *res)
 }
 
 /* Convenience shorthand with allocation */
-#define request_region(start,n,name)	__request_region(&ioport_resource, (start), (n), (name), 0)
+#define request_region(start,n,name)		__request_region(&ioport_resource, (start), (n), (name), 0)
+#define request_muxed_region(start,n,name)	__request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED)
 #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl)
 #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0)
 #define request_mem_region_exclusive(start,n,name) \
diff --git a/kernel/resource.c b/kernel/resource.c
index fb11a58..a0db758 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -15,6 +15,7 @@
 #include <linux/spinlock.h>
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
+#include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/device.h>
 #include <linux/pfn.h>
@@ -601,6 +602,8 @@ resource_size_t resource_alignment(struct resource *res)
  * release_region releases a matching busy region.
  */
 
+static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait);
+
 /**
  * __request_region - create a new busy resource region
  * @parent: parent resource descriptor
@@ -613,6 +616,7 @@ struct resource * __request_region(struct resource *parent,
 				   resource_size_t start, resource_size_t n,
 				   const char *name, int flags)
 {
+	DECLARE_WAITQUEUE(wait, current);
 	struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
 
 	if (!res)
@@ -637,7 +641,15 @@ struct resource * __request_region(struct resource *parent,
 			if (!(conflict->flags & IORESOURCE_BUSY))
 				continue;
 		}
-
+		if (conflict->flags & flags & IORESOURCE_MUXED) {
+			add_wait_queue(&muxed_resource_wait, &wait);
+			write_unlock(&resource_lock);
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule();
+			remove_wait_queue(&muxed_resource_wait, &wait);
+			write_lock(&resource_lock);
+			continue;
+		}
 		/* Uhhuh, that didn't work out.. */
 		kfree(res);
 		res = NULL;
@@ -711,6 +723,8 @@ void __release_region(struct resource *parent, resource_size_t start,
 				break;
 			*p = res->sibling;
 			write_unlock(&resource_lock);
+			if (res->flags & IORESOURCE_MUXED)
+				wake_up(&muxed_resource_wait);
 			kfree(res);
 			return;
 		}

Reply to: