diff --git a/sys/dev/drm/linux_tasklet.c b/sys/dev/drm/linux_tasklet.c --- a/sys/dev/drm/linux_tasklet.c +++ b/sys/dev/drm/linux_tasklet.c @@ -169,9 +169,31 @@ void tasklet_kill(struct tasklet_struct *t) { + struct tasklet_entry *te; + set_bit(TASKLET_IS_DYING, &t->state); wakeup(&tasklet_runner); tasklet_unlock_wait(t); + + /* Ensure no dangling tasklet_entry remains on any queue */ + lockmgr(&tasklet_lock, LK_EXCLUSIVE); + STAILQ_FOREACH(te, &tlist, tasklet_entries) { + if (te->ts == t) { + STAILQ_REMOVE(&tlist, te, tasklet_entry, + tasklet_entries); + kfree(te); + break; + } + } + STAILQ_FOREACH(te, &tlist_hi, tasklet_entries) { + if (te->ts == t) { + STAILQ_REMOVE(&tlist_hi, te, tasklet_entry, + tasklet_entries); + kfree(te); + break; + } + } + lockmgr(&tasklet_lock, LK_RELEASE); } int