Additional I/O interrupt cleanup; only wakeup a waiting CPU if enabled for I/O interrupts.

This commit is contained in:
dasdman
2013-08-24 14:32:12 -07:00
parent b5ec867780
commit 5648c5dc39
3 changed files with 68 additions and 26 deletions
+44 -9
View File
@@ -322,7 +322,11 @@ scsw_clear_ac_Nr (SCSW* scsw)
static INLINE void
scsw_clear_sc_Cs (SCSW* scsw)
{
scsw->flag3 &= ~SCSW3_SC_PEND;
scsw->flag3 &= ~(SCSW3_SC_ALERT |
SCSW3_SC_INTER |
SCSW3_SC_PRI |
SCSW3_SC_SEC |
SCSW3_SC_PEND);
}
@@ -3775,13 +3779,13 @@ int rc; /* Return code */
/* Initialize the subchannel status word */
memset (&dev->scsw, 0, sizeof(SCSW));
dev->scsw.flag0 = (orb->flag4 & SCSW0_KEY); /*@IWZ*/
if (orb->flag4 & ORB4_S) dev->scsw.flag0 |= SCSW0_S; /*@IWZ*/
if (orb->flag5 & ORB5_F) dev->scsw.flag1 |= SCSW1_F; /*@IWZ*/
if (orb->flag5 & ORB5_P) dev->scsw.flag1 |= SCSW1_P; /*@IWZ*/
if (orb->flag5 & ORB5_I) dev->scsw.flag1 |= SCSW1_I; /*@IWZ*/
if (orb->flag5 & ORB5_A) dev->scsw.flag1 |= SCSW1_A; /*@IWZ*/
if (orb->flag5 & ORB5_U) dev->scsw.flag1 |= SCSW1_U; /*@IWZ*/
dev->scsw.flag0 = (orb->flag4 & (SCSW0_KEY |
SCSW0_S));
dev->scsw.flag1 = (orb->flag5 & (SCSW1_F |
SCSW1_P |
SCSW1_I |
SCSW1_A |
SCSW1_U));
/* Set the device busy indicator */
set_subchannel_busy(dev);
@@ -5538,7 +5542,38 @@ retry:
}
/* See if another CPU can take this interrupt */
WAKEUP_CPU_MASK (sysblk.waiting_mask);
{
REGS *regs;
CPU_BITMAP mask = sysblk.waiting_mask;
CPU_BITMAP wake;
int i;
/* If any CPUs are waiting, isolate to subgroup enabled for
* I/O interrupts.
*/
if (mask)
{
wake = mask;
/* Turn off wake mask bits for waiting CPUs that aren't
* enabled for I/O interrupts.
*/
for (i = 0; mask; mask >>= 1, ++i)
{
if (mask & 1)
{
regs = sysblk.regs[i];
if (!OPEN_IC_IOPENDING(regs))
wake ^= regs->cpubit;
}
}
/* Wakeup the LRU waiting CPU enabled for I/O
* interrupts.
*/
WAKEUP_CPU_MASK(wake);
}
}
} /* end for(io) */
+24 -16
View File
@@ -5,7 +5,7 @@
Interrupts_State & Interrupts_Mask bits definition (Initial_Mask=800E)
Machine check, PER and external interrupt subclass bit positions
are fixed by the architecture and cannot be changed
Floating interrupts are made pending to all CPUs, and are
Floating interrupts are made pending to all CPUs, and are
recorded in the sysblk structure, CPU specific interrupts
are recorded in the regs structure.
hi0m mmmm pppp p00p xxxx xxxx xxxx h0hs : type U32
@@ -25,22 +25,22 @@
|| | |||| |||| | | |||| ||+-------------> '1' : SERVSIG
|| | |||| |||| | | |||| |+--------------> '1' : PTIMER
|| | |||| |||| | | |||| +---------------> '1' : CLKC
|| | |||| |||| | | ||||
|| | |||| |||| | | ||||
|| | |||| |||| | | |||+-----------------> '1' : TODSYNC
|| | |||| |||| | | ||+------------------> '1' : EXTCALL
|| | |||| |||| | | |+-------------------> '1' : EMERSIG
|| | |||| |||| | | +--------------------> '1' : MALFALT
|| | |||| |||| | |
|| | |||| |||| | +----------------------> '1' : PER IFNUL
|| | |||| |||| |
|| | |||| |||| |
|| | |||| |||| |
|| | |||| |||| |
|| | |||| |||| +-------------------------> '1' : PER STURA
|| | |||| ||||
|| | |||| ||||
|| | |||| |||+---------------------------> '1' : PER GRA
|| | |||| ||+----------------------------> '1' : PER SA
|| | |||| |+-----------------------------> '1' : PER IF
|| | |||| +------------------------------> '1' : PER SB
|| | ||||
|| | ||||
|| | |||+--------------------------------> '1' : WARNING
|| | ||+---------------------------------> '1' : XDMGRPT
|| | |+----------------------------------> '1' : DGRDRPT
@@ -138,7 +138,7 @@
/* External interrupt subclasses */
/*
/*
* Adds ECPS:VM Vtimer which has no individual
* subclass mask in CR0
*/
@@ -311,19 +311,27 @@
#define ON_IC_IOPENDING \
do { \
int i; CPU_BITMAP mask; \
if ( !(sysblk.ints_state & BIT(IC_IO)) ) { \
REGS *regs; \
CPU_BITMAP mask = sysblk.started_mask; \
CPU_BITMAP wake; \
int i; \
if ( !(sysblk.ints_state & BIT(IC_IO)) ) \
{ \
sysblk.ints_state |= BIT(IC_IO); \
mask = sysblk.started_mask; \
for (i = 0; mask; i++) { \
if (mask & 1) { \
if ( sysblk.regs[i]->ints_mask & BIT(IC_IO) ) \
sysblk.regs[i]->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_IO); \
wake = mask; \
for (i = 0; mask; mask >>= 1, ++i) \
{ \
if (mask & 1) \
{ \
regs = sysblk.regs[i]; \
if ( regs->ints_mask & BIT(IC_IO) ) \
regs->ints_state |= BIT(IC_INTERRUPT) | BIT(IC_IO); \
else \
sysblk.regs[i]->ints_state |= BIT(IC_IO); \
regs->ints_state |= BIT(IC_IO), \
wake ^= regs->cpubit; \
} \
mask >>= 1; \
} \
WAKEUP_CPU_MASK(wake); \
} \
} while (0)
-1
View File
@@ -574,7 +574,6 @@ typedef int CMPFUNC(const void*, const void*);
OFF_IC_IOPENDING; \
else { \
ON_IC_IOPENDING; \
WAKEUP_CPU_MASK (sysblk.waiting_mask); \
} \
} while (0)