Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
c2df88cb
Commit
c2df88cb
authored
Jan 24, 2011
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'irq/numa' of
git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
parents
5bdc22a5
cd7eab44
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
117 additions
and
1 deletion
+117
-1
include/linux/interrupt.h
include/linux/interrupt.h
+32
-1
include/linux/irqdesc.h
include/linux/irqdesc.h
+3
-0
kernel/irq/manage.c
kernel/irq/manage.c
+82
-0
No files found.
include/linux/interrupt.h
View file @
c2df88cb
...
...
@@ -14,6 +14,8 @@
#include <linux/smp.h>
#include <linux/percpu.h>
#include <linux/hrtimer.h>
#include <linux/kref.h>
#include <linux/workqueue.h>
#include <asm/atomic.h>
#include <asm/ptrace.h>
...
...
@@ -240,6 +242,35 @@ extern int irq_can_set_affinity(unsigned int irq);
extern
int
irq_select_affinity
(
unsigned
int
irq
);
extern
int
irq_set_affinity_hint
(
unsigned
int
irq
,
const
struct
cpumask
*
m
);
/**
* struct irq_affinity_notify - context for notification of IRQ affinity changes
* @irq: Interrupt to which notification applies
* @kref: Reference count, for internal use
* @work: Work item, for internal use
* @notify: Function to be called on change. This will be
* called in process context.
* @release: Function to be called on release. This will be
* called in process context. Once registered, the
* structure must only be freed when this function is
* called or later.
*/
struct
irq_affinity_notify
{
unsigned
int
irq
;
struct
kref
kref
;
struct
work_struct
work
;
void
(
*
notify
)(
struct
irq_affinity_notify
*
,
const
cpumask_t
*
mask
);
void
(
*
release
)(
struct
kref
*
ref
);
};
extern
int
irq_set_affinity_notifier
(
unsigned
int
irq
,
struct
irq_affinity_notify
*
notify
);
static
inline
void
irq_run_affinity_notifiers
(
void
)
{
flush_scheduled_work
();
}
#else
/* CONFIG_SMP */
static
inline
int
irq_set_affinity
(
unsigned
int
irq
,
const
struct
cpumask
*
m
)
...
...
include/linux/irqdesc.h
View file @
c2df88cb
...
...
@@ -8,6 +8,7 @@
* For now it's included from <linux/irq.h>
*/
struct
irq_affinity_notify
;
struct
proc_dir_entry
;
struct
timer_rand_state
;
/**
...
...
@@ -24,6 +25,7 @@ struct timer_rand_state;
* @last_unhandled: aging timer for unhandled count
* @irqs_unhandled: stats field for spurious unhandled interrupts
* @lock: locking for SMP
* @affinity_notify: context for notification of affinity changes
* @pending_mask: pending rebalanced interrupts
* @threads_active: number of irqaction threads currently running
* @wait_for_threads: wait queue for sync_irq to wait for threaded handlers
...
...
@@ -70,6 +72,7 @@ struct irq_desc {
raw_spinlock_t
lock
;
#ifdef CONFIG_SMP
const
struct
cpumask
*
affinity_hint
;
struct
irq_affinity_notify
*
affinity_notify
;
#ifdef CONFIG_GENERIC_PENDING_IRQ
cpumask_var_t
pending_mask
;
#endif
...
...
kernel/irq/manage.c
View file @
c2df88cb
...
...
@@ -134,6 +134,10 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
irq_set_thread_affinity
(
desc
);
}
#endif
if
(
desc
->
affinity_notify
)
{
kref_get
(
&
desc
->
affinity_notify
->
kref
);
schedule_work
(
&
desc
->
affinity_notify
->
work
);
}
desc
->
status
|=
IRQ_AFFINITY_SET
;
raw_spin_unlock_irqrestore
(
&
desc
->
lock
,
flags
);
return
0
;
...
...
@@ -155,6 +159,79 @@ int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m)
}
EXPORT_SYMBOL_GPL
(
irq_set_affinity_hint
);
static
void
irq_affinity_notify
(
struct
work_struct
*
work
)
{
struct
irq_affinity_notify
*
notify
=
container_of
(
work
,
struct
irq_affinity_notify
,
work
);
struct
irq_desc
*
desc
=
irq_to_desc
(
notify
->
irq
);
cpumask_var_t
cpumask
;
unsigned
long
flags
;
if
(
!
desc
)
goto
out
;
if
(
!
alloc_cpumask_var
(
&
cpumask
,
GFP_KERNEL
))
goto
out
;
raw_spin_lock_irqsave
(
&
desc
->
lock
,
flags
);
#ifdef CONFIG_GENERIC_PENDING_IRQ
if
(
desc
->
status
&
IRQ_MOVE_PENDING
)
cpumask_copy
(
cpumask
,
desc
->
pending_mask
);
else
#endif
cpumask_copy
(
cpumask
,
desc
->
affinity
);
raw_spin_unlock_irqrestore
(
&
desc
->
lock
,
flags
);
notify
->
notify
(
notify
,
cpumask
);
free_cpumask_var
(
cpumask
);
out:
kref_put
(
&
notify
->
kref
,
notify
->
release
);
}
/**
* irq_set_affinity_notifier - control notification of IRQ affinity changes
* @irq: Interrupt for which to enable/disable notification
* @notify: Context for notification, or %NULL to disable
* notification. Function pointers must be initialised;
* the other fields will be initialised by this function.
*
* Must be called in process context. Notification may only be enabled
* after the IRQ is allocated and must be disabled before the IRQ is
* freed using free_irq().
*/
int
irq_set_affinity_notifier
(
unsigned
int
irq
,
struct
irq_affinity_notify
*
notify
)
{
struct
irq_desc
*
desc
=
irq_to_desc
(
irq
);
struct
irq_affinity_notify
*
old_notify
;
unsigned
long
flags
;
/* The release function is promised process context */
might_sleep
();
if
(
!
desc
)
return
-
EINVAL
;
/* Complete initialisation of *notify */
if
(
notify
)
{
notify
->
irq
=
irq
;
kref_init
(
&
notify
->
kref
);
INIT_WORK
(
&
notify
->
work
,
irq_affinity_notify
);
}
raw_spin_lock_irqsave
(
&
desc
->
lock
,
flags
);
old_notify
=
desc
->
affinity_notify
;
desc
->
affinity_notify
=
notify
;
raw_spin_unlock_irqrestore
(
&
desc
->
lock
,
flags
);
if
(
old_notify
)
kref_put
(
&
old_notify
->
kref
,
old_notify
->
release
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
irq_set_affinity_notifier
);
#ifndef CONFIG_AUTO_IRQ_AFFINITY
/*
* Generic version of the affinity autoselector.
...
...
@@ -1004,6 +1081,11 @@ void free_irq(unsigned int irq, void *dev_id)
if
(
!
desc
)
return
;
#ifdef CONFIG_SMP
if
(
WARN_ON
(
desc
->
affinity_notify
))
desc
->
affinity_notify
=
NULL
;
#endif
chip_bus_lock
(
desc
);
kfree
(
__free_irq
(
irq
,
dev_id
));
chip_bus_sync_unlock
(
desc
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment