Bug#601187: linux-image-2.6.32-5-amd64: Please apply patch for shared I/O region support
Is the following going to be considered for squeeze?
Thanks,
Mike
On Sun, Oct 24, 2010 at 10:55:23AM +0200, Mike Hommey wrote:
> 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: