static void stop_ep_timer(struct iwch_ep *ep)
 {
        PDBG("%s ep %p\n", __func__, ep);
+       if (!timer_pending(&ep->timer)) {
+               printk(KERN_ERR "%s timer stopped when its not running!  ep %p state %u\n",
+                       __func__, ep, ep->com.state);
+               WARN_ON(1);
+               return;
+       }
        del_timer_sync(&ep->timer);
        put_ep(&ep->com);
 }
 static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 {
        struct iwch_ep *ep = ctx;
+       unsigned long flags;
+       int release = 0;
 
        PDBG("%s ep %p\n", __func__, ep);
+       BUG_ON(!ep);
 
        /*
         * We get 2 abort replies from the HW.  The first one must
                return CPL_RET_BUF_DONE;
        }
 
-       close_complete_upcall(ep);
-       state_set(&ep->com, DEAD);
-       release_ep_resources(ep);
+       spin_lock_irqsave(&ep->com.lock, flags);
+       switch (ep->com.state) {
+       case ABORTING:
+               close_complete_upcall(ep);
+               __state_set(&ep->com, DEAD);
+               release = 1;
+               break;
+       default:
+               printk(KERN_ERR "%s ep %p state %d\n",
+                    __func__, ep, ep->com.state);
+               break;
+       }
+       spin_unlock_irqrestore(&ep->com.lock, flags);
+
+       if (release)
+               release_ep_resources(ep);
        return CPL_RET_BUF_DONE;
 }
 
        struct sk_buff *rpl_skb;
        struct iwch_qp_attributes attrs;
        int ret;
-       int state;
+       int release = 0;
+       unsigned long flags;
 
        if (is_neg_adv_abort(req->status)) {
                PDBG("%s neg_adv_abort ep %p tid %d\n", __func__, ep,
                return CPL_RET_BUF_DONE;
        }
 
-       state = state_read(&ep->com);
-       PDBG("%s ep %p state %u\n", __func__, ep, state);
-       switch (state) {
+       spin_lock_irqsave(&ep->com.lock, flags);
+       PDBG("%s ep %p state %u\n", __func__, ep, ep->com.state);
+       switch (ep->com.state) {
        case CONNECTING:
                break;
        case MPA_REQ_WAIT:
                break;
        case DEAD:
                PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__);
+               spin_unlock_irqrestore(&ep->com.lock, flags);
                return CPL_RET_BUF_DONE;
        default:
                BUG_ON(1);
                break;
        }
        dst_confirm(ep->dst);
+       if (ep->com.state != ABORTING) {
+               __state_set(&ep->com, DEAD);
+               release = 1;
+       }
+       spin_unlock_irqrestore(&ep->com.lock, flags);
 
        rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL);
        if (!rpl_skb) {
                printk(KERN_ERR MOD "%s - cannot allocate skb!\n",
                       __func__);
-               dst_release(ep->dst);
-               l2t_release(L2DATA(ep->com.tdev), ep->l2t);
-               put_ep(&ep->com);
-               return CPL_RET_BUF_DONE;
+               release = 1;
+               goto out;
        }
        rpl_skb->priority = CPL_PRIORITY_DATA;
        rpl = (struct cpl_abort_rpl *) skb_put(rpl_skb, sizeof(*rpl));
        OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid));
        rpl->cmd = CPL_ABORT_NO_RST;
        cxgb3_ofld_send(ep->com.tdev, rpl_skb);
-       if (state != ABORTING) {
-               state_set(&ep->com, DEAD);
+out:
+       if (release)
                release_ep_resources(ep);
-       }
        return CPL_RET_BUF_DONE;
 }
 
        struct iwch_ep *ep = (struct iwch_ep *)arg;
        struct iwch_qp_attributes attrs;
        unsigned long flags;
+       int abort = 1;
 
        spin_lock_irqsave(&ep->com.lock, flags);
        PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid,
             ep->com.state);
        switch (ep->com.state) {
        case MPA_REQ_SENT:
+               __state_set(&ep->com, ABORTING);
                connect_reply_upcall(ep, -ETIMEDOUT);
                break;
        case MPA_REQ_WAIT:
+               __state_set(&ep->com, ABORTING);
                break;
        case CLOSING:
        case MORIBUND:
                                     ep->com.qp, IWCH_QP_ATTR_NEXT_STATE,
                                     &attrs, 1);
                }
+               __state_set(&ep->com, ABORTING);
                break;
        default:
-               BUG();
+               printk(KERN_ERR "%s unexpected state ep %p state %u\n",
+                       __func__, ep, ep->com.state);
+               WARN_ON(1);
+               abort = 0;
        }
-       __state_set(&ep->com, CLOSING);
        spin_unlock_irqrestore(&ep->com.lock, flags);
-       abort_connection(ep, NULL, GFP_ATOMIC);
+       if (abort)
+               abort_connection(ep, NULL, GFP_ATOMIC);
        put_ep(&ep->com);
 }
 
        PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep,
             states[ep->com.state], abrupt);
 
-       if (ep->com.state == DEAD) {
-               PDBG("%s already dead ep %p\n", __func__, ep);
-               goto out;
-       }
-
-       if (abrupt) {
-               if (ep->com.state != ABORTING) {
-                       ep->com.state = ABORTING;
-                       close = 1;
-               }
-               goto out;
-       }
-
        switch (ep->com.state) {
        case MPA_REQ_WAIT:
        case MPA_REQ_SENT:
        case MPA_REQ_RCVD:
        case MPA_REP_SENT:
        case FPDU_MODE:
-               start_ep_timer(ep);
-               ep->com.state = CLOSING;
                close = 1;
+               if (abrupt)
+                       ep->com.state = ABORTING;
+               else {
+                       ep->com.state = CLOSING;
+                       start_ep_timer(ep);
+               }
                break;
        case CLOSING:
-               ep->com.state = MORIBUND;
                close = 1;
+               if (abrupt) {
+                       stop_ep_timer(ep);
+                       ep->com.state = ABORTING;
+               } else
+                       ep->com.state = MORIBUND;
                break;
        case MORIBUND:
+       case ABORTING:
+       case DEAD:
+               PDBG("%s ignoring disconnect ep %p state %u\n",
+                    __func__, ep, ep->com.state);
                break;
        default:
                BUG();
                break;
        }
-out:
+
        spin_unlock_irqrestore(&ep->com.lock, flags);
        if (close) {
                if (abrupt)