| 819 | } |
| 820 | |
| 821 | int |
| 822 | intr_event_remove_handler(void *cookie) |
| 823 | { |
| 824 | struct intr_handler *handler = (struct intr_handler *)cookie; |
| 825 | struct intr_event *ie; |
| 826 | struct intr_handler *ih; |
| 827 | struct intr_handler **prevptr; |
| 828 | #ifdef notyet |
| 829 | int dead; |
| 830 | #endif |
| 831 | |
| 832 | if (handler == NULL) |
| 833 | return (EINVAL); |
| 834 | ie = handler->ih_event; |
| 835 | KASSERT(ie != NULL, |
| 836 | ("interrupt handler \"%s\" has a NULL interrupt event", |
| 837 | handler->ih_name)); |
| 838 | |
| 839 | mtx_lock(&ie->ie_lock); |
| 840 | CTR3(KTR_INTR, "%s: removing %s from %s", __func__, handler->ih_name, |
| 841 | ie->ie_name); |
| 842 | CK_SLIST_FOREACH_PREVPTR(ih, prevptr, &ie->ie_handlers, ih_next) { |
| 843 | if (ih == handler) |
| 844 | break; |
| 845 | } |
| 846 | if (ih == NULL) { |
| 847 | panic("interrupt handler \"%s\" not found in " |
| 848 | "interrupt event \"%s\"", handler->ih_name, ie->ie_name); |
| 849 | } |
| 850 | |
| 851 | /* |
| 852 | * If there is no ithread, then directly remove the handler. Note that |
| 853 | * intr_event_handle() iterates ie_handlers in a lock-less fashion, so |
| 854 | * care needs to be taken to keep ie_handlers consistent and to free |
| 855 | * the removed handler only when ie_handlers is quiescent. |
| 856 | */ |
| 857 | if (ie->ie_thread == NULL) { |
| 858 | CK_SLIST_REMOVE_PREVPTR(prevptr, ih, ih_next); |
| 859 | intr_event_barrier(ie); |
| 860 | intr_event_update(ie); |
| 861 | mtx_unlock(&ie->ie_lock); |
| 862 | free(handler, M_ITHREAD); |
| 863 | return (0); |
| 864 | } |
| 865 | |
| 866 | /* |
| 867 | * Let the interrupt thread do the job. |
| 868 | * The interrupt source is disabled when the interrupt thread is |
| 869 | * running, so it does not have to worry about interaction with |
| 870 | * intr_event_handle(). |
| 871 | */ |
| 872 | KASSERT((handler->ih_flags & IH_DEAD) == 0, |
| 873 | ("duplicate handle remove")); |
| 874 | handler->ih_flags |= IH_DEAD; |
| 875 | intr_event_schedule_thread(ie); |
| 876 | while (handler->ih_flags & IH_DEAD) |
| 877 | msleep(handler, &ie->ie_lock, 0, "iev_rmh", 0); |
| 878 | intr_event_update(ie); |
no test coverage detected