lgr->smcd = ini->ism_dev;
                lgr_list = &ini->ism_dev->lgr_list;
                lgr_lock = &lgr->smcd->lgr_lock;
+               lgr->peer_shutdown = 0;
        } else {
                /* SMC-R specific settings */
                get_device(&ini->ib_dev->ibdev->dev);
 {
        struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
 
-       smc_close_abort(conn);
+       if (conn->lgr->is_smcd && conn->lgr->peer_shutdown)
+               conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
+       else
+               smc_close_abort(conn);
        conn->killed = 1;
+       smc->sk.sk_err = ECONNABORTED;
        smc_sk_wake_ups(smc);
+       if (conn->lgr->is_smcd)
+               tasklet_kill(&conn->rx_tsklet);
        smc_lgr_unregister_conn(conn);
-       smc->sk.sk_err = ECONNABORTED;
        smc_close_active_abort(smc);
 }
 
        list_for_each_entry_safe(lgr, l, &dev->lgr_list, list) {
                if ((!peer_gid || lgr->peer_gid == peer_gid) &&
                    (vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) {
+                       if (peer_gid) /* peer triggered termination */
+                               lgr->peer_shutdown = 1;
                        list_move(&lgr->list, &lgr_free_list);
                }
        }
        /* cancel the regular free workers and actually free lgrs */
        list_for_each_entry_safe(lgr, l, &lgr_free_list, list) {
                list_del_init(&lgr->list);
-               __smc_lgr_terminate(lgr);
-               cancel_delayed_work_sync(&lgr->free_work);
-               if (!peer_gid && vlan == VLAN_VID_MASK) /* dev terminated? */
-                       smc_ism_signal_shutdown(lgr);
-               smc_lgr_free(lgr);
+               schedule_work(&lgr->terminate_work);
        }
 }
 
 
        int rc;
        union smcd_sw_event_info ev_info;
 
+       if (lgr->peer_shutdown)
+               return 0;
+
        memcpy(ev_info.uid, lgr->id, SMC_LGR_ID_SIZE);
        ev_info.vlan_id = lgr->vlan_id;
        ev_info.code = ISM_EVENT_REQUEST;
 void smcd_unregister_dev(struct smcd_dev *smcd)
 {
        spin_lock(&smcd_dev_list.lock);
-       list_del(&smcd->list);
+       list_del_init(&smcd->list);
        spin_unlock(&smcd_dev_list.lock);
        smcd->going_away = 1;
+       smc_smcd_terminate(smcd, 0, VLAN_VID_MASK);
        flush_workqueue(smcd->event_wq);
        destroy_workqueue(smcd->event_wq);
-       smc_smcd_terminate(smcd, 0, VLAN_VID_MASK);
 
        device_del(&smcd->dev);
 }