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
nexedi
linux
Commits
9145db56
Commit
9145db56
authored
Aug 10, 2011
by
Geert Uytterhoeven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
m68k/mac: Optimize interrupts using chain handlers
Signed-off-by:
Geert Uytterhoeven
<
geert@linux-m68k.org
>
parent
ddc7fd25
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
298 additions
and
63 deletions
+298
-63
arch/m68k/mac/baboon.c
arch/m68k/mac/baboon.c
+38
-0
arch/m68k/mac/oss.c
arch/m68k/mac/oss.c
+86
-20
arch/m68k/mac/psc.c
arch/m68k/mac/psc.c
+57
-17
arch/m68k/mac/via.c
arch/m68k/mac/via.c
+117
-26
No files found.
arch/m68k/mac/baboon.c
View file @
9145db56
...
...
@@ -56,6 +56,39 @@ void __init baboon_init(void)
* Baboon interrupt handler. This works a lot like a VIA.
*/
#ifdef CONFIG_GENERIC_HARDIRQS
static
void
baboon_irq
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
int
irq_bit
,
irq_num
;
unsigned
char
events
;
#ifdef DEBUG_IRQS
printk
(
"baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X
\n
"
,
(
uint
)
baboon
->
mb_control
,
(
uint
)
baboon
->
mb_ifr
,
(
uint
)
baboon
->
mb_status
);
#endif
events
=
baboon
->
mb_ifr
&
0x07
;
if
(
!
events
)
return
;
irq_num
=
IRQ_BABOON_0
;
irq_bit
=
1
;
do
{
if
(
events
&
irq_bit
)
{
baboon
->
mb_ifr
&=
~
irq_bit
;
generic_handle_irq
(
irq_num
);
}
irq_bit
<<=
1
;
irq_num
++
;
}
while
(
events
>=
irq_bit
);
#if 0
if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL);
/* for now we need to smash all interrupts */
baboon->mb_ifr &= ~events;
#endif
}
#else
static
irqreturn_t
baboon_irq
(
int
irq
,
void
*
dev_id
)
{
int
irq_bit
,
irq_num
;
...
...
@@ -87,6 +120,7 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
#endif
return
IRQ_HANDLED
;
}
#endif
/*
* Register the Baboon interrupt dispatcher on nubus slot $C.
...
...
@@ -95,8 +129,12 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
void
__init
baboon_register_interrupts
(
void
)
{
baboon_disabled
=
0
;
#ifdef CONFIG_GENERIC_HARDIRQS
irq_set_chained_handler
(
IRQ_NUBUS_C
,
baboon_irq
);
#else
if
(
request_irq
(
IRQ_NUBUS_C
,
baboon_irq
,
0
,
"baboon"
,
(
void
*
)
baboon
))
pr_err
(
"Couldn't register baboon interrupt
\n
"
);
#endif
}
/*
...
...
arch/m68k/mac/oss.c
View file @
9145db56
...
...
@@ -32,10 +32,11 @@
int
oss_present
;
volatile
struct
mac_oss
*
oss
;
static
irqreturn_t
oss_irq
(
int
,
void
*
);
static
irqreturn_t
oss_nubus_irq
(
int
,
void
*
);
#ifdef CONFIG_GENERIC_HARDIRQS
extern
void
via1_irq
(
unsigned
int
irq
,
struct
irq_desc
*
desc
);
#else
extern
irqreturn_t
via1_irq
(
int
,
void
*
);
#endif
/*
* Initialize the OSS
...
...
@@ -62,23 +63,6 @@ void __init oss_init(void)
oss
->
irq_level
[
OSS_VIA1
]
=
OSS_IRQLEV_VIA1
;
}
/*
* Register the OSS and NuBus interrupt dispatchers.
*/
void
__init
oss_register_interrupts
(
void
)
{
if
(
request_irq
(
OSS_IRQLEV_SCSI
,
oss_irq
,
0
,
"scsi"
,
(
void
*
)
oss
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"scsi"
);
if
(
request_irq
(
OSS_IRQLEV_NUBUS
,
oss_nubus_irq
,
0
,
"nubus"
,
(
void
*
)
oss
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"nubus"
);
if
(
request_irq
(
OSS_IRQLEV_SOUND
,
oss_irq
,
0
,
"sound"
,
(
void
*
)
oss
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"sound"
);
if
(
request_irq
(
OSS_IRQLEV_VIA1
,
via1_irq
,
0
,
"via1"
,
(
void
*
)
via1
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"via1"
);
}
/*
* Initialize OSS for Nubus access
*/
...
...
@@ -92,6 +76,34 @@ void __init oss_nubus_init(void)
* and SCSI; everything else is routed to its own autovector IRQ.
*/
#ifdef CONFIG_GENERIC_HARDIRQS
static
void
oss_irq
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
int
events
;
events
=
oss
->
irq_pending
&
(
OSS_IP_SOUND
|
OSS_IP_SCSI
);
if
(
!
events
)
return
;
#ifdef DEBUG_IRQS
if
((
console_loglevel
==
10
)
&&
!
(
events
&
OSS_IP_SCSI
))
{
printk
(
"oss_irq: irq %u events = 0x%04X
\n
"
,
irq
,
(
int
)
oss
->
irq_pending
);
}
#endif
/* FIXME: how do you clear a pending IRQ? */
if
(
events
&
OSS_IP_SOUND
)
{
oss
->
irq_pending
&=
~
OSS_IP_SOUND
;
/* FIXME: call sound handler */
}
else
if
(
events
&
OSS_IP_SCSI
)
{
oss
->
irq_pending
&=
~
OSS_IP_SCSI
;
generic_handle_irq
(
IRQ_MAC_SCSI
);
}
else
{
/* FIXME: error check here? */
}
}
#else
static
irqreturn_t
oss_irq
(
int
irq
,
void
*
dev_id
)
{
int
events
;
...
...
@@ -119,6 +131,7 @@ static irqreturn_t oss_irq(int irq, void *dev_id)
}
return
IRQ_HANDLED
;
}
#endif
/*
* Nubus IRQ handler, OSS style
...
...
@@ -126,6 +139,34 @@ static irqreturn_t oss_irq(int irq, void *dev_id)
* Unlike the VIA/RBV this is on its own autovector interrupt level.
*/
#ifdef CONFIG_GENERIC_HARDIRQS
static
void
oss_nubus_irq
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
int
events
,
irq_bit
,
i
;
events
=
oss
->
irq_pending
&
OSS_IP_NUBUS
;
if
(
!
events
)
return
;
#ifdef DEBUG_NUBUS_INT
if
(
console_loglevel
>
7
)
{
printk
(
"oss_nubus_irq: events = 0x%04X
\n
"
,
events
);
}
#endif
/* There are only six slots on the OSS, not seven */
i
=
6
;
irq_bit
=
0x40
;
do
{
--
i
;
irq_bit
>>=
1
;
if
(
events
&
irq_bit
)
{
oss
->
irq_pending
&=
~
irq_bit
;
generic_handle_irq
(
NUBUS_SOURCE_BASE
+
i
);
}
}
while
(
events
&
(
irq_bit
-
1
));
}
#else
static
irqreturn_t
oss_nubus_irq
(
int
irq
,
void
*
dev_id
)
{
int
events
,
irq_bit
,
i
;
...
...
@@ -153,6 +194,31 @@ static irqreturn_t oss_nubus_irq(int irq, void *dev_id)
}
while
(
events
&
(
irq_bit
-
1
));
return
IRQ_HANDLED
;
}
#endif
/*
* Register the OSS and NuBus interrupt dispatchers.
*/
void
__init
oss_register_interrupts
(
void
)
{
#ifdef CONFIG_GENERIC_HARDIRQS
irq_set_chained_handler
(
OSS_IRQLEV_SCSI
,
oss_irq
);
irq_set_chained_handler
(
OSS_IRQLEV_NUBUS
,
oss_nubus_irq
);
irq_set_chained_handler
(
OSS_IRQLEV_SOUND
,
oss_irq
);
irq_set_chained_handler
(
OSS_IRQLEV_VIA1
,
via1_irq
);
#else
/* !CONFIG_GENERIC_HARDIRQS */
if
(
request_irq
(
OSS_IRQLEV_SCSI
,
oss_irq
,
0
,
"scsi"
,
(
void
*
)
oss
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"scsi"
);
if
(
request_irq
(
OSS_IRQLEV_NUBUS
,
oss_nubus_irq
,
0
,
"nubus"
,
(
void
*
)
oss
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"nubus"
);
if
(
request_irq
(
OSS_IRQLEV_SOUND
,
oss_irq
,
0
,
"sound"
,
(
void
*
)
oss
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"sound"
);
if
(
request_irq
(
OSS_IRQLEV_VIA1
,
via1_irq
,
0
,
"via1"
,
(
void
*
)
via1
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"via1"
);
#endif
/* !CONFIG_GENERIC_HARDIRQS */
}
/*
* Enable an OSS interrupt
...
...
arch/m68k/mac/psc.c
View file @
9145db56
...
...
@@ -33,8 +33,6 @@
int
psc_present
;
volatile
__u8
*
psc
;
irqreturn_t
psc_irq
(
int
,
void
*
);
/*
* Debugging dump, used in various places to see what's going on.
*/
...
...
@@ -115,26 +113,40 @@ void __init psc_init(void)
}
/*
*
Register the PSC interrupt dispatchers for autovector interrupts 3-6
.
*
PSC interrupt handler. It's a lot like the VIA interrupt handler
.
*/
void
__init
psc_register_interrupts
(
void
)
#ifdef CONFIG_GENERIC_HARDIRQS
static
void
psc_irq
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
if
(
request_irq
(
IRQ_AUTO_3
,
psc_irq
,
0
,
"psc3"
,
(
void
*
)
0x30
))
pr_err
(
"Couldn't register psc%d interrupt
\n
"
,
3
);
if
(
request_irq
(
IRQ_AUTO_4
,
psc_irq
,
0
,
"psc4"
,
(
void
*
)
0x40
))
pr_err
(
"Couldn't register psc%d interrupt
\n
"
,
4
);
if
(
request_irq
(
IRQ_AUTO_5
,
psc_irq
,
0
,
"psc5"
,
(
void
*
)
0x50
))
pr_err
(
"Couldn't register psc%d interrupt
\n
"
,
5
);
if
(
request_irq
(
IRQ_AUTO_6
,
psc_irq
,
0
,
"psc6"
,
(
void
*
)
0x60
))
pr_err
(
"Couldn't register psc%d interrupt
\n
"
,
6
);
}
unsigned
int
offset
=
(
unsigned
int
)
irq_desc_get_handler_data
(
desc
);
int
pIFR
=
pIFRbase
+
offset
;
int
pIER
=
pIERbase
+
offset
;
int
irq_num
;
unsigned
char
irq_bit
,
events
;
/*
* PSC interrupt handler. It's a lot like the VIA interrupt handler.
*/
#ifdef DEBUG_IRQS
printk
(
"psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X
\n
"
,
irq
,
(
int
)
psc_read_byte
(
pIFR
),
(
int
)
psc_read_byte
(
pIER
));
#endif
irqreturn_t
psc_irq
(
int
irq
,
void
*
dev_id
)
events
=
psc_read_byte
(
pIFR
)
&
psc_read_byte
(
pIER
)
&
0xF
;
if
(
!
events
)
return
;
irq_num
=
irq
<<
3
;
irq_bit
=
1
;
do
{
if
(
events
&
irq_bit
)
{
psc_write_byte
(
pIFR
,
irq_bit
);
generic_handle_irq
(
irq_num
);
}
irq_num
++
;
irq_bit
<<=
1
;
}
while
(
events
>=
irq_bit
);
}
#else
static
irqreturn_t
psc_irq
(
int
irq
,
void
*
dev_id
)
{
int
pIFR
=
pIFRbase
+
((
int
)
dev_id
);
int
pIER
=
pIERbase
+
((
int
)
dev_id
);
...
...
@@ -162,6 +174,34 @@ irqreturn_t psc_irq(int irq, void *dev_id)
}
while
(
events
>=
irq_bit
);
return
IRQ_HANDLED
;
}
#endif
/*
* Register the PSC interrupt dispatchers for autovector interrupts 3-6.
*/
void
__init
psc_register_interrupts
(
void
)
{
#ifdef CONFIG_GENERIC_HARDIRQS
irq_set_chained_handler
(
IRQ_AUTO_3
,
psc_irq
);
irq_set_handler_data
(
IRQ_AUTO_3
,
(
void
*
)
0x30
);
irq_set_chained_handler
(
IRQ_AUTO_4
,
psc_irq
);
irq_set_handler_data
(
IRQ_AUTO_4
,
(
void
*
)
0x40
);
irq_set_chained_handler
(
IRQ_AUTO_5
,
psc_irq
);
irq_set_handler_data
(
IRQ_AUTO_5
,
(
void
*
)
0x50
);
irq_set_chained_handler
(
IRQ_AUTO_6
,
psc_irq
);
irq_set_handler_data
(
IRQ_AUTO_6
,
(
void
*
)
0x60
);
#else
/* !CONFIG_GENERIC_HARDIRQS */
if
(
request_irq
(
IRQ_AUTO_3
,
psc_irq
,
0
,
"psc3"
,
(
void
*
)
0x30
))
pr_err
(
"Couldn't register psc%d interrupt
\n
"
,
3
);
if
(
request_irq
(
IRQ_AUTO_4
,
psc_irq
,
0
,
"psc4"
,
(
void
*
)
0x40
))
pr_err
(
"Couldn't register psc%d interrupt
\n
"
,
4
);
if
(
request_irq
(
IRQ_AUTO_5
,
psc_irq
,
0
,
"psc5"
,
(
void
*
)
0x50
))
pr_err
(
"Couldn't register psc%d interrupt
\n
"
,
5
);
if
(
request_irq
(
IRQ_AUTO_6
,
psc_irq
,
0
,
"psc6"
,
(
void
*
)
0x60
))
pr_err
(
"Couldn't register psc%d interrupt
\n
"
,
6
);
#endif
/* !CONFIG_GENERIC_HARDIRQS */
}
void
psc_irq_enable
(
int
irq
)
{
int
irq_src
=
IRQ_SRC
(
irq
);
...
...
arch/m68k/mac/via.c
View file @
9145db56
...
...
@@ -80,9 +80,6 @@ static int gIER,gIFR,gBufA,gBufB;
static
u8
nubus_disabled
;
void
via_debug_dump
(
void
);
irqreturn_t
via1_irq
(
int
,
void
*
);
irqreturn_t
via2_irq
(
int
,
void
*
);
irqreturn_t
via_nubus_irq
(
int
,
void
*
);
void
via_irq_enable
(
int
irq
);
void
via_irq_disable
(
int
irq
);
void
via_irq_clear
(
int
irq
);
...
...
@@ -288,29 +285,6 @@ void __init via_init_clock(irq_handler_t func)
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"timer"
);
}
/*
* Register the interrupt dispatchers for VIA or RBV machines only.
*/
void
__init
via_register_interrupts
(
void
)
{
if
(
via_alt_mapping
)
{
if
(
request_irq
(
IRQ_AUTO_1
,
via1_irq
,
0
,
"software"
,
(
void
*
)
via1
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"software"
);
if
(
request_irq
(
IRQ_AUTO_6
,
via1_irq
,
0
,
"via1"
,
(
void
*
)
via1
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"via1"
);
}
else
{
if
(
request_irq
(
IRQ_AUTO_1
,
via1_irq
,
0
,
"via1"
,
(
void
*
)
via1
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"via1"
);
}
if
(
request_irq
(
IRQ_AUTO_2
,
via2_irq
,
0
,
"via2"
,
(
void
*
)
via2
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"via2"
);
if
(
request_irq
(
IRQ_MAC_NUBUS
,
via_nubus_irq
,
0
,
"nubus"
,
(
void
*
)
via2
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"nubus"
);
}
/*
* Debugging dump, used in various places to see what's going on.
*/
...
...
@@ -443,6 +417,49 @@ void __init via_nubus_init(void)
* via6522.c :-), disable/pending masks added.
*/
#ifdef CONFIG_GENERIC_HARDIRQS
void
via1_irq
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
int
irq_num
;
unsigned
char
irq_bit
,
events
;
events
=
via1
[
vIFR
]
&
via1
[
vIER
]
&
0x7F
;
if
(
!
events
)
return
;
irq_num
=
VIA1_SOURCE_BASE
;
irq_bit
=
1
;
do
{
if
(
events
&
irq_bit
)
{
via1
[
vIFR
]
=
irq_bit
;
generic_handle_irq
(
irq_num
);
}
++
irq_num
;
irq_bit
<<=
1
;
}
while
(
events
>=
irq_bit
);
}
static
void
via2_irq
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
int
irq_num
;
unsigned
char
irq_bit
,
events
;
events
=
via2
[
gIFR
]
&
via2
[
gIER
]
&
0x7F
;
if
(
!
events
)
return
;
irq_num
=
VIA2_SOURCE_BASE
;
irq_bit
=
1
;
do
{
if
(
events
&
irq_bit
)
{
via2
[
gIFR
]
=
irq_bit
|
rbv_clear
;
generic_handle_irq
(
irq_num
);
}
++
irq_num
;
irq_bit
<<=
1
;
}
while
(
events
>=
irq_bit
);
}
#else
irqreturn_t
via1_irq
(
int
irq
,
void
*
dev_id
)
{
int
irq_num
;
...
...
@@ -486,12 +503,49 @@ irqreturn_t via2_irq(int irq, void *dev_id)
}
while
(
events
>=
irq_bit
);
return
IRQ_HANDLED
;
}
#endif
/*
* Dispatch Nubus interrupts. We are called as a secondary dispatch by the
* VIA2 dispatcher as a fast interrupt handler.
*/
#ifdef CONFIG_GENERIC_HARDIRQS
void
via_nubus_irq
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
int
slot_irq
;
unsigned
char
slot_bit
,
events
;
events
=
~
via2
[
gBufA
]
&
0x7F
;
if
(
rbv_present
)
events
&=
via2
[
rSIER
];
else
events
&=
~
via2
[
vDirA
];
if
(
!
events
)
return
;
do
{
slot_irq
=
IRQ_NUBUS_F
;
slot_bit
=
0x40
;
do
{
if
(
events
&
slot_bit
)
{
events
&=
~
slot_bit
;
generic_handle_irq
(
slot_irq
);
}
--
slot_irq
;
slot_bit
>>=
1
;
}
while
(
events
);
/* clear the CA1 interrupt and make certain there's no more. */
via2
[
gIFR
]
=
0x02
|
rbv_clear
;
events
=
~
via2
[
gBufA
]
&
0x7F
;
if
(
rbv_present
)
events
&=
via2
[
rSIER
];
else
events
&=
~
via2
[
vDirA
];
}
while
(
events
);
}
#else
irqreturn_t
via_nubus_irq
(
int
irq
,
void
*
dev_id
)
{
int
slot_irq
;
...
...
@@ -527,6 +581,43 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
}
while
(
events
);
return
IRQ_HANDLED
;
}
#endif
/*
* Register the interrupt dispatchers for VIA or RBV machines only.
*/
void
__init
via_register_interrupts
(
void
)
{
#ifdef CONFIG_GENERIC_HARDIRQS
if
(
via_alt_mapping
)
{
/* software interrupt */
irq_set_chained_handler
(
IRQ_AUTO_1
,
via1_irq
);
/* via1 interrupt */
irq_set_chained_handler
(
IRQ_AUTO_6
,
via1_irq
);
}
else
{
irq_set_chained_handler
(
IRQ_AUTO_1
,
via1_irq
);
}
irq_set_chained_handler
(
IRQ_AUTO_2
,
via2_irq
);
irq_set_chained_handler
(
IRQ_MAC_NUBUS
,
via_nubus_irq
);
#else
if
(
via_alt_mapping
)
{
if
(
request_irq
(
IRQ_AUTO_1
,
via1_irq
,
0
,
"software"
,
(
void
*
)
via1
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"software"
);
if
(
request_irq
(
IRQ_AUTO_6
,
via1_irq
,
0
,
"via1"
,
(
void
*
)
via1
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"via1"
);
}
else
{
if
(
request_irq
(
IRQ_AUTO_1
,
via1_irq
,
0
,
"via1"
,
(
void
*
)
via1
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"via1"
);
}
if
(
request_irq
(
IRQ_AUTO_2
,
via2_irq
,
0
,
"via2"
,
(
void
*
)
via2
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"via2"
);
if
(
request_irq
(
IRQ_MAC_NUBUS
,
via_nubus_irq
,
0
,
"nubus"
,
(
void
*
)
via2
))
pr_err
(
"Couldn't register %s interrupt
\n
"
,
"nubus"
);
#endif
}
void
via_irq_enable
(
int
irq
)
{
int
irq_src
=
IRQ_SRC
(
irq
);
...
...
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