]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/infiniband/hw/nes/nes_cm.c
RDMA/nes: Allocate work item for disconnect event handling
[mv-sheeva.git] / drivers / infiniband / hw / nes / nes_cm.c
index fe08eb57c99f7543f1aff77194a304438e9e5631..d89bdee0cf554ca9388c2e6c2e6ca29536a99829 100644 (file)
@@ -2450,20 +2450,16 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
  */
 int nes_cm_disconn(struct nes_qp *nesqp)
 {
-       unsigned long flags;
+       struct disconn_work *work;
 
-       spin_lock_irqsave(&nesqp->lock, flags);
-       if (nesqp->disconn_pending == 0) {
-               nesqp->disconn_pending++;
-               spin_unlock_irqrestore(&nesqp->lock, flags);
-               nes_add_ref(&nesqp->ibqp);
-               /* init our disconnect work element, to */
-               INIT_WORK(&nesqp->disconn_work, nes_disconnect_worker);
-
-               queue_work(g_cm_core->disconn_wq, &nesqp->disconn_work);
-       } else
-               spin_unlock_irqrestore(&nesqp->lock, flags);
+       work = kzalloc(sizeof *work, GFP_ATOMIC);
+       if (!work)
+               return -ENOMEM; /* Timer will clean up */
 
+       nes_add_ref(&nesqp->ibqp);
+       work->nesqp = nesqp;
+       INIT_WORK(&work->work, nes_disconnect_worker);
+       queue_work(g_cm_core->disconn_wq, &work->work);
        return 0;
 }
 
@@ -2473,8 +2469,10 @@ int nes_cm_disconn(struct nes_qp *nesqp)
  */
 static void nes_disconnect_worker(struct work_struct *work)
 {
-       struct nes_qp *nesqp = container_of(work, struct nes_qp, disconn_work);
+       struct disconn_work *dwork = container_of(work, struct disconn_work, work);
+       struct nes_qp *nesqp = dwork->nesqp;
 
+       kfree(dwork);
        nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n",
                        nesqp->last_aeq, nesqp->hwqp.qp_id);
        nes_cm_disconn_true(nesqp);
@@ -2557,7 +2555,6 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
                        spin_lock_irqsave(&nesqp->lock, flags);
                }
 
-               nesqp->disconn_pending = 0;
                /* There might have been another AE while the lock was released */
                original_hw_tcp_state = nesqp->hw_tcp_state;
                original_ibqp_state   = nesqp->ibqp_state;
@@ -2610,7 +2607,6 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
                        }
                }
        } else {
-               nesqp->disconn_pending = 0;
                spin_unlock_irqrestore(&nesqp->lock, flags);
        }