/* * Called from the kernel proper when it can create threads. */ void usbf_create_thread(void *arg) { struct usbf_softc *sc = arg; if (kthread_create(usbf_task_thread, sc, &sc->sc_proc, "%s", DEVNAME(sc)) != 0) { printf("%s: can't create task thread\n", DEVNAME(sc)); return; } config_pending_decr(); }
static void ld_sdmmc_doattach(void *arg) { struct ld_sdmmc_softc *sc = (struct ld_sdmmc_softc *)arg; struct ld_softc *ld = &sc->sc_ld; struct sdmmc_softc *ssc = device_private(device_parent(ld->sc_dv)); ldattach(ld); aprint_normal_dev(ld->sc_dv, "%d-bit width, bus clock", sc->sc_sf->width); if ((ssc->sc_busclk / 1000) != 0) aprint_normal(" %u.%03u MHz\n", ssc->sc_busclk / 1000, ssc->sc_busclk % 1000); else aprint_normal(" %u KHz\n", ssc->sc_busclk % 1000); config_pending_decr(ld->sc_dv); kthread_exit(0); }
void pxapcic_create_event_thread(void *arg) { struct pxapcic_socket *sock = arg; struct pxapcic_softc *sc = sock->sc; u_int cs; /* If there's a card there, attach it. */ cs = sock->pcictag->read(sock, PXAPCIC_CARD_STATUS); if (cs == PXAPCIC_CARD_VALID) pxapcic_attach_card(sock); if (kthread_create(pxapcic_event_thread, sock, &sock->event_thread, sc->sc_dev.dv_xname, sock->socket ? "1" : "0")) { printf("%s: unable to create event thread for %s\n", sc->sc_dev.dv_xname, sock->socket ? "1" : "0"); } #ifdef DO_CONFIG_PENDING config_pending_decr(); #endif }
void pcic_event_thread(void *arg) { struct pcic_handle *h = arg; struct pcic_event *pe; int s, first = 1; struct pcic_softc *sc = device_private(h->ph_parent); while (h->shutdown == 0) { /* * Serialize event processing on the PCIC. We may * sleep while we hold this lock. */ mutex_enter(&sc->sc_pcic_lock); s = splhigh(); if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) { splx(s); if (first) { first = 0; config_pending_decr(sc->dev); } /* * No events to process; release the PCIC lock. */ (void) mutex_exit(&sc->sc_pcic_lock); (void) tsleep(&h->events, PWAIT, "pcicev", 0); continue; } else { splx(s); /* sleep .25s to be enqueued chatterling interrupts */ (void) tsleep((void *)pcic_event_thread, PWAIT, "pcicss", hz / 4); } s = splhigh(); SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); splx(s); switch (pe->pe_type) { case PCIC_EVENT_INSERTION: s = splhigh(); for (;;) { struct pcic_event *pe1, *pe2; if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL) break; if (pe1->pe_type != PCIC_EVENT_REMOVAL) break; if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL) break; if (pe2->pe_type == PCIC_EVENT_INSERTION) { SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); free(pe1, M_TEMP); SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); free(pe2, M_TEMP); } } splx(s); DPRINTF(("%s: insertion event\n", device_xname(h->ph_parent))); pcic_attach_card(h); break; case PCIC_EVENT_REMOVAL: s = splhigh(); for (;;) { struct pcic_event *pe1, *pe2; if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL) break; if (pe1->pe_type != PCIC_EVENT_INSERTION) break; if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL) break; if (pe2->pe_type == PCIC_EVENT_REMOVAL) { SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); free(pe1, M_TEMP); SIMPLEQ_REMOVE_HEAD(&h->events, pe_q); free(pe2, M_TEMP); } } splx(s); DPRINTF(("%s: removal event\n", device_xname(h->ph_parent))); pcic_detach_card(h, DETACH_FORCE); break; default: panic("pcic_event_thread: unknown event %d", pe->pe_type); } free(pe, M_TEMP); mutex_exit(&sc->sc_pcic_lock); } h->event_thread = NULL; /* In case parent is waiting for us to exit. */ wakeup(sc); kthread_exit(0); }
/* * atabus_configthread: finish attach of atabus's childrens, in a separate * kernel thread. */ static void atabusconfig_thread(void *arg) { struct atabus_softc *atabus_sc = arg; struct ata_channel *chp = atabus_sc->sc_chan; struct atac_softc *atac = chp->ch_atac; struct atabus_initq *atabus_initq = NULL; int i, s; /* XXX seems wrong */ mutex_enter(&atabus_qlock); atabus_initq = TAILQ_FIRST(&atabus_initq_head); KASSERT(atabus_initq->atabus_sc == atabus_sc); mutex_exit(&atabus_qlock); /* * First look for a port multiplier */ if (chp->ch_ndrives == PMP_MAX_DRIVES && chp->ch_drive[PMP_PORT_CTL].drive_type == ATA_DRIVET_PM) { #if NSATA_PMP > 0 satapmp_attach(chp); #else aprint_error_dev(atabus_sc->sc_dev, "SATA port multiplier not supported\n"); /* no problems going on, all drives are ATA_DRIVET_NONE */ #endif } /* * Attach an ATAPI bus, if needed. */ KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL); for (i = 0; i < chp->ch_ndrives && chp->atapibus == NULL; i++) { if (chp->ch_drive[i].drive_type == ATA_DRIVET_ATAPI) { #if NATAPIBUS > 0 (*atac->atac_atapibus_attach)(atabus_sc); #else /* * Fake the autoconfig "not configured" message */ aprint_normal("atapibus at %s not configured\n", device_xname(atac->atac_dev)); chp->atapibus = NULL; s = splbio(); for (i = 0; i < chp->ch_ndrives; i++) { if (chp->ch_drive[i].drive_type == ATA_DRIVET_ATAPI) chp->ch_drive[i].drive_type = ATA_DRIVET_NONE; } splx(s); #endif break; } } for (i = 0; i < chp->ch_ndrives; i++) { struct ata_device adev; if (chp->ch_drive[i].drive_type != ATA_DRIVET_ATA && chp->ch_drive[i].drive_type != ATA_DRIVET_OLD) { continue; } if (chp->ch_drive[i].drv_softc != NULL) continue; memset(&adev, 0, sizeof(struct ata_device)); adev.adev_bustype = atac->atac_bustype_ata; adev.adev_channel = chp->ch_channel; adev.adev_openings = 1; adev.adev_drv_data = &chp->ch_drive[i]; chp->ch_drive[i].drv_softc = config_found_ia(atabus_sc->sc_dev, "ata_hl", &adev, ataprint); if (chp->ch_drive[i].drv_softc != NULL) { ata_probe_caps(&chp->ch_drive[i]); } else { s = splbio(); chp->ch_drive[i].drive_type = ATA_DRIVET_NONE; splx(s); } } /* now that we know the drives, the controller can set its modes */ if (atac->atac_set_modes) { (*atac->atac_set_modes)(chp); ata_print_modes(chp); } #if NATARAID > 0 if (atac->atac_cap & ATAC_CAP_RAID) { for (i = 0; i < chp->ch_ndrives; i++) { if (chp->ch_drive[i].drive_type == ATA_DRIVET_ATA) { ata_raid_check_component( chp->ch_drive[i].drv_softc); } } } #endif /* NATARAID > 0 */ /* * reset drive_flags for unattached devices, reset state for attached * ones */ s = splbio(); for (i = 0; i < chp->ch_ndrives; i++) { if (chp->ch_drive[i].drive_type == ATA_DRIVET_PM) continue; if (chp->ch_drive[i].drv_softc == NULL) { chp->ch_drive[i].drive_flags = 0; chp->ch_drive[i].drive_type = ATA_DRIVET_NONE; } else chp->ch_drive[i].state = 0; } splx(s); mutex_enter(&atabus_qlock); TAILQ_REMOVE(&atabus_initq_head, atabus_initq, atabus_initq); cv_broadcast(&atabus_qcv); mutex_exit(&atabus_qlock); free(atabus_initq, M_DEVBUF); ata_delref(chp); config_pending_decr(atac->atac_dev); kthread_exit(0); }
static void atabusconfig(struct atabus_softc *atabus_sc) { struct ata_channel *chp = atabus_sc->sc_chan; struct atac_softc *atac = chp->ch_atac; struct atabus_initq *atabus_initq = NULL; int i, s, error; /* we are in the atabus's thread context */ s = splbio(); chp->ch_flags |= ATACH_TH_RUN; splx(s); /* * Probe for the drives attached to controller, unless a PMP * is already known */ /* XXX for SATA devices we will power up all drives at once */ if (chp->ch_satapmp_nports == 0) (*atac->atac_probe)(chp); if (chp->ch_ndrives >= 2) { ATADEBUG_PRINT(("atabusattach: ch_drive_type 0x%x 0x%x\n", chp->ch_drive[0].drive_type, chp->ch_drive[1].drive_type), DEBUG_PROBE); } /* next operations will occurs in a separate thread */ s = splbio(); chp->ch_flags &= ~ATACH_TH_RUN; splx(s); /* Make sure the devices probe in atabus order to avoid jitter. */ mutex_enter(&atabus_qlock); for (;;) { atabus_initq = TAILQ_FIRST(&atabus_initq_head); if (atabus_initq->atabus_sc == atabus_sc) break; cv_wait(&atabus_qcv, &atabus_qlock); } mutex_exit(&atabus_qlock); /* If no drives, abort here */ if (chp->ch_drive == NULL) goto out; KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL); for (i = 0; i < chp->ch_ndrives; i++) if (chp->ch_drive[i].drive_type != ATA_DRIVET_NONE) break; if (i == chp->ch_ndrives) goto out; /* Shortcut in case we've been shutdown */ if (chp->ch_flags & ATACH_SHUTDOWN) goto out; if ((error = kthread_create(PRI_NONE, 0, NULL, atabusconfig_thread, atabus_sc, &atabus_cfg_lwp, "%scnf", device_xname(atac->atac_dev))) != 0) aprint_error_dev(atac->atac_dev, "unable to create config thread: error %d\n", error); return; out: mutex_enter(&atabus_qlock); TAILQ_REMOVE(&atabus_initq_head, atabus_initq, atabus_initq); cv_broadcast(&atabus_qcv); mutex_exit(&atabus_qlock); free(atabus_initq, M_DEVBUF); ata_delref(chp); config_pending_decr(atac->atac_dev); }
/* * static void cardslot_event_thread(void *arg) * * This function is the main routine handing cardslot events such as * insertions and removals. * */ static void cardslot_event_thread(void *arg) { struct cardslot_softc *sc = arg; struct cardslot_event *ce; int s, first = 1; 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); if (first) { first = 0; config_pending_decr(sc->sc_dev); } (void) tsleep(&sc->sc_events, PWAIT, "cardslotev", 0); continue; } SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q); splx(s); 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); } } 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; } } 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); } } else { panic("no cardbus on %s", device_xname(sc->sc_dev)); } 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 work. */ break; } } if (sc->sc_16_softc) { CARDSLOT_SET_CARDTYPE(sc->sc_status, CARDSLOT_STATUS_CARD_16); if (pcmcia_card_attach(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); } } else { panic("no 16-bit pcmcia on %s", device_xname(sc->sc_dev)); } 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, CARDSLOT_STATUS_CARD_NONE); } CARDSLOT_SET_WORK(sc->sc_status, CARDSLOT_STATUS_NOTWORK); break; case CARDSLOT_EVENT_REMOVAL_16: DPRINTF(("%s: removal event\n", device_xname(sc->sc_dev))); 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 = device_private(sc->sc_16_softc); pcmcia_card_deactivate(sc->sc_16_softc); pcmcia_chip_socket_disable(psc->pct, psc->pch); pcmcia_card_detach(sc->sc_16_softc, 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", ce->ce_type); } free(ce, M_TEMP); } sc->sc_event_thread = NULL; /* In case the parent device is waiting for us to exit. */ wakeup(sc); kthread_exit(0); }