Skip to content

Commit

Permalink
RDMA/nes: Allocate work item for disconnect event handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Don Wood authored and Roland Dreier committed Sep 6, 2009
1 parent c4c3f27 commit 873fcdd
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 17 deletions.
26 changes: 11 additions & 15 deletions drivers/infiniband/hw/nes/nes_cm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down
7 changes: 5 additions & 2 deletions drivers/infiniband/hw/nes/nes_verbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ struct nes_wq {
spinlock_t lock;
};

struct disconn_work {
struct work_struct work;
struct nes_qp *nesqp;
};

struct iw_cm_id;
struct ietf_mpa_frame;

Expand All @@ -127,7 +132,6 @@ struct nes_qp {
void *allocated_buffer;
struct iw_cm_id *cm_id;
struct workqueue_struct *wq;
struct work_struct disconn_work;
struct nes_cq *nesscq;
struct nes_cq *nesrcq;
struct nes_pd *nespd;
Expand Down Expand Up @@ -165,7 +169,6 @@ struct nes_qp {
u8 hw_iwarp_state;
u8 flush_issued;
u8 hw_tcp_state;
u8 disconn_pending;
u8 destroyed;
};
#endif /* NES_VERBS_H */

0 comments on commit 873fcdd

Please sign in to comment.