diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2008-11-24 15:50:45 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2008-11-24 15:50:45 +0000 |
commit | 12d0b513950a3e41089b1128b472689c689d4175 (patch) | |
tree | faf8ef049f3ed448c1e95168fa91ad04a86af658 /sys/dev/cardbus/cardslot.c | |
parent | 22c7ad1354a2e9091ea23248b0fde52f6d9f37c3 (diff) |
use workq instead of crafting our own kthread, since the tasks being done
are fairly small. tested by a few, and kettenis says he will test it sooner
if it is commited...
Diffstat (limited to 'sys/dev/cardbus/cardslot.c')
-rw-r--r-- | sys/dev/cardbus/cardslot.c | 351 |
1 files changed, 162 insertions, 189 deletions
diff --git a/sys/dev/cardbus/cardslot.c b/sys/dev/cardbus/cardslot.c index 101f3671223..38f57e9ec1a 100644 --- a/sys/dev/cardbus/cardslot.c +++ b/sys/dev/cardbus/cardslot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cardslot.c,v 1.10 2007/12/21 17:36:52 kettenis Exp $ */ +/* $OpenBSD: cardslot.c,v 1.11 2008/11/24 15:50:44 deraadt Exp $ */ /* $NetBSD: cardslot.c,v 1.9 2000/03/22 09:35:06 haya Exp $ */ /* @@ -40,6 +40,8 @@ #include <sys/kernel.h> #include <sys/syslog.h> #include <sys/kthread.h> +#include <sys/pool.h> +#include <sys/workq.h> #include <machine/bus.h> @@ -64,8 +66,7 @@ STATIC void cardslotattach(struct device *, struct device *, void *); STATIC int cardslotmatch(struct device *, void *, void *); -STATIC void create_slot_manager(void *); -STATIC void cardslot_event_thread(void *arg); +STATIC void cardslot_event(void *arg1, void *arg2); STATIC int cardslot_cb_print(void *aux, const char *pcic); STATIC int cardslot_16_print(void *, const char *); @@ -79,6 +80,8 @@ struct cfdriver cardslot_cd = { NULL, "cardslot", DV_DULL }; +struct pool cardsloteventpool; + STATIC int cardslotmatch(struct device *parent, void *match, void *aux) { @@ -104,11 +107,14 @@ cardslotattach(struct device *parent, struct device *self, void *aux) struct cardbus_softc *csc = NULL; struct pcmcia_softc *psc = NULL; + if (cardsloteventpool.pr_align == 0) + pool_init(&cardsloteventpool, sizeof(cardslot_event), 0, 0, 0, + "cardslot", NULL); + sc->sc_slot = sc->sc_dev.dv_unit; sc->sc_cb_softc = NULL; sc->sc_16_softc = NULL; SIMPLEQ_INIT(&sc->sc_events); - sc->sc_th_enable = 0; printf(" slot %d flags %x\n", sc->sc_slot, sc->sc_dev.dv_cfdata->cf_flags); @@ -137,9 +143,6 @@ cardslotattach(struct device *parent, struct device *self, void *aux) } } - if (csc != NULL || psc != NULL) - kthread_create_deferred(create_slot_manager, (void *)sc); - if (csc && (csc->sc_cf->cardbus_ctrl)(csc->sc_cc, CARDBUS_CD)) { DPRINTF(("cardslotattach: CardBus card found\n")); /* attach deferred */ @@ -187,21 +190,6 @@ cardslot_16_print(void *arg, const char *pnp) return (UNCONF); } -STATIC void -create_slot_manager(void *arg) -{ - struct cardslot_softc *sc = (struct cardslot_softc *)arg; - - sc->sc_th_enable = 1; - - if (kthread_create(cardslot_event_thread, sc, &sc->sc_event_thread, - "%s", sc->sc_dev.dv_xname)) { - printf("%s: unable to create event thread for slot %d\n", - sc->sc_dev.dv_xname, sc->sc_slot); - panic("create_slot_manager"); - } -} - /* * void cardslot_event_throw(struct cardslot_softc *sc, int ev) * @@ -212,6 +200,7 @@ void cardslot_event_throw(struct cardslot_softc *sc, int ev) { struct cardslot_event *ce; + int s; DPRINTF(("cardslot_event_throw: an event %s comes\n", ev == CARDSLOT_EVENT_INSERTION_CB ? "CardBus Card inserted" : @@ -219,202 +208,186 @@ cardslot_event_throw(struct cardslot_softc *sc, int ev) ev == CARDSLOT_EVENT_REMOVAL_CB ? "CardBus Card removed" : ev == CARDSLOT_EVENT_REMOVAL_16 ? "16-bit Card removed" : "???")); - if ((ce = (struct cardslot_event *)malloc(sizeof(struct cardslot_event), - M_TEMP, M_NOWAIT)) == NULL) { - panic("cardslot_event"); - } - + ce = pool_get(&cardsloteventpool, PR_NOWAIT); + if (ce == NULL) + return; ce->ce_type = ev; - { - int s = spltty(); - SIMPLEQ_INSERT_TAIL(&sc->sc_events, ce, ce_q); - splx(s); - } + s = spltty(); + SIMPLEQ_INSERT_TAIL(&sc->sc_events, ce, ce_q); + splx(s); - wakeup(&sc->sc_events); + workq_add_task(NULL, 0, cardslot_event, sc, NULL); } /* - * STATIC void cardslot_event_thread(void *arg) + * STATIC void cardslot_event(void *arg) * * This function is the main routine handing cardslot events such as * insertions and removals. * */ STATIC void -cardslot_event_thread(void *arg) +cardslot_event(void *arg1, void *arg2) { - struct cardslot_softc *sc = arg; + struct cardslot_softc *sc = arg1; struct cardslot_event *ce; - int s; - static int antonym_ev[4] = { - CARDSLOT_EVENT_REMOVAL_16, CARDSLOT_EVENT_INSERTION_16, - CARDSLOT_EVENT_REMOVAL_CB, CARDSLOT_EVENT_INSERTION_CB - }; - - while (sc->sc_th_enable) { - s = spltty(); - if ((ce = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) { - splx(s); - (void) tsleep(&sc->sc_events, PWAIT, "cardslotev", 0); - continue; - } - SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q); - splx(s); + int s, ev; - if (IS_CARDSLOT_INSERT_REMOVE_EV(ce->ce_type)) { - /* Chattering suppression */ - s = spltty(); - while (1) { - struct cardslot_event *ce1, *ce2; - - if ((ce1 = SIMPLEQ_FIRST(&sc->sc_events)) == - NULL) - break; - if (ce1->ce_type != antonym_ev[ce->ce_type]) - break; - if ((ce2 = SIMPLEQ_NEXT(ce1, ce_q)) == NULL) - break; - if (ce2->ce_type == ce->ce_type) { - SIMPLEQ_REMOVE_HEAD(&sc->sc_events, - ce_q); - free(ce1, M_TEMP); - SIMPLEQ_REMOVE_HEAD(&sc->sc_events, - ce_q); - free(ce2, M_TEMP); - } + s = spltty(); + if ((ce = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) { + splx(s); + return; + } + SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q); + + if (IS_CARDSLOT_INSERT_REMOVE_EV(ce->ce_type)) { + /* Chattering suppression */ + static int antonym_ev[4] = { + CARDSLOT_EVENT_REMOVAL_16, + CARDSLOT_EVENT_INSERTION_16, + CARDSLOT_EVENT_REMOVAL_CB, + CARDSLOT_EVENT_INSERTION_CB + }; + + while (1) { + struct cardslot_event *ce1, *ce2; + + if ((ce1 = SIMPLEQ_FIRST(&sc->sc_events)) == + NULL) + break; + if (ce1->ce_type != antonym_ev[ce->ce_type]) + break; + if ((ce2 = SIMPLEQ_NEXT(ce1, ce_q)) == NULL) + break; + if (ce2->ce_type == ce->ce_type) { + SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q); + pool_put(&cardsloteventpool, ce1); + SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q); + pool_put(&cardsloteventpool, ce2); } - splx(s); } - - switch (ce->ce_type) { - case CARDSLOT_EVENT_INSERTION_CB: - if ((CARDSLOT_CARDTYPE(sc->sc_status) == - CARDSLOT_STATUS_CARD_CB) || - (CARDSLOT_CARDTYPE(sc->sc_status) == - CARDSLOT_STATUS_CARD_16)) { - if (CARDSLOT_WORK(sc->sc_status) == - CARDSLOT_STATUS_WORKING) { - /* A card has already been inserted - * and works. - */ - break; - } + } + splx(s); + + ev = ce->ce_type; + pool_put(&cardsloteventpool, ce); + + switch (ev) { + case CARDSLOT_EVENT_INSERTION_CB: + if ((CARDSLOT_CARDTYPE(sc->sc_status) == + CARDSLOT_STATUS_CARD_CB) || + (CARDSLOT_CARDTYPE(sc->sc_status) == + CARDSLOT_STATUS_CARD_16)) { + if (CARDSLOT_WORK(sc->sc_status) == + CARDSLOT_STATUS_WORKING) { + /* A card has already been inserted + * and works. + */ + break; } + } - if (sc->sc_cb_softc) { - CARDSLOT_SET_CARDTYPE(sc->sc_status, - CARDSLOT_STATUS_CARD_CB); - if (cardbus_attach_card(sc->sc_cb_softc) > 0) { - /* At least one function works */ - CARDSLOT_SET_WORK(sc->sc_status, - CARDSLOT_STATUS_WORKING); - } else { - /* No functions work or this card is - * not known - */ - CARDSLOT_SET_WORK(sc->sc_status, - CARDSLOT_STATUS_NOTWORK); - } + if (sc->sc_cb_softc) { + CARDSLOT_SET_CARDTYPE(sc->sc_status, + CARDSLOT_STATUS_CARD_CB); + if (cardbus_attach_card(sc->sc_cb_softc) > 0) { + /* At least one function works */ + CARDSLOT_SET_WORK(sc->sc_status, + CARDSLOT_STATUS_WORKING); } else { - printf("%s: CardBus support disabled\n", - sc->sc_dev.dv_xname); + /* No functions work or this card is + * not known + */ + CARDSLOT_SET_WORK(sc->sc_status, + CARDSLOT_STATUS_NOTWORK); } - - break; - - case CARDSLOT_EVENT_INSERTION_16: - if ((CARDSLOT_CARDTYPE(sc->sc_status) == - CARDSLOT_STATUS_CARD_CB) || - (CARDSLOT_CARDTYPE(sc->sc_status) == - CARDSLOT_STATUS_CARD_16)) { - if (CARDSLOT_WORK(sc->sc_status) == - CARDSLOT_STATUS_WORKING) { - /* A card has already been inserted - * and works. - */ - break; - } + } else { + printf("%s: CardBus support disabled\n", + sc->sc_dev.dv_xname); + } + break; + + case CARDSLOT_EVENT_INSERTION_16: + if ((CARDSLOT_CARDTYPE(sc->sc_status) == + CARDSLOT_STATUS_CARD_CB) || + (CARDSLOT_CARDTYPE(sc->sc_status) == + CARDSLOT_STATUS_CARD_16)) { + if (CARDSLOT_WORK(sc->sc_status) == + CARDSLOT_STATUS_WORKING) { + /* A card has already been inserted + * and works. + */ + break; } - if (sc->sc_16_softc) { - CARDSLOT_SET_CARDTYPE(sc->sc_status, - CARDSLOT_STATUS_CARD_16); - if (pcmcia_card_attach( - (struct device *)sc->sc_16_softc)) { - /* Do not attach */ - CARDSLOT_SET_WORK(sc->sc_status, - CARDSLOT_STATUS_NOTWORK); - } else { - /* working */ - CARDSLOT_SET_WORK(sc->sc_status, - CARDSLOT_STATUS_WORKING); - } + } + if (sc->sc_16_softc) { + CARDSLOT_SET_CARDTYPE(sc->sc_status, + CARDSLOT_STATUS_CARD_16); + if (pcmcia_card_attach( + (struct device *)sc->sc_16_softc)) { + /* Do not attach */ + CARDSLOT_SET_WORK(sc->sc_status, + CARDSLOT_STATUS_NOTWORK); } else { - panic("no 16-bit pcmcia on %s", - sc->sc_dev.dv_xname); + /* working */ + CARDSLOT_SET_WORK(sc->sc_status, + CARDSLOT_STATUS_WORKING); } - - break; - - case CARDSLOT_EVENT_REMOVAL_CB: - if (CARDSLOT_CARDTYPE(sc->sc_status) == - CARDSLOT_STATUS_CARD_CB) { - /* CardBus card has not been inserted. */ - if (CARDSLOT_WORK(sc->sc_status) == - CARDSLOT_STATUS_WORKING) { - cardbus_detach_card(sc->sc_cb_softc); - CARDSLOT_SET_WORK(sc->sc_status, - CARDSLOT_STATUS_NOTWORK); - CARDSLOT_SET_WORK(sc->sc_status, - CARDSLOT_STATUS_CARD_NONE); - } - CARDSLOT_SET_CARDTYPE(sc->sc_status, - CARDSLOT_STATUS_CARD_NONE); - } else if (CARDSLOT_CARDTYPE(sc->sc_status) != - CARDSLOT_STATUS_CARD_16) { - /* Unknown card... */ - CARDSLOT_SET_CARDTYPE(sc->sc_status, + } else { + panic("no 16-bit pcmcia on %s", + sc->sc_dev.dv_xname); + } + break; + + case CARDSLOT_EVENT_REMOVAL_CB: + if (CARDSLOT_CARDTYPE(sc->sc_status) == + CARDSLOT_STATUS_CARD_CB) { + /* CardBus card has not been inserted. */ + if (CARDSLOT_WORK(sc->sc_status) == + CARDSLOT_STATUS_WORKING) { + cardbus_detach_card(sc->sc_cb_softc); + CARDSLOT_SET_WORK(sc->sc_status, + CARDSLOT_STATUS_NOTWORK); + CARDSLOT_SET_WORK(sc->sc_status, CARDSLOT_STATUS_CARD_NONE); } - CARDSLOT_SET_WORK(sc->sc_status, - CARDSLOT_STATUS_NOTWORK); - break; - - case CARDSLOT_EVENT_REMOVAL_16: - DPRINTF(("%s: removal event\n", sc->sc_dev.dv_xname)); - if (CARDSLOT_CARDTYPE(sc->sc_status) != - CARDSLOT_STATUS_CARD_16) { - /* 16-bit card has not been inserted. */ - break; - } - if ((sc->sc_16_softc != NULL) && - (CARDSLOT_WORK(sc->sc_status) == - CARDSLOT_STATUS_WORKING)) { - struct pcmcia_softc *psc = sc->sc_16_softc; - - pcmcia_card_deactivate((struct device *)psc); - pcmcia_chip_socket_disable(psc->pct, psc->pch); - pcmcia_card_detach((struct device *)psc, - DETACH_FORCE); - } CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_NONE); - CARDSLOT_SET_WORK(sc->sc_status, - CARDSLOT_STATUS_NOTWORK); + } else if (CARDSLOT_CARDTYPE(sc->sc_status) != + CARDSLOT_STATUS_CARD_16) { + /* Unknown card... */ + CARDSLOT_SET_CARDTYPE(sc->sc_status, + CARDSLOT_STATUS_CARD_NONE); + } + CARDSLOT_SET_WORK(sc->sc_status, + CARDSLOT_STATUS_NOTWORK); + break; + + case CARDSLOT_EVENT_REMOVAL_16: + DPRINTF(("%s: removal event\n", sc->sc_dev.dv_xname)); + if (CARDSLOT_CARDTYPE(sc->sc_status) != + CARDSLOT_STATUS_CARD_16) { + /* 16-bit card has not been inserted. */ break; - - default: - panic("cardslot_event_thread: unknown event %d", - ce->ce_type); } - free(ce, M_TEMP); + if ((sc->sc_16_softc != NULL) && + (CARDSLOT_WORK(sc->sc_status) == + CARDSLOT_STATUS_WORKING)) { + struct pcmcia_softc *psc = sc->sc_16_softc; + + pcmcia_card_deactivate((struct device *)psc); + pcmcia_chip_socket_disable(psc->pct, psc->pch); + pcmcia_card_detach((struct device *)psc, + DETACH_FORCE); + } + CARDSLOT_SET_CARDTYPE(sc->sc_status, + CARDSLOT_STATUS_CARD_NONE); + CARDSLOT_SET_WORK(sc->sc_status, + CARDSLOT_STATUS_NOTWORK); + break; + + default: + panic("cardslot_event_thread: unknown event %d", ev); } - - sc->sc_event_thread = NULL; - - /* In case the parent device is waiting for us to exit. */ - wakeup(sc); - - kthread_exit(0); } |