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:
parent
83d530c093
commit
64652f7b07
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user