Prevents a race condition between hardware and ULPs when
tearing down connections.  Memory and data structures are
cleaned up after the hardware ce handler has run.

Signed-off-by: Glenn Grundstrom <[EMAIL PROTECTED]>

---

diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index 1088330..4376bc2 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -263,13 +263,43 @@ void nes_add_ref(struct ib_qp *ibqp)
        atomic_inc(&nesqp->refcount);
 }
 
+static void nes_cqp_rem_ref_callback(struct nes_device *nesdev, struct 
nes_cqp_request *cqp_request)
+{
+       unsigned long flags;
+       struct nes_qp *nesqp = cqp_request->cqp_callback_pointer;
+       struct nes_adapter *nesadapter = nesdev->nesadapter;
+       u32 qp_id;
+
+       atomic_inc(&qps_destroyed);
+
+       /* Free the control structures */
+
+       qp_id = nesqp->hwqp.qp_id;
+       if (nesqp->pbl_vbase) {
+               pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size,
+                               nesqp->hwqp.q2_vbase, nesqp->hwqp.q2_pbase);
+               spin_lock_irqsave(&nesadapter->pbl_lock, flags);
+               nesadapter->free_256pbl++;
+               spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
+               pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, 
nesqp->pbl_pbase);
+               nesqp->pbl_vbase = NULL;
+               kunmap(nesqp->page);
+
+       } else {
+               pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size,
+                               nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase);
+       }
+       nes_free_resource(nesadapter, nesadapter->allocated_qps, 
nesqp->hwqp.qp_id);
+
+       kfree(nesqp->allocated_buffer);
+
+}
 
 /**
  * nes_rem_ref
  */
 void nes_rem_ref(struct ib_qp *ibqp)
 {
-       unsigned long flags;
        u64 u64temp;
        struct nes_qp *nesqp;
        struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);
@@ -287,27 +317,7 @@ void nes_rem_ref(struct ib_qp *ibqp)
        }
 
        if (atomic_dec_and_test(&nesqp->refcount)) {
-               atomic_inc(&qps_destroyed);
-
-               /* Free the control structures */
-
-               if (nesqp->pbl_vbase) {
-                       pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size,
-                                       nesqp->hwqp.q2_vbase, 
nesqp->hwqp.q2_pbase);
-                       spin_lock_irqsave(&nesadapter->pbl_lock, flags);
-                       nesadapter->free_256pbl++;
-                       spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
-                       pci_free_consistent(nesdev->pcidev, 256, 
nesqp->pbl_vbase, nesqp->pbl_pbase);
-                       nesqp->pbl_vbase = NULL;
-                       kunmap(nesqp->page);
-
-               } else {
-                       pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size,
-                                       nesqp->hwqp.sq_vbase, 
nesqp->hwqp.sq_pbase);
-               }
-
                nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = NULL;
-               nes_free_resource(nesadapter, nesadapter->allocated_qps, 
nesqp->hwqp.qp_id);
 
                /* Destroy the QP */
                cqp_request = nes_get_cqp_request(nesdev);
@@ -316,6 +326,9 @@ void nes_rem_ref(struct ib_qp *ibqp)
                        return;
                }
                cqp_request->waiting = 0;
+               cqp_request->callback = 1;
+               cqp_request->cqp_callback = nes_cqp_rem_ref_callback;
+               cqp_request->cqp_callback_pointer = nesqp;
                cqp_wqe = &cqp_request->cqp_wqe;
 
                cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] =
@@ -339,8 +352,6 @@ void nes_rem_ref(struct ib_qp *ibqp)
                                cpu_to_le32((u32)(u64temp >> 32));
 
                nes_post_cqp_request(nesdev, cqp_request, 
NES_CQP_REQUEST_RING_DOORBELL);
-
-               kfree(nesqp->allocated_buffer);
        }
 }
 
diff --git a/drivers/infiniband/hw/nes/nes_hw.c 
b/drivers/infiniband/hw/nes/nes_hw.c
index 1048db2..06d1963 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -2427,6 +2427,16 @@ void nes_cqp_ce_handler(struct nes_device *nesdev, 
struct nes_hw_cq *cq)
                                                        
spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
                                                }
                                        }
+                               } else if (cqp_request->callback) {
+                                       /* Envoke the callback routine */
+                                       cqp_request->cqp_callback(nesdev, 
cqp_request);
+                                       if (cqp_request->dynamic) {
+                                               kfree(cqp_request);
+                                       } else {
+                                               
spin_lock_irqsave(&nesdev->cqp.lock, flags);
+                                               
list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
+                                               
spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
+                                       }
                                } else {
                                        nes_debug(NES_DBG_CQP, "CQP request %p 
(opcode 0x%02X) freed.\n",
                                                        cqp_request,
diff --git a/drivers/infiniband/hw/nes/nes_hw.h 
b/drivers/infiniband/hw/nes/nes_hw.h
index ca0b006..0279d4c 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -813,18 +813,22 @@ struct nes_hw_aeqe {
        __le32 aeqe_words[4];
 };
 
-
 struct nes_cqp_request {
+       union {
+               u64 cqp_callback_context;
+               void *cqp_callback_pointer;
+       };
        wait_queue_head_t     waitq;
        struct nes_hw_cqp_wqe cqp_wqe;
        struct list_head      list;
        atomic_t              refcount;
+       void (*cqp_callback)(struct nes_device *nesdev, struct nes_cqp_request 
*cqp_request);
        u16                   major_code;
        u16                   minor_code;
        u8                    waiting;
        u8                    request_done;
        u8                    dynamic;
-       u8                    padding[1];
+       u8                    callback;
 };
 
 struct nes_hw_cqp {
@@ -1158,6 +1162,8 @@ struct nes_vnic {
        struct nes_hw_nic    nic;
        struct nes_hw_nic_cq nic_cq;
 
+       struct nes_cqp_request* (*get_cqp_request)(struct nes_device *nesdev);
+       void (*post_cqp_request)(struct nes_device*, struct nes_cqp_request *, 
int);
        struct net_device_stats netstats;
        /* used to put the netdev on the adapters logical port list */
        struct list_head list;
diff --git a/drivers/infiniband/hw/nes/nes_utils.c 
b/drivers/infiniband/hw/nes/nes_utils.c
index 8d2c1ee..ffd2b99 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -558,6 +558,7 @@ struct nes_cqp_request *nes_get_cqp_request(struct 
nes_device *nesdev)
                init_waitqueue_head(&cqp_request->waitq);
                cqp_request->waiting = 0;
                cqp_request->request_done = 0;
+               cqp_request->callback = 0;
                init_waitqueue_head(&cqp_request->waitq);
                nes_debug(NES_DBG_CQP, "Got cqp request %p from the available 
list \n",
                                cqp_request);
_______________________________________________
general mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to