thi->task = NULL;
        thi->t_state = NONE;
        smp_mb();
-       complete(&thi->stop);
+       complete_all(&thi->stop);
        spin_unlock_irqrestore(&thi->t_lock, flags);
 
        conn_info(tconn, "Terminating %s\n", current->comm);
 
 /* if still unconfigured, stops worker again. */
 static void conn_reconfig_done(struct drbd_tconn *tconn)
 {
+       bool stop_threads;
        spin_lock_irq(&tconn->req_lock);
-       if (conn_all_vols_unconf(tconn))
-               drbd_thread_stop_nowait(&tconn->worker);
+       stop_threads = conn_all_vols_unconf(tconn);
        spin_unlock_irq(&tconn->req_lock);
+       if (stop_threads) {
+               /* asender is implicitly stopped by receiver
+                * in drbd_disconnect() */
+               drbd_thread_stop(&tconn->receiver);
+               drbd_thread_stop(&tconn->worker);
+       }
 }
 
 /* Make sure IO is suspended before calling this function(). */
 
        /* delete connection */
        if (conn_lowest_minor(adm_ctx.tconn) < 0) {
-               drbd_thread_stop(&adm_ctx.tconn->worker);
                list_del(&adm_ctx.tconn->all_tconn);
                kref_put(&adm_ctx.tconn->kref, &conn_destroy);
 
                retcode = ERR_CONN_IN_USE;
                drbd_msg_put_info("failed to delete connection");
        }
-
        up_write(&drbd_cfg_rwsem);
        goto out;
 out_unlock:
        }
        up_write(&drbd_cfg_rwsem);
 
+       if (retcode == NO_ERROR)
+               drbd_thread_stop(&adm_ctx.tconn->worker);
 out:
        drbd_adm_finish(info, retcode);
        return 0;
 
 static int w_after_state_ch(struct drbd_work *w, int unused);
 static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
                           union drbd_state ns, enum chg_state_flags flags);
-static void after_all_state_ch(struct drbd_tconn *tconn);
 static enum drbd_state_rv is_valid_state(struct drbd_conf *, union drbd_state);
 static enum drbd_state_rv is_valid_soft_transition(union drbd_state, union drbd_state);
 static enum drbd_state_rv is_valid_transition(union drbd_state os, union drbd_state ns);
                        resume_next_sg(mdev);
        }
 
-       after_all_state_ch(mdev->tconn);
-
        drbd_md_sync(mdev);
 }
 
        enum chg_state_flags flags;
 };
 
-static void after_all_state_ch(struct drbd_tconn *tconn)
-{
-       if (conn_all_vols_unconf(tconn))
-               drbd_thread_stop_nowait(&tconn->worker);
-}
-
 static int w_after_conn_state_ch(struct drbd_work *w, int unused)
 {
        struct after_conn_state_chg_work *acscw =
                        spin_unlock_irq(&tconn->req_lock);
                }
        }
-
-
-       //conn_err(tconn, STATE_FMT, STATE_ARGS("nms", nms));
-       after_all_state_ch(tconn);
        kref_put(&tconn->kref, &conn_destroy);
-
        return 0;
 }
 
 
         */
        spin_unlock_irq(&tconn->data.work.q_lock);
 
-       /* _drbd_set_state only uses stop_nowait.
-        * wait here for the exiting receiver. */
-       drbd_thread_stop(&tconn->receiver);
-
        down_read(&drbd_cfg_rwsem);
        idr_for_each_entry(&tconn->volumes, mdev, vnr) {
                D_ASSERT(mdev->state.disk == D_DISKLESS && mdev->state.conn == C_STANDALONE);