Migrate from setting a CARD_OK flag in a shared word, to setting its

own entry in the softc.  This should allow more of cbb_pci_intr() to
migrate to a new cbb_pci_filt() so that we don't have to run cbb's ISR
in almost every case we get an interrupt.  We can't just move
cbb_pci_intr into cbb_pci_filt because it does things that aren't safe
to do from a fast interrupt handler, err I mean from a filter.  This is
an important first step.

# I wonder if I need to make cardok volatile or not.
This commit is contained in:
imp 2007-06-04 05:59:44 +00:00
parent 83d530c093
commit 64652f7b07
3 changed files with 21 additions and 32 deletions

View File

@ -389,7 +389,7 @@ cbb_setup_intr(device_t dev, device_t child, struct resource *irq,
return (err);
}
cbb_enable_func_intr(sc);
sc->flags |= CBB_CARD_OK;
sc->cardok = 1;
return 0;
}
@ -575,7 +575,7 @@ cbb_insert(struct cbb_softc *sc)
static void
cbb_removal(struct cbb_softc *sc)
{
sc->flags &= ~CBB_CARD_OK;
sc->cardok = 0;
if (sc->flags & CBB_16BIT_CARD) {
exca_removal(&sc->exca[0]);
} else {
@ -589,26 +589,6 @@ cbb_removal(struct cbb_softc *sc)
/* Interrupt Handler */
/************************************************************************/
/*
* Since we touch hardware in the worst case, we don't need to use atomic ops
* on the CARD_OK tests. They would save us a trip to the hardware if CARD_OK
* was recently cleared and the caches haven't updated yet. However, an
* atomic op costs between 100-200 CPU cycles. On a 3GHz machine, this is
* about 33-66ns, whereas a trip the the hardware is about that. On slower
* machines, the cost is even higher, so the trip to the hardware is cheaper
* and achieves the same ends that a fully locked operation would give us.
*
* This is a separate routine because we'd have to use locking and/or other
* synchronization in cbb_intr to do this there. That would be even more
* expensive.
*
* I need to investigate what this means for a SMP machine with multiple CPUs
* servicing the ISR when an eject happens. In the case of a dirty eject, CD
* glitches and we might read 'card present' from the hardware due to this
* jitter. If we assumed that cbb_intr() ran before cbb_func_intr(), we could
* just check the SOCKET_MASK register and if CD changes were clear there,
* then we'd know the card was gone.
*/
static int
cbb_func_filt(void *arg)
{
@ -618,10 +598,10 @@ cbb_func_filt(void *arg)
/*
* Make sure that the card is really there.
*/
if ((sc->flags & CBB_CARD_OK) == 0)
if (!sc->cardok)
return (FILTER_STRAY);
if (!CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE))) {
sc->flags &= ~CBB_CARD_OK;
sc->cardok = 0;
return (FILTER_HANDLED);
}
@ -652,10 +632,10 @@ cbb_func_intr(void *arg)
* called if their filter said they needed to be called.
*/
if (ih->filt == NULL) {
if ((sc->flags & CBB_CARD_OK) == 0)
if (!sc->cardok)
return;
if (!CBB_CARD_PRESENT(cbb_get(sc, CBB_SOCKET_STATE))) {
sc->flags &= ~CBB_CARD_OK;
sc->cardok = 0;
return;
}
}
@ -1520,7 +1500,7 @@ cbb_suspend(device_t self)
if (error != 0)
return (error);
cbb_set(sc, CBB_SOCKET_MASK, 0); /* Quiet hardware */
sc->flags &= ~CBB_CARD_OK; /* Card is bogus now */
sc->cardok = 0; /* Card is bogus now */
return (0);
}
@ -1570,6 +1550,5 @@ cbb_child_present(device_t self)
uint32_t sockstate;
sockstate = cbb_get(sc, CBB_SOCKET_STATE);
return (CBB_CARD_PRESENT(sockstate) &&
(sc->flags & CBB_CARD_OK) == CBB_CARD_OK);
return (CBB_CARD_PRESENT(sockstate) && sc->cardok);
}

View File

@ -352,6 +352,16 @@ cbb_pci_attach(device_t brdev)
CTLFLAG_RD, &sc->secbus, 0, "Secondary bus number");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "subbus",
CTLFLAG_RD, &sc->subbus, 0, "Subordinate bus number");
#if 0
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "memory",
CTLFLAG_RD, &sc->subbus, 0, "Memory window open");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "premem",
CTLFLAG_RD, &sc->subbus, 0, "Prefetch memroy window open");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "io1",
CTLFLAG_RD, &sc->subbus, 0, "io range 1 open");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "io2",
CTLFLAG_RD, &sc->subbus, 0, "io range 2 open");
#endif
/*
* This is a gross hack. We should be scanning the entire pci
@ -695,7 +705,7 @@ cbb_pci_intr(void *arg)
/*
* If anything has happened to the socket, we assume that
* the card is no longer OK, and we shouldn't call its
* ISR. We set CARD_OK as soon as we've attached the
* ISR. We set cardok as soon as we've attached the
* card. This helps in a noisy eject, which happens
* all too often when users are ejecting their PC Cards.
*
@ -708,7 +718,7 @@ cbb_pci_intr(void *arg)
if (sockevent & CBB_SOCKET_EVENT_CD) {
mtx_lock(&sc->mtx);
cbb_clrb(sc, CBB_SOCKET_MASK, CBB_SOCKET_MASK_CD);
sc->flags &= ~CBB_CARD_OK;
sc->cardok = 0;
cbb_disable_func_intr(sc);
cv_signal(&sc->cv);
mtx_unlock(&sc->mtx);

View File

@ -68,8 +68,8 @@ struct cbb_softc {
struct mtx mtx;
struct cv cv;
struct cv powercv;
int cardok;
u_int32_t flags;
#define CBB_CARD_OK 0x08000000
#define CBB_16BIT_CARD 0x20000000
#define CBB_KTHREAD_RUNNING 0x40000000
#define CBB_KTHREAD_DONE 0x80000000