lkml.org 
[lkml]   [2006]   [Jun]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 2/5] [PREEMPT_RT] Changing interrupt handlers from running in thread to hardirq and back runtime.
    This patch makes it possible to change which context the interrupt handlers
    for each interrupt run in, hard-irq or threaded if CONFIG_PREEMPT_HARDIRQS is
    set.

    The interface is the file
    /proc/irq/<irq number>/threaded
    You can read it to see what the context is now or write one of

    irq
    fifo <rt priority>
    rr <rt priority>
    normal <nice value>
    batch <nice value>

    where one of the latter makes the interrupt handler threaded.

    A replacement for request_irq(), called request_irq2(), is added. When a driver
    uses this to install it's irq-handler it can also give a change_irq_context
    call-back. This call-back is called whenever the irq-context is changed or
    going to be changed. The call-back must be of the form

    int driver_change_context(int irq, void *dev_id, enum change_context_cmd cmd)

    where

    enum change_context_cmd {
    IRQ_TO_HARDIRQ,
    IRQ_CAN_THREAD,
    IRQ_TO_THREADED
    };

    The call-back is supposed to do the following on
    IRQ_TO_HARDIRQ: make sure everything in the interrupt handler is non-blocking
    or return a non-zero error code.
    IRQ_CAN_THREAD: Return 0 if it is ok for the interrupt handler to be run in
    thread context. Return a non-zero error code otherwise.
    IRQ_TO_THREAD: Now the interrupt handler does run in thread context. The
    driver can now change it's locks to being mutexes. The return
    value is ignored as the driver already got a chance to protest
    above.

    Index: linux-2.6.16-rt23.spin_mutex/include/linux/interrupt.h
    ===================================================================
    --- linux-2.6.16-rt23.spin_mutex.orig/include/linux/interrupt.h
    +++ linux-2.6.16-rt23.spin_mutex/include/linux/interrupt.h
    @@ -34,21 +34,38 @@ typedef int irqreturn_t;
    #define IRQ_HANDLED (1)
    #define IRQ_RETVAL(x) ((x) != 0)

    +enum change_context_cmd {
    + IRQ_TO_HARDIRQ,
    + IRQ_CAN_THREAD,
    + IRQ_TO_THREADED
    +};
    +
    struct irqaction {
    irqreturn_t (*handler)(int, void *, struct pt_regs *);
    unsigned long flags;
    cpumask_t mask;
    const char *name;
    void *dev_id;
    +#ifdef CONFIG_CHANGE_IRQ_CONTEXT
    + int (*change_context)(int, void *,
    + enum change_context_cmd);
    +#endif
    struct irqaction *next;
    int irq;
    - struct proc_dir_entry *dir, *threaded;
    + struct proc_dir_entry *dir;
    + struct rcu_head rcu;
    };

    extern irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs);
    extern int request_irq(unsigned int,
    irqreturn_t (*handler)(int, void *, struct pt_regs *),
    unsigned long, const char *, void *);
    +extern int request_irq2(unsigned int irq,
    + irqreturn_t (*handler)(int, void *, struct pt_regs *),
    + unsigned long irqflags, const char * devname,
    + void *dev_id,
    + int (*change_context)(int, void *,
    + enum change_context_cmd));
    extern void free_irq(unsigned int, void *);


    Index: linux-2.6.16-rt23.spin_mutex/include/linux/irq.h
    ===================================================================
    --- linux-2.6.16-rt23.spin_mutex.orig/include/linux/irq.h
    +++ linux-2.6.16-rt23.spin_mutex/include/linux/irq.h
    @@ -47,6 +47,18 @@
    # define SA_NODELAY 0x01000000
    #endif

    +#ifndef SA_MUST_THREAD
    +# define SA_MUST_THREAD 0x02000000
    +#endif
    +
    +/* Set this flag if the irq handler must thread under preempt-rt otherwise not
    + */
    +#ifdef CONFIG_PREEMPT_RT
    +# define SA_MUST_THREAD_RT SA_MUST_THREAD
    +#else
    +# define SA_MUST_THREAD_RT 0
    +#endif
    +
    /*
    * IRQ types
    */
    @@ -147,12 +159,13 @@ struct irq_type {
    * @chip: low level hardware access functions - comes from type
    * @action: the irq action chain
    * @status: status information
    + * (protected by the spinlock )
    * @depth: disable-depth, for nested irq_disable() calls
    * @irq_count: stats field to detect stalled irqs
    * @irqs_unhandled: stats field for spurious unhandled interrupts
    * @thread: Thread pointer for threaded preemptible irq handling
    * @wait_for_handler: Waitqueue to wait for a running preemptible handler
    - * @lock: locking for SMP
    + * @lock: lock around the action list
    * @move_irq: Flag need to re-target interrupt destination
    *
    * Pad this out to 32 bytes for cache and indexing reasons.
    Index: linux-2.6.16-rt23.spin_mutex/kernel/Kconfig.preempt
    ===================================================================
    --- linux-2.6.16-rt23.spin_mutex.orig/kernel/Kconfig.preempt
    +++ linux-2.6.16-rt23.spin_mutex/kernel/Kconfig.preempt
    @@ -119,6 +119,17 @@ config PREEMPT_HARDIRQS

    Say N if you are unsure.

    +config CHANGE_IRQ_CONTEXT
    + bool "Change the irq context runtime"
    + depends on PREEMPT_HARDIRQS && (PREEMPT_RCU || !SPIN_MUTEXES)
    + help
    + You can change wether the IRQ handler(s) for each IRQ number is
    + running in hardirq context or as threaded by writing to
    + /proc/irq/<number>/threaded
    + If PREEMPT_RT is selected the drivers involved must be ready for it,
    + though, or the write will fail. Remember to switch on SPIN_MUTEXES as
    + well in that case as the drivers which are ready uses spin-mutexes.
    +
    config SPINLOCK_BKL
    bool "Old-Style Big Kernel Lock"
    depends on (PREEMPT || SMP) && !PREEMPT_RT
    Index: linux-2.6.16-rt23.spin_mutex/kernel/irq/internals.h
    ===================================================================
    --- linux-2.6.16-rt23.spin_mutex.orig/kernel/irq/internals.h
    +++ linux-2.6.16-rt23.spin_mutex/kernel/irq/internals.h
    @@ -22,6 +22,10 @@ static inline void end_irq(irq_desc_t *d
    }

    #ifdef CONFIG_PROC_FS
    +#ifdef CONFIG_CHANGE_IRQ_CONTEXT
    +extern int make_irq_nodelay(int irq, struct irq_desc *desc);
    +extern int make_irq_threaded(int irq, struct irq_desc *desc);
    +#endif
    extern void register_irq_proc(unsigned int irq);
    extern void register_handler_proc(unsigned int irq, struct irqaction *action);
    extern void unregister_handler_proc(unsigned int irq, struct irqaction *action);
    Index: linux-2.6.16-rt23.spin_mutex/kernel/irq/manage.c
    ===================================================================
    --- linux-2.6.16-rt23.spin_mutex.orig/kernel/irq/manage.c
    +++ linux-2.6.16-rt23.spin_mutex/kernel/irq/manage.c
    @@ -206,6 +206,153 @@ int can_request_irq(unsigned int irq, un
    return !action;
    }

    +
    +#ifdef CONFIG_CHANGE_IRQ_CONTEXT
    +int make_action_nodelay(int irq, struct irqaction *act)
    +{
    + unsigned long flags;
    +
    + if(!(act->flags & SA_MUST_THREAD)) {
    + return 0;
    + }
    +
    + if( act->change_context ) {
    + int ret =
    + act->change_context(irq, act->dev_id, IRQ_TO_HARDIRQ);
    + if(ret) {
    + printk(KERN_ERR "Failed to change irq handler "
    + "for dev %s on IRQ%d to hardirq "
    + "context (ret: %d)\n", act->name, irq, ret);
    + return ret;
    + }
    + spin_lock_irqsave(&irq_desc[irq].lock, flags);
    + act->flags &=~SA_MUST_THREAD;
    + act->flags |= SA_NODELAY;
    + spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
    + return 0;
    + }
    + else {
    + printk(KERN_ERR "Irq handler "
    + "for dev %s on IRQ%d can not be changed"
    + " to hardirq context\n", act->name, irq);
    + return -ENOSYS;
    + }
    +
    +}
    +
    +
    +static int __make_irq_threaded(int irq, struct irq_desc *desc);
    +
    +int make_irq_nodelay(int irq, struct irq_desc *desc)
    +{
    + int ret = 0;
    + struct irqaction *act;
    + unsigned long flags;
    +
    + rcu_read_lock();
    + for(act = desc->action; act; act = act->next) {
    + WARN_ON(((~act->flags) & (SA_MUST_THREAD|SA_NODELAY)) == 0);
    + if(act->flags & SA_MUST_THREAD) {
    + ret = make_action_nodelay(irq, act);
    + if(ret) {
    + printk(KERN_ERR "Could not make irq %d "
    + "nodelay (errno %d)\n",
    + irq, ret);
    + goto failed;
    + }
    + }
    + }
    + spin_lock_irqsave(&desc->lock, flags);
    + desc->status |= IRQ_NODELAY;
    + spin_unlock_irqrestore(&desc->lock, flags);
    + rcu_read_unlock();
    +
    + return 0;
    + failed:
    + __make_irq_threaded(irq, desc);
    + rcu_read_unlock();
    + return ret;
    +}
    +
    +int action_may_thread(int irq, struct irqaction *act)
    +{
    + if(!act->change_context)
    + return !(act->flags & SA_NODELAY);
    +
    + return act->change_context(irq, act->dev_id, IRQ_CAN_THREAD) == 0;
    +}
    +
    +
    +static int __make_irq_threaded(int irq, struct irq_desc *desc)
    +{
    + struct irqaction *act;
    +
    + for(act = desc->action; act; act = act->next) {
    + WARN_ON(((~act->flags) & (SA_MUST_THREAD|SA_NODELAY)) == 0);
    + if(!action_may_thread(irq, act)) {
    + return -EINVAL;
    + }
    + }
    +
    + if (start_irq_thread(irq, desc))
    + return -ENOMEM;
    +
    + spin_lock_irq(&desc->lock);
    + desc->status &= ~IRQ_NODELAY;
    + spin_unlock_irq(&desc->lock);
    +
    + /* We can't make irq handlers change their context before we
    + are sure no CPU is running them in hard irq context */
    + synchronize_irq(irq);
    +
    + for(act = desc->action; act; act = act->next) {
    + WARN_ON(((~act->flags) & (SA_MUST_THREAD|SA_NODELAY)) == 0);
    + if(act->change_context) {
    + /* This callback can't fail */
    + act->change_context(irq, act->dev_id, IRQ_TO_THREADED);
    + spin_lock_irq(&desc->lock);
    + act->flags &=~SA_NODELAY;
    + act->flags |= SA_MUST_THREAD;
    + spin_unlock_irq(&desc->lock);
    + }
    + }
    +
    + return 0;
    +}
    +
    +int make_irq_threaded(int irq, struct irq_desc *desc)
    +{
    + int ret;
    + rcu_read_lock();
    + ret = __make_irq_threaded(irq, desc);
    + rcu_read_unlock();
    + return ret;
    +}
    +#else /* CONFIG_CHANGE_IRQ_CONTEXT */
    +int make_action_nodelay(int irq, struct irqaction *act)
    +{
    + return -EINVAL;
    +}
    +int make_irq_nodelay(int irq, struct irq_desc *desc)
    +{
    + unsigned long flags;
    + struct irqaction *act;
    +
    + spin_lock_irqsave(&desc->lock, flags);
    + for(act = desc->action; act; act = act->next) {
    + WARN_ON((~act->flags) & (SA_MUST_THREAD|SA_NODELAY) == 0);
    + if(act->flags & SA_MUST_THREAD)
    + return -EINVAL;
    + }
    +
    + desc->status |= IRQ_NODELAY;
    + spin_unlock_irqrestore(&desc->lock, flags);
    +
    + return 0;
    +}
    +
    +#endif /* !CONFIG_CHANGE_IRQ_CONTEXT */
    +
    /*
    * Internal function to register an irqaction - typically used to
    * allocate special interrupts that are part of the architecture.
    @@ -239,11 +386,28 @@ int setup_irq(unsigned int irq, struct i
    rand_initialize_irq(irq);
    }

    + WARN_ON(((~new->flags) & (SA_MUST_THREAD|SA_NODELAY)) == 0);
    if (!(new->flags & SA_NODELAY))
    if (start_irq_thread(irq, desc))
    return -ENOMEM;
    +
    + if( (desc->status & IRQ_NODELAY) && (new->flags & SA_MUST_THREAD) ) {
    + int ret = make_action_nodelay(irq, new);
    + if(ret)
    + return ret;
    + }
    +
    +
    + if( (new->flags & SA_NODELAY) && !(desc->status & IRQ_NODELAY) ) {
    + int ret = make_irq_nodelay(irq, desc);
    + if(ret)
    + return ret;
    + }
    +
    +
    /*
    - * The following block of code has to be executed atomically
    + * The following block of code has to be executed atomically due
    + * to the hard irq context
    */
    spin_lock_irqsave(&desc->lock, flags);
    p = &desc->action;
    @@ -262,7 +426,7 @@ int setup_irq(unsigned int irq, struct i
    shared = 1;
    }

    - *p = new;
    + rcu_assign_pointer(*p, new);

    /*
    * Propagate any possible SA_NODELAY flag into IRQ_NODELAY:
    @@ -282,13 +446,25 @@ int setup_irq(unsigned int irq, struct i

    new->irq = irq;
    register_irq_proc(irq);
    - new->dir = new->threaded = NULL;
    + new->dir = NULL;
    register_handler_proc(irq, new);

    return 0;
    }

    /**
    + * free_irqaction_rcu - free the actual memory block of a struct irqaction
    + * @rcu: Pointer to the struct rcu_head
    + *
    + * Is called after RCU syncronization
    + */
    +static void free_irqaction_rcu(struct rcu_head *rcu)
    +{
    + struct irqaction *p = container_of(rcu, struct irqaction, rcu);
    + kfree(p);
    +}
    +
    +/**
    * free_irq - free an interrupt
    * @irq: Interrupt line to free
    * @dev_id: Device identity to free
    @@ -312,6 +488,7 @@ void free_irq(unsigned int irq, void *de
    return;

    desc = irq_desc + irq;
    +
    spin_lock_irqsave(&desc->lock, flags);
    p = &desc->action;
    for (;;) {
    @@ -325,7 +502,7 @@ void free_irq(unsigned int irq, void *de
    continue;

    /* Found it - now remove it from the list of entries */
    - *pp = action->next;
    + rcu_assign_pointer(*pp, action->next);

    /* Currently used only by UML, might disappear one day.*/
    #ifdef CONFIG_IRQ_RELEASE_METHOD
    @@ -344,9 +521,8 @@ void free_irq(unsigned int irq, void *de
    spin_unlock_irqrestore(&desc->lock, flags);
    unregister_handler_proc(irq, action);

    - /* Make sure it's not being used on another CPU */
    synchronize_irq(irq);
    - kfree(action);
    + call_rcu(&action->rcu, free_irqaction_rcu);
    return;
    }
    printk(KERN_ERR "Trying to free free IRQ%d\n", irq);
    @@ -358,12 +534,14 @@ void free_irq(unsigned int irq, void *de
    EXPORT_SYMBOL(free_irq);

    /**
    - * request_irq - allocate an interrupt line
    + * request_irq2 - allocate an interrupt line
    * @irq: Interrupt line to allocate
    * @handler: Function to be called when the IRQ occurs
    * @irqflags: Interrupt type flags
    * @devname: An ascii name for the claiming device
    * @dev_id: A cookie passed back to the handler function
    + * @change_context: call back for requesting a change of context
    + * (threaded vs hardirq)
    *
    * This call allocates interrupt resources and enables the
    * interrupt line and IRQ handling. From the point this
    @@ -381,18 +559,23 @@ EXPORT_SYMBOL(free_irq);
    *
    * Flags:
    *
    - * SA_SHIRQ Interrupt is shared
    + * SA_SHIRQ Interrupt can be shared
    * SA_INTERRUPT Disable local interrupts while processing
    * SA_SAMPLE_RANDOM The interrupt can be used for entropy
    + * SA_NODELAY The handler must run in hardirq context
    + * SA_MUSTTHREAD The handler can not run in hardirq context
    *
    */
    -int request_irq(unsigned int irq,
    - irqreturn_t (*handler)(int, void *, struct pt_regs *),
    - unsigned long irqflags, const char * devname, void *dev_id)
    +int request_irq2(unsigned int irq,
    + irqreturn_t (*handler)(int, void *, struct pt_regs *),
    + unsigned long irqflags, const char * devname, void *dev_id,
    + int (*change_context)(int, void *,
    + enum change_context_cmd))
    {
    struct irqaction * action;
    int retval;

    +
    /*
    * Sanity-check: shared interrupts must pass in a real dev-ID,
    * otherwise we'll have trouble later trying to figure out
    @@ -416,8 +599,11 @@ int request_irq(unsigned int irq,
    action->flags = irqflags;
    cpus_clear(action->mask);
    action->name = devname;
    - action->next = NULL;
    action->dev_id = dev_id;
    +#ifdef CONFIG_CHANGE_IRQ_CONTEXT
    + action->change_context = change_context;
    +#endif
    + action->next = NULL;

    select_smp_affinity(irq);

    @@ -427,7 +613,17 @@ int request_irq(unsigned int irq,

    return retval;
    }
    +EXPORT_SYMBOL(request_irq2);

    +int request_irq(unsigned int irq,
    + irqreturn_t (*handler)(int, void *, struct pt_regs *),
    + unsigned long irqflags, const char * devname, void *dev_id)
    +{
    + if( !(irqflags & SA_NODELAY) )
    + irqflags |= SA_MUST_THREAD_RT;
    +
    + return request_irq2(irq, handler, irqflags, devname, dev_id, NULL);
    +}
    EXPORT_SYMBOL(request_irq);

    /**
    Index: linux-2.6.16-rt23.spin_mutex/kernel/irq/proc.c
    ===================================================================
    --- linux-2.6.16-rt23.spin_mutex.orig/kernel/irq/proc.c
    +++ linux-2.6.16-rt23.spin_mutex/kernel/irq/proc.c
    @@ -11,6 +11,7 @@
    #include <linux/profile.h>
    #include <linux/proc_fs.h>
    #include <linux/interrupt.h>
    +#include <linux/ctype.h>

    #include "internals.h"

    @@ -83,6 +84,138 @@ static int irq_affinity_write_proc(struc

    #endif

    +
    +#ifdef CONFIG_CHANGE_IRQ_CONTEXT
    +/*
    + * The /proc/irq/<irq>/threaded values:
    + */
    +static struct proc_dir_entry *irq_threaded_entry[NR_IRQS];
    +
    +static const char *sched_policies[] = {
    + "normal",
    + "fifo",
    + "rr",
    + "batch"
    +};
    +
    +static int irq_threaded_read_proc(char *page, char **start, off_t off,
    + int count, int *eof, void *data)
    +{
    + unsigned int irq = (int)(long)data;
    + task_t *t;
    +
    + if ( (irq_desc[irq].status & IRQ_NODELAY)
    + || !irq_desc[irq].thread ) {
    + return scnprintf(page, count, "IRQ\n");
    + }
    +
    + t = irq_desc[irq].thread;
    + if (t->policy==SCHED_NORMAL && t->policy == SCHED_BATCH )
    + return scnprintf(page, count, "%s %d\n",
    + sched_policies[t->policy],
    + task_prio(t));
    + else
    + return scnprintf(page, count, "%s %lu\n",
    + sched_policies[t->policy],
    + t->rt_priority);
    +}
    +
    +
    +static int set_rt_prio(int irq, int policy, char *arg)
    +{
    + char *tmp;
    + struct sched_param prm;
    + int ret;
    + task_t *t;
    +
    + while(isspace(*arg))
    + arg++;
    +
    + if(*arg) {
    + prm.sched_priority = simple_strtol(arg,&tmp,10);
    + if (tmp == arg)
    + return -EINVAL;
    + }
    + else
    + return -EINVAL;
    +
    + ret = make_irq_threaded(irq, &irq_desc[irq]);
    + if(ret)
    + return ret;
    +
    + t = irq_desc[irq].thread;
    + return sched_setscheduler(t, policy, &prm);
    +}
    +
    +static int set_nonrt_prio(int irq, int policy, char *arg)
    +{
    + char *tmp;
    + long prio;
    + int ret;
    + struct sched_param prm;
    + task_t *t;
    +
    + while(isspace(*arg))
    + arg++;
    +
    +
    + if(*arg) {
    + prio = simple_strtol(arg,&tmp,10);
    + if (tmp == arg || prio < -20 || prio > 19)
    + return -EINVAL;
    + }
    + else
    + prio = 0;
    +
    + ret = make_irq_threaded(irq, &irq_desc[irq]);
    + if(ret)
    + return ret;
    +
    + t = irq_desc[irq].thread;
    + prm.sched_priority = 0;
    + ret = sched_setscheduler(t, policy, &prm);
    + if(ret)
    + return ret;
    +
    + set_user_nice(t, prio);
    + return 0;
    +}
    +
    +static int irq_threaded_write_proc(struct file *file,
    + const char __user *buffer,
    + unsigned long count, void *data)
    +{
    + unsigned int irq = (int)(long)data;
    + int ret = 0;
    + char buf[20];
    +
    + if(copy_from_user( (void*)&buf[0], (void*)buffer,
    + count>20 ? 20: count ) )
    + return -EFAULT;
    +
    + buf[19] = 0;
    +
    + if(!strnicmp(buf,"irq",3))
    + ret = make_irq_nodelay(irq, &irq_desc[irq]);
    + else if(!strnicmp(buf,"normal",3))
    + ret = set_nonrt_prio(irq, SCHED_NORMAL, buf+6);
    + else if(!strnicmp(buf,"fifo",3))
    + ret = set_rt_prio(irq, SCHED_FIFO, buf+4);
    + else if(!strnicmp(buf,"rr",2))
    + ret = set_rt_prio(irq, SCHED_RR, buf+2);
    + else if(!strnicmp(buf,"batch",3))
    + ret = set_nonrt_prio(irq, SCHED_BATCH, buf+5);
    + else
    + ret = -EINVAL;
    +
    +
    + if(ret)
    + return ret;
    + else
    + return count;
    +}
    +#endif /* CONFIG_CHANGE_IRQ_CONTEXT */
    +
    #define MAX_NAMELEN 10

    void register_irq_proc(unsigned int irq)
    @@ -116,58 +249,33 @@ void register_irq_proc(unsigned int irq)
    smp_affinity_entry[irq] = entry;
    }
    #endif
    +
    +#ifdef CONFIG_CHANGE_IRQ_CONTEXT
    + {
    + struct proc_dir_entry *entry;
    +
    + /* create /proc/irq/<irq>/threaded */
    + entry = create_proc_entry("threaded", 0600, irq_dir[irq]);
    +
    + if (entry) {
    + entry->nlink = 1;
    + entry->data = (void *)(long)irq;
    + entry->read_proc = irq_threaded_read_proc;
    + entry->write_proc = irq_threaded_write_proc;
    + }
    + irq_threaded_entry[irq] = entry;
    + }
    +#endif
    }

    #undef MAX_NAMELEN

    void unregister_handler_proc(unsigned int irq, struct irqaction *action)
    {
    - if (action->threaded)
    - remove_proc_entry(action->threaded->name, action->dir);
    if (action->dir)
    remove_proc_entry(action->dir->name, irq_dir[irq]);
    }

    -#ifndef CONFIG_PREEMPT_RT
    -
    -#ifndef CONFIG_PREEMPT_RT
    -
    -static int threaded_read_proc(char *page, char **start, off_t off,
    - int count, int *eof, void *data)
    -{
    - return sprintf(page, "%c\n",
    - ((struct irqaction *)data)->flags & SA_NODELAY ? '0' : '1');
    -}
    -
    -static int threaded_write_proc(struct file *file, const char __user *buffer,
    - unsigned long count, void *data)
    -{
    - int c;
    - struct irqaction *action = data;
    - irq_desc_t *desc = irq_desc + action->irq;
    -
    - if (get_user(c, buffer))
    - return -EFAULT;
    - if (c != '0' && c != '1')
    - return -EINVAL;
    -
    - spin_lock_irq(&desc->lock);
    -
    - if (c == '0')
    - action->flags |= SA_NODELAY;
    - if (c == '1')
    - action->flags &= ~SA_NODELAY;
    - recalculate_desc_flags(desc);
    -
    - spin_unlock_irq(&desc->lock);
    -
    - return 1;
    -}
    -
    -#endif
    -
    -#endif
    -
    #define MAX_NAMELEN 128

    static int name_unique(unsigned int irq, struct irqaction *new_action)
    @@ -197,20 +305,6 @@ void register_handler_proc(unsigned int
    action->dir = proc_mkdir(name, irq_dir[irq]);
    if (!action->dir)
    return;
    -#ifndef CONFIG_PREEMPT_RT
    - {
    - struct proc_dir_entry *entry;
    - /* create /proc/irq/1234/handler/threaded */
    - entry = create_proc_entry("threaded", 0600, action->dir);
    - if (!entry)
    - return;
    - entry->nlink = 1;
    - entry->data = (void *)action;
    - entry->read_proc = threaded_read_proc;
    - entry->write_proc = threaded_write_proc;
    - action->threaded = entry;
    - }
    -#endif
    }

    #undef MAX_NAMELEN
    --
    -
    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/

    \
     
     \ /
      Last update: 2006-06-02 23:26    [W:0.080 / U:0.208 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site