[GIT PATCH] driver core patches for your 2.6-git tree - Kernel

This is a discussion on [GIT PATCH] driver core patches for your 2.6-git tree - Kernel ; From: Jason Baron Base infrastructure to enable per-module debug messages. I've introduced CONFIG_DYNAMIC_PRINTK_DEBUG, which when enabled centralizes control of debugging statements on a per-module basis in one /proc file, currently, /dynamic_printk/modules. When, CONFIG_DYNAMIC_PRINTK_DEBUG, is not set, debugging statements can still ...

+ Reply to Thread
Page 2 of 3 FirstFirst 1 2 3 LastLast
Results 21 to 40 of 42

Thread: [GIT PATCH] driver core patches for your 2.6-git tree

  1. [PATCH 23/46] driver core: basic infrastructure for per-module dynamic debug messages

    From: Jason Baron

    Base infrastructure to enable per-module debug messages.

    I've introduced CONFIG_DYNAMIC_PRINTK_DEBUG, which when enabled centralizes
    control of debugging statements on a per-module basis in one /proc file,
    currently, /dynamic_printk/modules. When, CONFIG_DYNAMIC_PRINTK_DEBUG,
    is not set, debugging statements can still be enabled as before, often by
    defining 'DEBUG' for the proper compilation unit. Thus, this patch set has no
    affect when CONFIG_DYNAMIC_PRINTK_DEBUG is not set.

    The infrastructure currently ties into all pr_debug() and dev_dbg() calls. That
    is, if CONFIG_DYNAMIC_PRINTK_DEBUG is set, all pr_debug() and dev_dbg() calls
    can be dynamically enabled/disabled on a per-module basis.

    Future plans include extending this functionality to subsystems, that define
    their own debug levels and flags.

    Usage:

    Dynamic debugging is controlled by the debugfs file,
    /dynamic_printk/modules. This file contains a list of the modules that
    can be enabled. The format of the file is as follows:



  2. [PATCH 20/46] usb gadget: link fixes for storage gadget

    From: David Brownell

    Change how the file storage gadget driver builds: don't
    use separate compilation, since it works poorly when key
    parts are library code (with init sections etc). Instead
    be as close as we can to "gcc --combine ...".

    Signed-off-by: David Brownell
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/usb/gadget/Makefile | 3 +--
    drivers/usb/gadget/file_storage.c | 12 ++++++++++++
    2 files changed, 13 insertions(+), 2 deletions(-)

    diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
    index 99956b7..736d58f 100644
    --- a/drivers/usb/gadget/Makefile
    +++ b/drivers/usb/gadget/Makefile
    @@ -29,8 +29,7 @@ g_ether-objs := ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS)
    g_serial-objs := serial.o
    g_midi-objs := gmidi.o
    gadgetfs-objs := inode.o
    -g_file_storage-objs := file_storage.o usbstring.o config.o \
    - epautoconf.o
    +g_file_storage-objs := file_storage.o
    g_printer-objs := printer.o
    g_cdc-objs := cdc2.o u_ether.o f_ecm.o \
    u_serial.o f_acm.o $(C_UTILS)
    diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
    index ea2c31d..0c632d2 100644
    --- a/drivers/usb/gadget/file_storage.c
    +++ b/drivers/usb/gadget/file_storage.c
    @@ -245,6 +245,18 @@
    #include "gadget_chips.h"


    +
    +/*
    + * Kbuild is not very cooperative with respect to linking separately
    + * compiled library objects into one module. So for now we won't use
    + * separate compilation ... ensuring init/exit sections work to shrink
    + * the runtime footprint, and giving us at least some parts of what
    + * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
    + */
    +#include "usbstring.c"
    +#include "config.c"
    +#include "epautoconf.c"
    +
    /*-------------------------------------------------------------------------*/

    #define DRIVER_DESC "File-backed Storage Gadget"
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  3. [PATCH 39/46] kobject: Fix kobject_rename and !CONFIG_SYSFS

    From: Eric W. Biederman

    When looking at kobject_rename I found two bugs with
    that exist when sysfs support is disabled in the kernel.

    kobject_rename does not change the name on the kobject when
    sysfs support is not compiled in.

    kobject_rename without locking attempts to check the
    validity of a rename operation, which the kobject layer
    simply does not have the infrastructure to do.

    This patch documents the previously unstated requirement of
    kobject_rename that is the responsibility of the caller to
    provide mutual exclusion and to be certain that the new_name
    for the kobject is valid.

    This patch modifies sysfs_rename_dir in !CONFIG_SYSFS case
    to call kobject_set_name to actually change the kobject_name.

    This patch removes the bogus and misleading check in kobject_rename
    that attempts to see if a rename is valid. The check is bogus
    because we do not have the proper locking. The check is misleading
    because it looks like we can and do perform checking at the kobject
    level that we don't.

    Signed-off-by: Eric W. Biederman
    Signed-off-by: Greg Kroah-Hartman
    ---
    Documentation/kobject.txt | 4 ++++
    drivers/base/core.c | 5 +++++
    include/linux/sysfs.h | 4 +++-
    lib/kobject.c | 18 +++++-------------
    4 files changed, 17 insertions(+), 14 deletions(-)

    diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
    index 51a8021..f5d2aad 100644
    --- a/Documentation/kobject.txt
    +++ b/Documentation/kobject.txt
    @@ -118,6 +118,10 @@ the name of the kobject, call kobject_rename():

    int kobject_rename(struct kobject *kobj, const char *new_name);

    +Note kobject_rename does perform any locking or have a solid notion of
    +what names are valid so the provide must provide their own sanity checking
    +and serialization.
    +
    There is a function called kobject_set_name() but that is legacy cruft and
    is being removed. If your code needs to call this function, it is
    incorrect and needs to be fixed.
    diff --git a/drivers/base/core.c b/drivers/base/core.c
    index 9649d1c..8c2cc26 100644
    --- a/drivers/base/core.c
    +++ b/drivers/base/core.c
    @@ -1327,6 +1327,11 @@ EXPORT_SYMBOL_GPL(device_destroy);
    * device_rename - renames a device
    * @dev: the pointer to the struct device to be renamed
    * @new_name: the new name of the device
    + *
    + * It is the responsibility of the caller to provide mutual
    + * exclusion between two different calls of device_rename
    + * on the same device to ensure that new_name is valid and
    + * won't conflict with other devices.
    */
    int device_rename(struct device *dev, char *new_name)
    {
    diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
    index b330e28..39924a9 100644
    --- a/include/linux/sysfs.h
    +++ b/include/linux/sysfs.h
    @@ -20,6 +20,8 @@
    struct kobject;
    struct module;

    +extern int kobject_set_name(struct kobject *kobj, const char *name, ...)
    + __attribute__((format(printf, 2, 3)));
    /* FIXME
    * The *owner field is no longer used, but leave around
    * until the tree gets cleaned up fully.
    @@ -147,7 +149,7 @@ static inline void sysfs_remove_dir(struct kobject *kobj)

    static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
    {
    - return 0;
    + return kobject_set_name(kobj, "%s", new_name);
    }

    static inline int sysfs_move_dir(struct kobject *kobj,
    diff --git a/lib/kobject.c b/lib/kobject.c
    index fbf0ae2..ae6bb90 100644
    --- a/lib/kobject.c
    +++ b/lib/kobject.c
    @@ -387,6 +387,11 @@ EXPORT_SYMBOL_GPL(kobject_init_and_add);
    * kobject_rename - change the name of an object
    * @kobj: object in question.
    * @new_name: object's new name
    + *
    + * It is the responsibility of the caller to provide mutual
    + * exclusion between two different calls of kobject_rename
    + * on the same kobject and to ensure that new_name is valid and
    + * won't conflict with other kobjects.
    */
    int kobject_rename(struct kobject *kobj, const char *new_name)
    {
    @@ -401,19 +406,6 @@ int kobject_rename(struct kobject *kobj, const char *new_name)
    if (!kobj->parent)
    return -EINVAL;

    - /* see if this name is already in use */
    - if (kobj->kset) {
    - struct kobject *temp_kobj;
    - temp_kobj = kset_find_obj(kobj->kset, new_name);
    - if (temp_kobj) {
    - printk(KERN_WARNING "kobject '%s' cannot be renamed "
    - "to '%s' as '%s' is already in existence.\n",
    - kobject_name(kobj), new_name, new_name);
    - kobject_put(temp_kobj);
    - return -EINVAL;
    - }
    - }
    -
    devpath = kobject_get_path(kobj, GFP_KERNEL);
    if (!devpath) {
    error = -ENOMEM;
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  4. [PATCH 27/46] Driver core: Clarify device cleanup.

    From: Cornelia Huck

    Make the comments on how to use device_initialize(), device_add()
    and device_register() a bit clearer - in particular, explicitly
    note that put_device() must be used once we tried to add the device
    to the hierarchy.

    Signed-off-by: Cornelia Huck
    Cc: stable
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/base/core.c | 23 ++++++++++++++++++-----
    1 files changed, 18 insertions(+), 5 deletions(-)

    diff --git a/drivers/base/core.c b/drivers/base/core.c
    index b98cb14..aac91e8 100644
    --- a/drivers/base/core.c
    +++ b/drivers/base/core.c
    @@ -523,11 +523,16 @@ static void klist_children_put(struct klist_node *n)
    * device_initialize - init device structure.
    * @dev: device.
    *
    - * This prepares the device for use by other layers,
    - * including adding it to the device hierarchy.
    + * This prepares the device for use by other layers by initializing
    + * its fields.
    * It is the first half of device_register(), if called by
    - * that, though it can also be called separately, so one
    - * may use @dev's fields (e.g. the refcount).
    + * that function, though it can also be called separately, so one
    + * may use @dev's fields. In particular, get_device()/put_device()
    + * may be used for reference counting of @dev after calling this
    + * function.
    + *
    + * NOTE: Use put_device() to give up your reference instead of freeing
    + * @dev directly once you have called this function.
    */
    void device_initialize(struct device *dev)
    {
    @@ -835,9 +840,13 @@ static void device_remove_sys_dev_entry(struct device *dev)
    * This is part 2 of device_register(), though may be called
    * separately _iff_ device_initialize() has been called separately.
    *
    - * This adds it to the kobject hierarchy via kobject_add(), adds it
    + * This adds @dev to the kobject hierarchy via kobject_add(), adds it
    * to the global and sibling lists for the device, then
    * adds it to the other relevant subsystems of the driver model.
    + *
    + * NOTE: _Never_ directly free @dev after calling this function, even
    + * if it returned an error! Always use put_device() to give up your
    + * reference instead.
    */
    int device_add(struct device *dev)
    {
    @@ -965,6 +974,10 @@ done:
    * I.e. you should only call the two helpers separately if
    * have a clearly defined need to use and refcount the device
    * before it is added to the hierarchy.
    + *
    + * NOTE: _Never_ directly free @dev after calling this function, even
    + * if it returned an error! Always use put_device() to give up the
    + * reference initialized in this function instead.
    */
    int device_register(struct device *dev)
    {
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  5. [PATCH 30/46] sysfs: fix deadlock

    From: Nick Piggin

    On Thu, Sep 11, 2008 at 10:27:10AM +0200, Ingo Molnar wrote:

    > and it's working fine on most boxes. One testbox found this new locking
    > scenario:
    >
    > PM: Adding info for No Bus:vcsa7
    > EDAC DEBUG: MC0: i82860_check()
    >
    > ================================================== =====
    > [ INFO: possible circular locking dependency detected ]
    > 2.6.27-rc6-tip #1
    > -------------------------------------------------------
    > X/4873 is trying to acquire lock:
    > (&bb->mutex){--..}, at: [] mmap+0x40/0xa0
    >
    > but task is already holding lock:
    > (&mm->mmap_sem){----}, at: [] sys_mmap2+0x8e/0xc0
    >
    > which lock already depends on the new lock.
    >
    >
    > the existing dependency chain (in reverse order) is:
    >
    > -> #1 (&mm->mmap_sem){----}:
    > [] validate_chain+0xa96/0xf50
    > [] __lock_acquire+0x2cb/0x5b0
    > [] lock_acquire+0x89/0xc0
    > [] might_fault+0x6b/0x90
    > [] copy_to_user+0x38/0x60
    > [] read+0xfb/0x170
    > [] vfs_read+0x95/0x110
    > [] sys_pread64+0x63/0x80
    > [] sysenter_do_call+0x12/0x43
    > [] 0xffffffff
    >
    > -> #0 (&bb->mutex){--..}:
    > [] validate_chain+0x6b7/0xf50
    > [] __lock_acquire+0x2cb/0x5b0
    > [] lock_acquire+0x89/0xc0
    > [] __mutex_lock_common+0xab/0x3c0
    > [] mutex_lock_nested+0x38/0x50
    > [] mmap+0x40/0xa0
    > [] mmap_region+0x14e/0x450
    > [] do_mmap_pgoff+0x2ef/0x310
    > [] sys_mmap2+0xad/0xc0
    > [] sysenter_do_call+0x12/0x43
    > [] 0xffffffff
    >
    > other info that might help us debug this:
    >
    > 1 lock held by X/4873:
    > #0: (&mm->mmap_sem){----}, at: [] sys_mmap2+0x8e/0xc0
    >
    > stack backtrace:
    > Pid: 4873, comm: X Not tainted 2.6.27-rc6-tip #1
    > [] print_circular_bug_tail+0x79/0xc0
    > [] validate_chain+0x6b7/0xf50
    > [] ? trace_hardirqs_off_caller+0x15/0xb0
    > [] __lock_acquire+0x2cb/0x5b0
    > [] lock_acquire+0x89/0xc0
    > [] ? mmap+0x40/0xa0
    > [] __mutex_lock_common+0xab/0x3c0
    > [] ? mmap+0x40/0xa0
    > [] mutex_lock_nested+0x38/0x50
    > [] ? mmap+0x40/0xa0
    > [] mmap+0x40/0xa0
    > [] mmap_region+0x14e/0x450
    > [] ? arch_get_unmapped_area_topdown+0xf8/0x160
    > [] do_mmap_pgoff+0x2ef/0x310
    > [] sys_mmap2+0xad/0xc0
    > [] sysenter_do_call+0x12/0x43
    > [] ? __switch_to+0x130/0x220
    > =======================
    > evbug.c: Event. Dev: input3, Type: 20, Code: 0, Value: 500
    > warning: `sudo' uses deprecated v2 capabilities in a way that may be insecure.
    >
    > i've attached the config.
    >
    > at first sight it looks like a genuine bug in fs/sysfs/bin.c?


    Yes, it is a real bug by the looks. bin.c takes bb->mutex under mmap_sem
    when it is mmapped, and then does its copy_*_user under bb->mutex too.

    Here is a basic fix for the sysfs lor.


    From: Nick Piggin
    Signed-off-by: Ingo Molnar
    Signed-off-by: Greg Kroah-Hartman
    ---
    fs/sysfs/bin.c | 42 +++++++++++++++++++++++++++++++-----------
    1 files changed, 31 insertions(+), 11 deletions(-)

    diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
    index 006fc64..66f6e58 100644
    --- a/fs/sysfs/bin.c
    +++ b/fs/sysfs/bin.c
    @@ -61,6 +61,7 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
    int size = dentry->d_inode->i_size;
    loff_t offs = *off;
    int count = min_t(size_t, bytes, PAGE_SIZE);
    + char *temp;

    if (size) {
    if (offs > size)
    @@ -69,23 +70,33 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
    count = size - offs;
    }

    + temp = kmalloc(count, GFP_KERNEL);
    + if (!temp)
    + return -ENOMEM;
    +
    mutex_lock(&bb->mutex);

    count = fill_read(dentry, bb->buffer, offs, count);
    - if (count < 0)
    - goto out_unlock;
    + if (count < 0) {
    + mutex_unlock(&bb->mutex);
    + goto out_free;
    + }

    - if (copy_to_user(userbuf, bb->buffer, count)) {
    + memcpy(temp, bb->buffer, count);
    +
    + mutex_unlock(&bb->mutex);
    +
    + if (copy_to_user(userbuf, temp, count)) {
    count = -EFAULT;
    - goto out_unlock;
    + goto out_free;
    }

    pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);

    *off = offs + count;

    - out_unlock:
    - mutex_unlock(&bb->mutex);
    + out_free:
    + kfree(temp);
    return count;
    }

    @@ -118,6 +129,7 @@ static ssize_t write(struct file *file, const char __user *userbuf,
    int size = dentry->d_inode->i_size;
    loff_t offs = *off;
    int count = min_t(size_t, bytes, PAGE_SIZE);
    + char *temp;

    if (size) {
    if (offs > size)
    @@ -126,19 +138,27 @@ static ssize_t write(struct file *file, const char __user *userbuf,
    count = size - offs;
    }

    - mutex_lock(&bb->mutex);
    + temp = kmalloc(count, GFP_KERNEL);
    + if (!temp)
    + return -ENOMEM;

    - if (copy_from_user(bb->buffer, userbuf, count)) {
    + if (copy_from_user(temp, userbuf, count)) {
    count = -EFAULT;
    - goto out_unlock;
    + goto out_free;
    }

    + mutex_lock(&bb->mutex);
    +
    + memcpy(bb->buffer, temp, count);
    +
    count = flush_write(dentry, bb->buffer, offs, count);
    + mutex_unlock(&bb->mutex);
    +
    if (count > 0)
    *off = offs + count;

    - out_unlock:
    - mutex_unlock(&bb->mutex);
    +out_free:
    + kfree(temp);
    return count;
    }

    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  6. [PATCH 28/46] Driver core: Fix cleanup in device_create_vargs().

    From: Cornelia Huck

    If device_register() in device_create_vargs() fails, the device
    must be cleaned up with put_device() (which is also fine on NULL)
    instead of kfree().

    Signed-off-by: Cornelia Huck
    Cc: stable
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/base/core.c | 2 +-
    1 files changed, 1 insertions(+), 1 deletions(-)

    diff --git a/drivers/base/core.c b/drivers/base/core.c
    index aac91e8..9649d1c 100644
    --- a/drivers/base/core.c
    +++ b/drivers/base/core.c
    @@ -1256,7 +1256,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
    return dev;

    error:
    - kfree(dev);
    + put_device(dev);
    return ERR_PTR(retval);
    }
    EXPORT_SYMBOL_GPL(device_create_vargs);
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  7. [PATCH 34/46] Driver core: make bus_find_device_by_name() more robust

    From: Peter Korsgaard

    Use sysfs_streq() in bus_find_device_by_name() so trailing newlines
    are ignored (E.G. in bind/unbind).

    Signed-off-by: Peter Korsgaard
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/base/bus.c | 4 +---
    1 files changed, 1 insertions(+), 3 deletions(-)

    diff --git a/drivers/base/bus.c b/drivers/base/bus.c
    index ef522ae..39b9b58 100644
    --- a/drivers/base/bus.c
    +++ b/drivers/base/bus.c
    @@ -333,9 +333,7 @@ static int match_name(struct device *dev, void *data)
    {
    const char *name = data;

    - if (strcmp(name, dev->bus_id) == 0)
    - return 1;
    - return 0;
    + return sysfs_streq(name, dev->bus_id);
    }

    /**
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  8. [PATCH 16/46] usb gadget: link fixes for serial gadget

    From: David Brownell

    Change how the serial gadget driver builds: don't use
    separate compilation, since it works poorly when key parts
    are library code (with init sections etc). Instead be as
    close as we can to "gcc --combine ...".

    Signed-off-by: David Brownell
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/usb/gadget/Makefile | 2 +-
    drivers/usb/gadget/serial.c | 18 ++++++++++++++++++
    2 files changed, 19 insertions(+), 1 deletions(-)

    diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
    index fcb5cb9..853dd02 100644
    --- a/drivers/usb/gadget/Makefile
    +++ b/drivers/usb/gadget/Makefile
    @@ -26,7 +26,7 @@ C_UTILS = composite.o usbstring.o config.o epautoconf.o

    g_zero-objs := zero.o f_sourcesink.o f_loopback.o $(C_UTILS)
    g_ether-objs := ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS)
    -g_serial-objs := serial.o u_serial.o f_acm.o f_serial.o $(C_UTILS)
    +g_serial-objs := serial.o
    g_midi-objs := gmidi.o usbstring.o config.o epautoconf.o
    gadgetfs-objs := inode.o
    g_file_storage-objs := file_storage.o usbstring.o config.o \
    diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
    index b3699af..3faa7a7 100644
    --- a/drivers/usb/gadget/serial.c
    +++ b/drivers/usb/gadget/serial.c
    @@ -30,6 +30,24 @@

    /*-------------------------------------------------------------------------*/

    +/*
    + * Kbuild is not very cooperative with respect to linking separately
    + * compiled library objects into one module. So for now we won't use
    + * separate compilation ... ensuring init/exit sections work to shrink
    + * the runtime footprint, and giving us at least some parts of what
    + * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
    + */
    +#include "composite.c"
    +#include "usbstring.c"
    +#include "config.c"
    +#include "epautoconf.c"
    +
    +#include "f_acm.c"
    +#include "f_serial.c"
    +#include "u_serial.c"
    +
    +/*-------------------------------------------------------------------------*/
    +
    /* Thanks to NetChip Technologies for donating this product ID.
    *
    * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  9. [PATCH 26/46] drivers/firmware/iscsi_ibft.c: make 3 functions static

    From: Adrian Bunk

    This patch makes the following needlessly global functions static:
    - ibft_attr_show_initiator()
    - ibft_attr_show_nic()
    - ibft_attr_show_target()

    Signed-off-by: Adrian Bunk
    Signed-off-by: Konrad Rzeszutek
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/firmware/iscsi_ibft.c | 18 +++++++++---------
    1 files changed, 9 insertions(+), 9 deletions(-)

    diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
    index b91ef63..deb154a 100644
    --- a/drivers/firmware/iscsi_ibft.c
    +++ b/drivers/firmware/iscsi_ibft.c
    @@ -334,9 +334,9 @@ static void ibft_release(struct kobject *kobj)
    /*
    * Routines for parsing the iBFT data to be human readable.
    */
    -ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
    - struct ibft_attribute *attr,
    - char *buf)
    +static ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
    + struct ibft_attribute *attr,
    + char *buf)
    {
    struct ibft_initiator *initiator = entry->initiator;
    void *ibft_loc = entry->header;
    @@ -376,9 +376,9 @@ ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry,
    return str - buf;
    }

    -ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
    - struct ibft_attribute *attr,
    - char *buf)
    +static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
    + struct ibft_attribute *attr,
    + char *buf)
    {
    struct ibft_nic *nic = entry->nic;
    void *ibft_loc = entry->header;
    @@ -440,9 +440,9 @@ ssize_t ibft_attr_show_nic(struct ibft_kobject *entry,
    return str - buf;
    };

    -ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
    - struct ibft_attribute *attr,
    - char *buf)
    +static ssize_t ibft_attr_show_target(struct ibft_kobject *entry,
    + struct ibft_attribute *attr,
    + char *buf)
    {
    struct ibft_tgt *tgt = entry->tgt;
    void *ibft_loc = entry->header;
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  10. [PATCH 37/46] platform: add new device registration helper

    From: Dmitry Baryshkov

    Add a helper that registers simple platform_device w/o resources but with
    parent and device data.

    This is usefull to cleanup platform code from code that registers such
    simple devices as leds-gpio, generic-bl, etc.

    Signed-off-by: Dmitry Baryshkov
    Cc: David Brownell
    Signed-off-by: Andrew Morton
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/base/platform.c | 47 +++++++++++++++++++++++++++++++++++++++
    include/linux/platform_device.h | 2 +
    2 files changed, 49 insertions(+), 0 deletions(-)

    diff --git a/drivers/base/platform.c b/drivers/base/platform.c
    index e621dad..9e60f7c 100644
    --- a/drivers/base/platform.c
    +++ b/drivers/base/platform.c
    @@ -391,6 +391,53 @@ error:
    }
    EXPORT_SYMBOL_GPL(platform_device_register_simple) ;

    +/**
    + * platform_device_register_data
    + * @parent: parent device for the device we're adding
    + * @name: base name of the device we're adding
    + * @id: instance id
    + * @data: platform specific data for this platform device
    + * @size: size of platform specific data
    + *
    + * This function creates a simple platform device that requires minimal
    + * resource and memory management. Canned release function freeing memory
    + * allocated for the device allows drivers using such devices to be
    + * unloaded without waiting for the last reference to the device to be
    + * dropped.
    + */
    +struct platform_device *platform_device_register_data(
    + struct device *parent,
    + const char *name, int id,
    + const void *data, size_t size)
    +{
    + struct platform_device *pdev;
    + int retval;
    +
    + pdev = platform_device_alloc(name, id);
    + if (!pdev) {
    + retval = -ENOMEM;
    + goto error;
    + }
    +
    + pdev->dev.parent = parent;
    +
    + if (size) {
    + retval = platform_device_add_data(pdev, data, size);
    + if (retval)
    + goto error;
    + }
    +
    + retval = platform_device_add(pdev);
    + if (retval)
    + goto error;
    +
    + return pdev;
    +
    +error:
    + platform_device_put(pdev);
    + return ERR_PTR(retval);
    +}
    +
    static int platform_drv_probe(struct device *_dev)
    {
    struct platform_driver *drv = to_platform_driver(_dev->driver);
    diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
    index 95ac21a..4b8cc6a 100644
    --- a/include/linux/platform_device.h
    +++ b/include/linux/platform_device.h
    @@ -37,6 +37,8 @@ extern int platform_add_devices(struct platform_device **, int);

    extern struct platform_device *platform_device_register_simple(const char *, int id,
    struct resource *, unsigned int);
    +extern struct platform_device *platform_device_register_data(struct device *,
    + const char *, int, const void *, size_t);

    extern struct platform_device *platform_device_alloc(const char *name, int id);
    extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  11. [PATCH 17/46] usb gadget: link fixes for gadget zero

    From: David Brownell

    Change how the Gadget Zero driver builds: don't use
    separate compilation, since it works poorly when key
    parts are library code (with init sections etc).
    Instead be as close as we can to "gcc --combine ...".

    Signed-off-by: David Brownell
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/usb/gadget/Makefile | 2 +-
    drivers/usb/gadget/f_loopback.c | 34 ++++++++++++++++++----------------
    drivers/usb/gadget/zero.c | 17 +++++++++++++++++
    3 files changed, 36 insertions(+), 17 deletions(-)

    diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
    index 853dd02..55f5891 100644
    --- a/drivers/usb/gadget/Makefile
    +++ b/drivers/usb/gadget/Makefile
    @@ -24,7 +24,7 @@ obj-$(CONFIG_USB_M66592) += m66592-udc.o
    #
    C_UTILS = composite.o usbstring.o config.o epautoconf.o

    -g_zero-objs := zero.o f_sourcesink.o f_loopback.o $(C_UTILS)
    +g_zero-objs := zero.o
    g_ether-objs := ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS)
    g_serial-objs := serial.o
    g_midi-objs := gmidi.o usbstring.o config.o epautoconf.o
    diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
    index eda4cde..87dde01 100644
    --- a/drivers/usb/gadget/f_loopback.c
    +++ b/drivers/usb/gadget/f_loopback.c
    @@ -70,7 +70,7 @@ static struct usb_interface_descriptor loopback_intf = {

    /* full speed support: */

    -static struct usb_endpoint_descriptor fs_source_desc = {
    +static struct usb_endpoint_descriptor fs_loop_source_desc = {
    .bLength = USB_DT_ENDPOINT_SIZE,
    .bDescriptorType = USB_DT_ENDPOINT,

    @@ -78,7 +78,7 @@ static struct usb_endpoint_descriptor fs_source_desc = {
    .bmAttributes = USB_ENDPOINT_XFER_BULK,
    };

    -static struct usb_endpoint_descriptor fs_sink_desc = {
    +static struct usb_endpoint_descriptor fs_loop_sink_desc = {
    .bLength = USB_DT_ENDPOINT_SIZE,
    .bDescriptorType = USB_DT_ENDPOINT,

    @@ -88,14 +88,14 @@ static struct usb_endpoint_descriptor fs_sink_desc = {

    static struct usb_descriptor_header *fs_loopback_descs[] = {
    (struct usb_descriptor_header *) &loopback_intf,
    - (struct usb_descriptor_header *) &fs_sink_desc,
    - (struct usb_descriptor_header *) &fs_source_desc,
    + (struct usb_descriptor_header *) &fs_loop_sink_desc,
    + (struct usb_descriptor_header *) &fs_loop_source_desc,
    NULL,
    };

    /* high speed support: */

    -static struct usb_endpoint_descriptor hs_source_desc = {
    +static struct usb_endpoint_descriptor hs_loop_source_desc = {
    .bLength = USB_DT_ENDPOINT_SIZE,
    .bDescriptorType = USB_DT_ENDPOINT,

    @@ -103,7 +103,7 @@ static struct usb_endpoint_descriptor hs_source_desc = {
    .wMaxPacketSize = __constant_cpu_to_le16(512),
    };

    -static struct usb_endpoint_descriptor hs_sink_desc = {
    +static struct usb_endpoint_descriptor hs_loop_sink_desc = {
    .bLength = USB_DT_ENDPOINT_SIZE,
    .bDescriptorType = USB_DT_ENDPOINT,

    @@ -113,8 +113,8 @@ static struct usb_endpoint_descriptor hs_sink_desc = {

    static struct usb_descriptor_header *hs_loopback_descs[] = {
    (struct usb_descriptor_header *) &loopback_intf,
    - (struct usb_descriptor_header *) &hs_source_desc,
    - (struct usb_descriptor_header *) &hs_sink_desc,
    + (struct usb_descriptor_header *) &hs_loop_source_desc,
    + (struct usb_descriptor_header *) &hs_loop_sink_desc,
    NULL,
    };

    @@ -152,7 +152,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)

    /* allocate endpoints */

    - loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
    + loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
    if (!loop->in_ep) {
    autoconf_fail:
    ERROR(cdev, "%s: can't autoconfigure on %s\n",
    @@ -161,17 +161,17 @@ autoconf_fail:
    }
    loop->in_ep->driver_data = cdev; /* claim */

    - loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
    + loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
    if (!loop->out_ep)
    goto autoconf_fail;
    loop->out_ep->driver_data = cdev; /* claim */

    /* support high speed hardware */
    if (gadget_is_dualspeed(c->cdev->gadget)) {
    - hs_source_desc.bEndpointAddress =
    - fs_source_desc.bEndpointAddress;
    - hs_sink_desc.bEndpointAddress =
    - fs_sink_desc.bEndpointAddress;
    + hs_loop_source_desc.bEndpointAddress =
    + fs_loop_source_desc.bEndpointAddress;
    + hs_loop_sink_desc.bEndpointAddress =
    + fs_loop_sink_desc.bEndpointAddress;
    f->hs_descriptors = hs_loopback_descs;
    }

    @@ -255,8 +255,10 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
    struct usb_request *req;
    unsigned i;

    - src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);
    - sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc);
    + src = ep_choose(cdev->gadget,
    + &hs_loop_source_desc, &fs_loop_source_desc);
    + sink = ep_choose(cdev->gadget,
    + &hs_loop_sink_desc, &fs_loop_sink_desc);

    /* one endpoint writes data back IN to the host */
    ep = loop->in_ep;
    diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
    index aa0bd4f..361d965 100644
    --- a/drivers/usb/gadget/zero.c
    +++ b/drivers/usb/gadget/zero.c
    @@ -59,6 +59,23 @@

    /*-------------------------------------------------------------------------*/

    +/*
    + * Kbuild is not very cooperative with respect to linking separately
    + * compiled library objects into one module. So for now we won't use
    + * separate compilation ... ensuring init/exit sections work to shrink
    + * the runtime footprint, and giving us at least some parts of what
    + * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
    + */
    +#include "composite.c"
    +#include "usbstring.c"
    +#include "config.c"
    +#include "epautoconf.c"
    +
    +#include "f_sourcesink.c"
    +#include "f_loopback.c"
    +
    +/*-------------------------------------------------------------------------*/
    +
    #define DRIVER_VERSION "Cinco de Mayo 2008"

    static const char longname[] = "Gadget Zero";
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  12. [PATCH 13/46] device create: video: convert device_create_drvdata to device_create

    Now that device_create() has been audited, rename things back to the
    original call to be sane.

    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/video/console/fbcon.c | 4 ++--
    drivers/video/display/display-sysfs.c | 9 +++------
    drivers/video/fbmem.c | 5 ++---
    3 files changed, 7 insertions(+), 11 deletions(-)

    diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
    index da91bb1..0e0ea42 100644
    --- a/drivers/video/console/fbcon.c
    +++ b/drivers/video/console/fbcon.c
    @@ -3573,8 +3573,8 @@ static int __init fb_console_init(void)

    acquire_console_sem();
    fb_register_client(&fbcon_event_notifier);
    - fbcon_device = device_create_drvdata(fb_class, NULL, MKDEV(0, 0),
    - NULL, "fbcon");
    + fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL,
    + "fbcon");

    if (IS_ERR(fbcon_device)) {
    printk(KERN_WARNING "Unable to create device "
    diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c
    index 6ef800b..4830b1b 100644
    --- a/drivers/video/display/display-sysfs.c
    +++ b/drivers/video/display/display-sysfs.c
    @@ -153,12 +153,9 @@ struct display_device *display_device_register(struct display_driver *driver,
    mutex_unlock(&allocated_dsp_lock);

    if (!ret) {
    - new_dev->dev = device_create_drvdata(display_class,
    - parent,
    - MKDEV(0,0),
    - new_dev,
    - "display%d",
    - new_dev->idx);
    + new_dev->dev = device_create(display_class, parent,
    + MKDEV(0, 0), new_dev,
    + "display%d", new_dev->idx);
    if (!IS_ERR(new_dev->dev)) {
    new_dev->parent = parent;
    new_dev->driver = driver;
    diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
    index 0737570..61b36ca 100644
    --- a/drivers/video/fbmem.c
    +++ b/drivers/video/fbmem.c
    @@ -1443,9 +1443,8 @@ register_framebuffer(struct fb_info *fb_info)
    break;
    fb_info->node = i;

    - fb_info->dev = device_create_drvdata(fb_class, fb_info->device,
    - MKDEV(FB_MAJOR, i), NULL,
    - "fb%d", i);
    + fb_info->dev = device_create(fb_class, fb_info->device,
    + MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
    if (IS_ERR(fb_info->dev)) {
    /* Not fatal */
    printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  13. [PATCH 44/46] UIO: Change driver name of uio_pdrv

    From: Hans J. Koch

    The generic UIO platform device driver should be given a unique driver ID and
    not just "uio". This is especially important since we now have a similar driver
    named uio_pdrv_genirq. Currently, there's no user of this driver in the
    mainline kernel.

    Signed-off-by: Hans J. Koch
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/uio/uio_pdrv.c | 2 +-
    1 files changed, 1 insertions(+), 1 deletions(-)

    diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c
    index 0b4ef39..d494ce9 100644
    --- a/drivers/uio/uio_pdrv.c
    +++ b/drivers/uio/uio_pdrv.c
    @@ -12,7 +12,7 @@
    #include
    #include

    -#define DRIVER_NAME "uio"
    +#define DRIVER_NAME "uio_pdrv"

    struct uio_platdata {
    struct uio_info *uioinfo;
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  14. [PATCH 41/46] NET: convert the phy_device file to use bus_find_device_by_name

    The driver core now has this helper function, so might as well use it
    instead of forcing the phy code to roll their own version.

    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/net/phy/phy_device.c | 8 +-------
    1 files changed, 1 insertions(+), 7 deletions(-)

    diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
    index f11e900..e11b03b 100644
    --- a/drivers/net/phy/phy_device.c
    +++ b/drivers/net/phy/phy_device.c
    @@ -309,11 +309,6 @@ void phy_disconnect(struct phy_device *phydev)
    }
    EXPORT_SYMBOL(phy_disconnect);

    -static int phy_compare_id(struct device *dev, void *data)
    -{
    - return strcmp((char *)data, dev->bus_id) ? 0 : 1;
    -}
    -
    /**
    * phy_attach - attach a network device to a particular PHY device
    * @dev: network device to attach
    @@ -337,8 +332,7 @@ struct phy_device *phy_attach(struct net_device *dev,

    /* Search the list of PHY devices on the mdio bus for the
    * PHY with the requested name */
    - d = bus_find_device(bus, NULL, (void *)bus_id, phy_compare_id);
    -
    + d = bus_find_device_by_name(bus, NULL, bus_id);
    if (d) {
    phydev = to_phy_device(d);
    } else {
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  15. [PATCH 45/46] UIO: add automata sercos3 pci card support

    From: John Ogness

    Here is a new version of the patch to support the Automata Sercos III
    PCI card driver. I now check that the IRQ is enabled before accepting
    the interrupt.

    I still use a logical OR to store the enabled interrupts and I've
    added a second use of a logical OR when restoring the enabled
    interrupts. I added an explanation of why I do this in comments at the
    top of the source file.

    Since I use a logical OR, I also removed the extra checks if the
    Interrupt Enable Register and ier0_cache are 0.

    Signed-off-by: John Ogness
    Signed-off-by: Hans J. Koch
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/uio/Kconfig | 13 +++
    drivers/uio/Makefile | 1 +
    drivers/uio/uio_sercos3.c | 243 +++++++++++++++++++++++++++++++++++++++++++++
    3 files changed, 257 insertions(+), 0 deletions(-)
    create mode 100644 drivers/uio/uio_sercos3.c

    diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
    index 4190be6..04b954c 100644
    --- a/drivers/uio/Kconfig
    +++ b/drivers/uio/Kconfig
    @@ -58,4 +58,17 @@ config UIO_SMX

    If you compile this as a module, it will be called uio_smx.

    +config UIO_SERCOS3
    + tristate "Automata Sercos III PCI card driver"
    + default n
    + help
    + Userspace I/O interface for the Sercos III PCI card from
    + Automata GmbH. The userspace part of this driver will be
    + available for download from the Automata GmbH web site.
    +
    + Automata GmbH: http://www.automataweb.com
    + Sercos III interface: http://www.sercos.com
    +
    + If you compile this as a module, it will be called uio_sercos3.
    +
    endif
    diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
    index 8667bbd..e695581 100644
    --- a/drivers/uio/Makefile
    +++ b/drivers/uio/Makefile
    @@ -3,3 +3,4 @@ obj-$(CONFIG_UIO_CIF) += uio_cif.o
    obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o
    obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o
    obj-$(CONFIG_UIO_SMX) += uio_smx.o
    +obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
    diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c
    new file mode 100644
    index 0000000..a6d1b2b
    --- /dev/null
    +++ b/drivers/uio/uio_sercos3.c
    @@ -0,0 +1,243 @@
    +/* sercos3: UIO driver for the Automata Sercos III PCI card
    +
    + Copyright (C) 2008 Linutronix GmbH
    + Author: John Ogness
    +
    + This is a straight-forward UIO driver, where interrupts are disabled
    + by the interrupt handler and re-enabled via a write to the UIO device
    + by the userspace-part.
    +
    + The only part that may seem odd is the use of a logical OR when
    + storing and restoring enabled interrupts. This is done because the
    + userspace-part could directly modify the Interrupt Enable Register
    + at any time. To reduce possible conflicts, the kernel driver uses
    + a logical OR to make more controlled changes (rather than blindly
    + overwriting previous values).
    +
    + Race conditions exist if the userspace-part directly modifies the
    + Interrupt Enable Register while in operation. The consequences are
    + that certain interrupts would fail to be enabled or disabled. For
    + this reason, the userspace-part should only directly modify the
    + Interrupt Enable Register at the beginning (to get things going).
    + The userspace-part can safely disable interrupts at any time using
    + a write to the UIO device.
    +*/
    +
    +#include
    +#include
    +#include
    +#include
    +#include
    +
    +/* ID's for SERCOS III PCI card (PLX 9030) */
    +#define SERCOS_SUB_VENDOR_ID 0x1971
    +#define SERCOS_SUB_SYSID_3530 0x3530
    +#define SERCOS_SUB_SYSID_3535 0x3535
    +#define SERCOS_SUB_SYSID_3780 0x3780
    +
    +/* Interrupt Enable Register */
    +#define IER0_OFFSET 0x08
    +
    +/* Interrupt Status Register */
    +#define ISR0_OFFSET 0x18
    +
    +struct sercos3_priv {
    + u32 ier0_cache;
    + spinlock_t ier0_cache_lock;
    +};
    +
    +/* this function assumes ier0_cache_lock is locked! */
    +static void sercos3_disable_interrupts(struct uio_info *info,
    + struct sercos3_priv *priv)
    +{
    + void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
    +
    + /* add enabled interrupts to cache */
    + priv->ier0_cache |= ioread32(ier0);
    +
    + /* disable interrupts */
    + iowrite32(0, ier0);
    +}
    +
    +/* this function assumes ier0_cache_lock is locked! */
    +static void sercos3_enable_interrupts(struct uio_info *info,
    + struct sercos3_priv *priv)
    +{
    + void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
    +
    + /* restore previously enabled interrupts */
    + iowrite32(ioread32(ier0) | priv->ier0_cache, ier0);
    + priv->ier0_cache = 0;
    +}
    +
    +static irqreturn_t sercos3_handler(int irq, struct uio_info *info)
    +{
    + struct sercos3_priv *priv = info->priv;
    + void __iomem *isr0 = info->mem[3].internal_addr + ISR0_OFFSET;
    + void __iomem *ier0 = info->mem[3].internal_addr + IER0_OFFSET;
    +
    + if (!(ioread32(isr0) & ioread32(ier0)))
    + return IRQ_NONE;
    +
    + spin_lock(&priv->ier0_cache_lock);
    + sercos3_disable_interrupts(info, priv);
    + spin_unlock(&priv->ier0_cache_lock);
    +
    + return IRQ_HANDLED;
    +}
    +
    +static int sercos3_irqcontrol(struct uio_info *info, s32 irq_on)
    +{
    + struct sercos3_priv *priv = info->priv;
    +
    + spin_lock_irq(&priv->ier0_cache_lock);
    + if (irq_on)
    + sercos3_enable_interrupts(info, priv);
    + else
    + sercos3_disable_interrupts(info, priv);
    + spin_unlock_irq(&priv->ier0_cache_lock);
    +
    + return 0;
    +}
    +
    +static int sercos3_setup_iomem(struct pci_dev *dev, struct uio_info *info,
    + int n, int pci_bar)
    +{
    + info->mem[n].addr = pci_resource_start(dev, pci_bar);
    + if (!info->mem[n].addr)
    + return -1;
    + info->mem[n].internal_addr = ioremap(pci_resource_start(dev, pci_bar),
    + pci_resource_len(dev, pci_bar));
    + if (!info->mem[n].internal_addr)
    + return -1;
    + info->mem[n].size = pci_resource_len(dev, pci_bar);
    + info->mem[n].memtype = UIO_MEM_PHYS;
    + return 0;
    +}
    +
    +static int __devinit sercos3_pci_probe(struct pci_dev *dev,
    + const struct pci_device_id *id)
    +{
    + struct uio_info *info;
    + struct sercos3_priv *priv;
    + int i;
    +
    + info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
    + if (!info)
    + return -ENOMEM;
    +
    + priv = kzalloc(sizeof(struct sercos3_priv), GFP_KERNEL);
    + if (!priv)
    + goto out_free;
    +
    + if (pci_enable_device(dev))
    + goto out_free_priv;
    +
    + if (pci_request_regions(dev, "sercos3"))
    + goto out_disable;
    +
    + /* we only need PCI BAR's 0, 2, 3, 4, 5 */
    + if (sercos3_setup_iomem(dev, info, 0, 0))
    + goto out_unmap;
    + if (sercos3_setup_iomem(dev, info, 1, 2))
    + goto out_unmap;
    + if (sercos3_setup_iomem(dev, info, 2, 3))
    + goto out_unmap;
    + if (sercos3_setup_iomem(dev, info, 3, 4))
    + goto out_unmap;
    + if (sercos3_setup_iomem(dev, info, 4, 5))
    + goto out_unmap;
    +
    + spin_lock_init(&priv->ier0_cache_lock);
    + info->priv = priv;
    + info->name = "Sercos_III_PCI";
    + info->version = "0.0.1";
    + info->irq = dev->irq;
    + info->irq_flags = IRQF_DISABLED | IRQF_SHARED;
    + info->handler = sercos3_handler;
    + info->irqcontrol = sercos3_irqcontrol;
    +
    + pci_set_drvdata(dev, info);
    +
    + if (uio_register_device(&dev->dev, info))
    + goto out_unmap;
    +
    + return 0;
    +
    +out_unmap:
    + for (i = 0; i < 5; i++) {
    + if (info->mem[i].internal_addr)
    + iounmap(info->mem[i].internal_addr);
    + }
    + pci_release_regions(dev);
    +out_disable:
    + pci_disable_device(dev);
    +out_free_priv:
    + kfree(priv);
    +out_free:
    + kfree(info);
    + return -ENODEV;
    +}
    +
    +static void sercos3_pci_remove(struct pci_dev *dev)
    +{
    + struct uio_info *info = pci_get_drvdata(dev);
    + int i;
    +
    + uio_unregister_device(info);
    + pci_release_regions(dev);
    + pci_disable_device(dev);
    + pci_set_drvdata(dev, NULL);
    + for (i = 0; i < 5; i++) {
    + if (info->mem[i].internal_addr)
    + iounmap(info->mem[i].internal_addr);
    + }
    + kfree(info->priv);
    + kfree(info);
    +}
    +
    +static struct pci_device_id sercos3_pci_ids[] __devinitdata = {
    + {
    + .vendor = PCI_VENDOR_ID_PLX,
    + .device = PCI_DEVICE_ID_PLX_9030,
    + .subvendor = SERCOS_SUB_VENDOR_ID,
    + .subdevice = SERCOS_SUB_SYSID_3530,
    + },
    + {
    + .vendor = PCI_VENDOR_ID_PLX,
    + .device = PCI_DEVICE_ID_PLX_9030,
    + .subvendor = SERCOS_SUB_VENDOR_ID,
    + .subdevice = SERCOS_SUB_SYSID_3535,
    + },
    + {
    + .vendor = PCI_VENDOR_ID_PLX,
    + .device = PCI_DEVICE_ID_PLX_9030,
    + .subvendor = SERCOS_SUB_VENDOR_ID,
    + .subdevice = SERCOS_SUB_SYSID_3780,
    + },
    + { 0, }
    +};
    +
    +static struct pci_driver sercos3_pci_driver = {
    + .name = "sercos3",
    + .id_table = sercos3_pci_ids,
    + .probe = sercos3_pci_probe,
    + .remove = sercos3_pci_remove,
    +};
    +
    +static int __init sercos3_init_module(void)
    +{
    + return pci_register_driver(&sercos3_pci_driver);
    +}
    +
    +static void __exit sercos3_exit_module(void)
    +{
    + pci_unregister_driver(&sercos3_pci_driver);
    +}
    +
    +module_init(sercos3_init_module);
    +module_exit(sercos3_exit_module);
    +
    +MODULE_DESCRIPTION("UIO driver for the Automata Sercos III PCI card");
    +MODULE_AUTHOR("John Ogness ");
    +MODULE_LICENSE("GPL v2");
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  16. [PATCH 46/46] UIO: Fix mapping of logical and virtual memory

    From: Andrew G. Harvey

    mmap() doesn't work as expected for UIO_MEM_LOGICAL or UIO_MEM_VIRTUAL
    mappings. The offset into the memory needs to be added, otherwise
    uio_vma_fault always returns the first page only. Note that for UIO
    userspace calls mmap() with offset = N * getpagesize() to access
    mapping N. This must be compensated when calculating the offset. A
    comment was added to explain this since it is not obvious.

    Signed-off-by: Andrew G. Harvey
    Signed-off-by: Hans J. Koch
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/uio/uio.c | 12 ++++++++++--
    1 files changed, 10 insertions(+), 2 deletions(-)

    diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
    index 557e73e..5dccf05 100644
    --- a/drivers/uio/uio.c
    +++ b/drivers/uio/uio.c
    @@ -490,15 +490,23 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
    {
    struct uio_device *idev = vma->vm_private_data;
    struct page *page;
    + unsigned long offset;

    int mi = uio_find_mem_index(vma);
    if (mi < 0)
    return VM_FAULT_SIGBUS;

    + /*
    + * We need to subtract mi because userspace uses offset = N*PAGE_SIZE
    + * to use mem[N].
    + */
    + offset = (vmf->pgoff - mi) << PAGE_SHIFT;
    +
    if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
    - page = virt_to_page(idev->info->mem[mi].addr);
    + page = virt_to_page(idev->info->mem[mi].addr + offset);
    else
    - page = vmalloc_to_page((void*)idev->info->mem[mi].addr);
    + page = vmalloc_to_page((void *)idev->info->mem[mi].addr
    + + offset);
    get_page(page);
    vmf->page = page;
    return 0;
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  17. [PATCH 43/46] UIO: Add alignment warnings for uio-mem

    From: Hans J. Koch

    This patch adds an "offset" attribute for UIO mappings. It shows the
    difference between the actual start address of the memory and the start
    address of the page.

    Signed-off-by: Hans J. Koch
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/uio/uio.c | 8 ++++++++
    1 files changed, 8 insertions(+), 0 deletions(-)

    diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
    index 9ac22c7..557e73e 100644
    --- a/drivers/uio/uio.c
    +++ b/drivers/uio/uio.c
    @@ -67,6 +67,11 @@ static ssize_t map_size_show(struct uio_mem *mem, char *buf)
    return sprintf(buf, "0x%lx\n", mem->size);
    }

    +static ssize_t map_offset_show(struct uio_mem *mem, char *buf)
    +{
    + return sprintf(buf, "0x%lx\n", mem->addr & ~PAGE_MASK);
    +}
    +
    struct uio_sysfs_entry {
    struct attribute attr;
    ssize_t (*show)(struct uio_mem *, char *);
    @@ -77,10 +82,13 @@ static struct uio_sysfs_entry addr_attribute =
    __ATTR(addr, S_IRUGO, map_addr_show, NULL);
    static struct uio_sysfs_entry size_attribute =
    __ATTR(size, S_IRUGO, map_size_show, NULL);
    +static struct uio_sysfs_entry offset_attribute =
    + __ATTR(offset, S_IRUGO, map_offset_show, NULL);

    static struct attribute *attrs[] = {
    &addr_attribute.attr,
    &size_attribute.attr,
    + &offset_attribute.attr,
    NULL, /* need to NULL terminate the list of attributes */
    };

    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  18. [PATCH 42/46] Driver core: add bus_sort_breadthfirst() function

    The PCI core wants to reorder the devices in the bus list. So move this
    functionality out of the pci core and into the driver core so that
    anyone else can also do this if needed. This also lets us change how
    struct device is attached to drivers in the future without messing with
    the PCI core.

    Acked-by: Jesse Barnes
    Signed-off-by: Greg Kroah-Hartman
    ---
    drivers/base/bus.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
    drivers/pci/probe.c | 50 ++++-------------------------------------------
    include/linux/device.h | 3 ++
    3 files changed, 58 insertions(+), 45 deletions(-)

    diff --git a/drivers/base/bus.c b/drivers/base/bus.c
    index 39b9b58..5aee1c0 100644
    --- a/drivers/base/bus.c
    +++ b/drivers/base/bus.c
    @@ -980,6 +980,56 @@ struct klist *bus_get_device_klist(struct bus_type *bus)
    }
    EXPORT_SYMBOL_GPL(bus_get_device_klist);

    +/*
    + * Yes, this forcably breaks the klist abstraction temporarily. It
    + * just wants to sort the klist, not change reference counts and
    + * take/drop locks rapidly in the process. It does all this while
    + * holding the lock for the list, so objects can't otherwise be
    + * added/removed while we're swizzling.
    + */
    +static void device_insertion_sort_klist(struct device *a, struct list_head *list,
    + int (*compare)(const struct device *a,
    + const struct device *b))
    +{
    + struct list_head *pos;
    + struct klist_node *n;
    + struct device *b;
    +
    + list_for_each(pos, list) {
    + n = container_of(pos, struct klist_node, n_node);
    + b = container_of(n, struct device, knode_bus);
    + if (compare(a, b) <= 0) {
    + list_move_tail(&a->knode_bus.n_node,
    + &b->knode_bus.n_node);
    + return;
    + }
    + }
    + list_move_tail(&a->knode_bus.n_node, list);
    +}
    +
    +void bus_sort_breadthfirst(struct bus_type *bus,
    + int (*compare)(const struct device *a,
    + const struct device *b))
    +{
    + LIST_HEAD(sorted_devices);
    + struct list_head *pos, *tmp;
    + struct klist_node *n;
    + struct device *dev;
    + struct klist *device_klist;
    +
    + device_klist = bus_get_device_klist(bus);
    +
    + spin_lock(&device_klist->k_lock);
    + list_for_each_safe(pos, tmp, &device_klist->k_list) {
    + n = container_of(pos, struct klist_node, n_node);
    + dev = container_of(n, struct device, knode_bus);
    + device_insertion_sort_klist(dev, &sorted_devices, compare);
    + }
    + list_splice(&sorted_devices, &device_klist->k_list);
    + spin_unlock(&device_klist->k_lock);
    +}
    +EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
    +
    int __init buses_init(void)
    {
    bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
    diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
    index 36698e5..dd9161a 100644
    --- a/drivers/pci/probe.c
    +++ b/drivers/pci/probe.c
    @@ -1237,8 +1237,11 @@ EXPORT_SYMBOL(pci_scan_bridge);
    EXPORT_SYMBOL_GPL(pci_scan_child_bus);
    #endif

    -static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev *b)
    +static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b)
    {
    + const struct pci_dev *a = to_pci_dev(d_a);
    + const struct pci_dev *b = to_pci_dev(d_b);
    +
    if (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1;
    else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return 1;

    @@ -1251,50 +1254,7 @@ static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev
    return 0;
    }

    -/*
    - * Yes, this forcably breaks the klist abstraction temporarily. It
    - * just wants to sort the klist, not change reference counts and
    - * take/drop locks rapidly in the process. It does all this while
    - * holding the lock for the list, so objects can't otherwise be
    - * added/removed while we're swizzling.
    - */
    -static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head *list)
    -{
    - struct list_head *pos;
    - struct klist_node *n;
    - struct device *dev;
    - struct pci_dev *b;
    -
    - list_for_each(pos, list) {
    - n = container_of(pos, struct klist_node, n_node);
    - dev = container_of(n, struct device, knode_bus);
    - b = to_pci_dev(dev);
    - if (pci_sort_bf_cmp(a, b) <= 0) {
    - list_move_tail(&a->dev.knode_bus.n_node, &b->dev.knode_bus.n_node);
    - return;
    - }
    - }
    - list_move_tail(&a->dev.knode_bus.n_node, list);
    -}
    -
    void __init pci_sort_breadthfirst(void)
    {
    - LIST_HEAD(sorted_devices);
    - struct list_head *pos, *tmp;
    - struct klist_node *n;
    - struct device *dev;
    - struct pci_dev *pdev;
    - struct klist *device_klist;
    -
    - device_klist = bus_get_device_klist(&pci_bus_type);
    -
    - spin_lock(&device_klist->k_lock);
    - list_for_each_safe(pos, tmp, &device_klist->k_list) {
    - n = container_of(pos, struct klist_node, n_node);
    - dev = container_of(n, struct device, knode_bus);
    - pdev = to_pci_dev(dev);
    - pci_insertion_sort_klist(pdev, &sorted_devices);
    - }
    - list_splice(&sorted_devices, &device_klist->k_list);
    - spin_unlock(&device_klist->k_lock);
    + bus_sort_breadthfirst(&pci_bus_type, &pci_sort_bf_cmp);
    }
    diff --git a/include/linux/device.h b/include/linux/device.h
    index ec90e79..987f591 100644
    --- a/include/linux/device.h
    +++ b/include/linux/device.h
    @@ -90,6 +90,9 @@ int __must_check bus_for_each_drv(struct bus_type *bus,
    struct device_driver *start, void *data,
    int (*fn)(struct device_driver *, void *));

    +void bus_sort_breadthfirst(struct bus_type *bus,
    + int (*compare)(const struct device *a,
    + const struct device *b));
    /*
    * Bus notifiers: Get notified of addition/removal of devices
    * and binding/unbinding of drivers to devices.
    --
    1.6.0.2

    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  19. Re: [PATCH 02/46] sysfs: crash debugging

    * Greg Kroah-Hartman (gregkh@suse.de) wrote:
    > From: Andrew Morton
    >
    > Print the name of the last-accessed sysfs file when we oops, to help track
    > down oopses which occur in sysfs store/read handlers. Because these oopses
    > tend to not leave any trace of the offending code in the stack traces.
    >
    > Cc: Kay Sievers
    > Cc: Mathieu Desnoyers
    > Signed-off-by: Andrew Morton
    > Signed-off-by: Greg Kroah-Hartman
    > ---
    > arch/x86/kernel/dumpstack_32.c | 2 ++
    > arch/x86/kernel/dumpstack_64.c | 2 ++
    > fs/sysfs/file.c | 13 +++++++++++++
    > include/linux/sysfs.h | 6 ++++++
    > 4 files changed, 23 insertions(+), 0 deletions(-)
    >
    > diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
    > index 201ee35..1a78180 100644
    > --- a/arch/x86/kernel/dumpstack_32.c
    > +++ b/arch/x86/kernel/dumpstack_32.c
    > @@ -13,6 +13,7 @@
    > #include
    > #include
    > #include
    > +#include
    >
    > #include
    >
    > @@ -343,6 +344,7 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
    > printk("DEBUG_PAGEALLOC");
    > #endif
    > printk("\n");
    > + sysfs_printk_last_file();
    > if (notify_die(DIE_OOPS, str, regs, err,
    > current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
    > return 1;
    > diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
    > index 086cc81..96a5db7 100644
    > --- a/arch/x86/kernel/dumpstack_64.c
    > +++ b/arch/x86/kernel/dumpstack_64.c
    > @@ -13,6 +13,7 @@
    > #include
    > #include
    > #include
    > +#include
    >
    > #include
    >
    > @@ -489,6 +490,7 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
    > printk("DEBUG_PAGEALLOC");
    > #endif
    > printk("\n");
    > + sysfs_printk_last_file();
    > if (notify_die(DIE_OOPS, str, regs, err,
    > current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
    > return 1;
    > diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
    > index c9e4e50..ce8339c 100644
    > --- a/fs/sysfs/file.c
    > +++ b/fs/sysfs/file.c
    > @@ -19,10 +19,18 @@
    > #include
    > #include
    > #include
    > +#include
    > #include
    >
    > #include "sysfs.h"
    >
    > +/* used in crash dumps to help with debugging */
    > +static char last_sysfs_file[PATH_MAX];
    > +void sysfs_printk_last_file(void)
    > +{
    > + printk(KERN_EMERG "last sysfs file: %s\n", last_sysfs_file);
    > +}
    > +
    > /*
    > * There's one sysfs_buffer for each open file and one
    > * sysfs_open_dirent for each sysfs_dirent with one or more open
    > @@ -328,6 +336,11 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
    > struct sysfs_buffer *buffer;
    > struct sysfs_ops *ops;
    > int error = -EACCES;
    > + char *p;
    > +
    > + p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file));
    > + if (p)


    if (!IS_ERR(p)) ?

    > + memmove(last_sysfs_file, p, strlen(p) + 1);
    >


    Given we do a strlen() here anyway, shouldn't we just use strcpy ?

    Mathieu

    > /* need attr_sd for attr and ops, its parent for kobj */
    > if (!sysfs_get_active_two(attr_sd))
    > diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
    > index 37fa241..8ec406a 100644
    > --- a/include/linux/sysfs.h
    > +++ b/include/linux/sysfs.h
    > @@ -119,6 +119,8 @@ void sysfs_remove_file_from_group(struct kobject *kobj,
    >
    > void sysfs_notify(struct kobject *kobj, char *dir, char *attr);
    >
    > +void sysfs_printk_last_file(void);
    > +
    > extern int __must_check sysfs_init(void);
    >
    > #else /* CONFIG_SYSFS */
    > @@ -231,6 +233,10 @@ static inline int __must_check sysfs_init(void)
    > return 0;
    > }
    >
    > +static inline void sysfs_printk_last_file(void)
    > +{
    > +}
    > +
    > #endif /* CONFIG_SYSFS */
    >
    > #endif /* _SYSFS_H_ */
    > --
    > 1.6.0.2
    >


    --
    Mathieu Desnoyers
    OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  20. Re: [GIT PATCH] driver core patches for your 2.6-git tree

    On Thu, Oct 16, 2008 at 10:09:55AM -0700, Greg KH wrote:
    > Here is the driver core patchset for your 2.6-git tree.
    >
    > Highlights include:


    > - dynamic dev_printk() patch, allows debugging to be turned on
    > the fly, instead of at build time. This is very good and has
    > been in the opensuse beta releases already with much success.


    while I think this is a good feature b/c it allows dynamically turning debug
    information on/off at runtime, and it creates a standard framework for
    all the DEBUGP, dprintk, DEBUG, calls that each subsystems defines for
    itself, there was some resistance to this approach in another thread,
    see: http://marc.info/?l=linux-kernel&m=122164181331567&w=2
    I am adding the relevant parties to the 'cc here in the interest of making sure
    interested parties are aware of this patch proposal.

    One concern, raised in the other thread was that subsystems might want
    to use their own defined tags, as opposed to KBUILD_MODNAME, which is
    used by default to group together debugging control. Layering this tag
    ability on top of this patchset is not hard, and I already have patches
    which begin to do that...Also, this patch allows passing one command
    line argument to enable all debugging which can later be turn on/off
    as desired. This patch already stands on its own in enabling all pr_debug and
    dev_dbg calls to be dynamically enabled.

    thanks,

    -Jason
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

+ Reply to Thread
Page 2 of 3 FirstFirst 1 2 3 LastLast