aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw
diff options
context:
space:
mode:
authorDon Wood <donald.e.wood@intel.com>2009-09-05 23:36:37 -0400
committerRoland Dreier <rolandd@cisco.com>2009-09-05 23:36:37 -0400
commit873fcdd4bfc75880888a7d148a71d70ed87c9ebf (patch)
treed64569366205a1c42be20806bb56e6b7885fe196 /drivers/infiniband/hw
parentc4c3f279cd8e9cc1d3e2f364a27beadb2e69cda8 (diff)
RDMA/nes: Allocate work item for disconnect event handling
The code currently has a work structure in the QP. This requires a lock and a pending flag to ensure there is never more than one request active. When two events happen quickly (such as FIN and LLP CLOSE), it causes unnecessary timeouts since the second one is dropped. This fix allocates memory for the work request so the second one can be queued. A lock is removed since it is no longer needed. Signed-off-by: Don Wood <donald.e.wood@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c26
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.h7
2 files changed, 16 insertions, 17 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index fe08eb57c99f..d89bdee0cf55 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -2450,20 +2450,16 @@ static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_nod
2450 */ 2450 */
2451int nes_cm_disconn(struct nes_qp *nesqp) 2451int nes_cm_disconn(struct nes_qp *nesqp)
2452{ 2452{
2453 unsigned long flags; 2453 struct disconn_work *work;
2454 2454
2455 spin_lock_irqsave(&nesqp->lock, flags); 2455 work = kzalloc(sizeof *work, GFP_ATOMIC);
2456 if (nesqp->disconn_pending == 0) { 2456 if (!work)
2457 nesqp->disconn_pending++; 2457 return -ENOMEM; /* Timer will clean up */
2458 spin_unlock_irqrestore(&nesqp->lock, flags);
2459 nes_add_ref(&nesqp->ibqp);
2460 /* init our disconnect work element, to */
2461 INIT_WORK(&nesqp->disconn_work, nes_disconnect_worker);
2462
2463 queue_work(g_cm_core->disconn_wq, &nesqp->disconn_work);
2464 } else
2465 spin_unlock_irqrestore(&nesqp->lock, flags);
2466 2458
2459 nes_add_ref(&nesqp->ibqp);
2460 work->nesqp = nesqp;
2461 INIT_WORK(&work->work, nes_disconnect_worker);
2462 queue_work(g_cm_core->disconn_wq, &work->work);
2467 return 0; 2463 return 0;
2468} 2464}
2469 2465
@@ -2473,8 +2469,10 @@ int nes_cm_disconn(struct nes_qp *nesqp)
2473 */ 2469 */
2474static void nes_disconnect_worker(struct work_struct *work) 2470static void nes_disconnect_worker(struct work_struct *work)
2475{ 2471{
2476 struct nes_qp *nesqp = container_of(work, struct nes_qp, disconn_work); 2472 struct disconn_work *dwork = container_of(work, struct disconn_work, work);
2473 struct nes_qp *nesqp = dwork->nesqp;
2477 2474
2475 kfree(dwork);
2478 nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n", 2476 nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n",
2479 nesqp->last_aeq, nesqp->hwqp.qp_id); 2477 nesqp->last_aeq, nesqp->hwqp.qp_id);
2480 nes_cm_disconn_true(nesqp); 2478 nes_cm_disconn_true(nesqp);
@@ -2557,7 +2555,6 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
2557 spin_lock_irqsave(&nesqp->lock, flags); 2555 spin_lock_irqsave(&nesqp->lock, flags);
2558 } 2556 }
2559 2557
2560 nesqp->disconn_pending = 0;
2561 /* There might have been another AE while the lock was released */ 2558 /* There might have been another AE while the lock was released */
2562 original_hw_tcp_state = nesqp->hw_tcp_state; 2559 original_hw_tcp_state = nesqp->hw_tcp_state;
2563 original_ibqp_state = nesqp->ibqp_state; 2560 original_ibqp_state = nesqp->ibqp_state;
@@ -2610,7 +2607,6 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp)
2610 } 2607 }
2611 } 2608 }
2612 } else { 2609 } else {
2613 nesqp->disconn_pending = 0;
2614 spin_unlock_irqrestore(&nesqp->lock, flags); 2610 spin_unlock_irqrestore(&nesqp->lock, flags);
2615 } 2611 }
2616 2612
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index 41c07f29f7c9..7df34fea2888 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -119,6 +119,11 @@ struct nes_wq {
119 spinlock_t lock; 119 spinlock_t lock;
120}; 120};
121 121
122struct disconn_work {
123 struct work_struct work;
124 struct nes_qp *nesqp;
125};
126
122struct iw_cm_id; 127struct iw_cm_id;
123struct ietf_mpa_frame; 128struct ietf_mpa_frame;
124 129
@@ -127,7 +132,6 @@ struct nes_qp {
127 void *allocated_buffer; 132 void *allocated_buffer;
128 struct iw_cm_id *cm_id; 133 struct iw_cm_id *cm_id;
129 struct workqueue_struct *wq; 134 struct workqueue_struct *wq;
130 struct work_struct disconn_work;
131 struct nes_cq *nesscq; 135 struct nes_cq *nesscq;
132 struct nes_cq *nesrcq; 136 struct nes_cq *nesrcq;
133 struct nes_pd *nespd; 137 struct nes_pd *nespd;
@@ -165,7 +169,6 @@ struct nes_qp {
165 u8 hw_iwarp_state; 169 u8 hw_iwarp_state;
166 u8 flush_issued; 170 u8 flush_issued;
167 u8 hw_tcp_state; 171 u8 hw_tcp_state;
168 u8 disconn_pending;
169 u8 destroyed; 172 u8 destroyed;
170}; 173};
171#endif /* NES_VERBS_H */ 174#endif /* NES_VERBS_H */