From 06b4f6d8aa4b65401de18a2437a5b9ba33e4c493 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 23 Jul 2010 13:41:55 +0000 Subject: [PATCH] Increased SRP initiator lockup safety margin, fixed a sparse warning and added more comments. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1869 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- srpt/src/ib_srpt.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index 5d3becdf2..66decae7e 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -1064,20 +1064,21 @@ out: * been called. This value is necessary for filling in the REQUEST LIMIT DELTA * field of an SRP_RSP response. * - * Side Effect: Modifies ch->last_response_req_lim. + * Side Effect: + * Increases ch->last_response_req_lim by 'delta', the value returned. */ static int srpt_req_lim_delta(struct srpt_rdma_ch *ch) { int req_lim; unsigned long flags; - int res; + int delta; req_lim = atomic_read(&ch->req_lim); spin_lock_irqsave(&ch->cred_lock, flags); - res = req_lim - ch->last_response_req_lim; + delta = req_lim - ch->last_response_req_lim; ch->last_response_req_lim = req_lim; spin_unlock_irqrestore(&ch->cred_lock, flags); - return res; + return delta; } /** @@ -3098,14 +3099,19 @@ out: * req_lim_min if that response would not increase initiator.req_lim. The last * condition is equivalent to srpt_req_lim_delta(ch) + 1 <= 0. * - * See also: For more information about how to reproduce the initiator lockup, - * see also http://bugzilla.kernel.org/show_bug.cgi?id=14235. + * If this function returns false, the caller must either send a response to + * the initiator with the REQUEST LIMIT DELTA field set to delta + 1 or call + * srpt_undo_req_lim_delta(ch, delta); where delta is the value written to + * the address that is the third argument of this function. * * Note: The constant 'compensate_for_incoming_requests' compensates for the * fact that if the initiator uses an I/O depth that is larger than one, * req_lim may have decreased towards req_lim_min after this function returned * and before the initiator has received and processed the SRP_RSP whose * REQUEST LIMIT DELTA field will have been set to *req_lim_delta. + * + * See also: For more information about how to reproduce the initiator lockup, + * see also http://bugzilla.kernel.org/show_bug.cgi?id=14235. */ static bool srpt_must_wait_for_cred(struct srpt_rdma_ch *ch, int req_lim_min, int *req_lim_delta) @@ -3114,7 +3120,7 @@ static bool srpt_must_wait_for_cred(struct srpt_rdma_ch *ch, int req_lim_min, int delta; unsigned long flags; bool res; - enum { compensate_for_incoming_requests = 1 }; + enum { compensate_for_incoming_requests = 3 }; EXTRACHECKS_BUG_ON(!req_lim_delta); @@ -3136,10 +3142,19 @@ static bool srpt_must_wait_for_cred(struct srpt_rdma_ch *ch, int req_lim_min, return res; } +/** + * srpt_wait_for_cred() - Wait until sending a response won't lock up the + * initiator. + * + * The caller must either send a response to the initiator with the REQUEST + * LIMIT DELTA field set to delta + 1 or call srpt_undo_req_lim_delta(ch, + * delta); where delta is the return value of this function. + */ static int srpt_wait_for_cred(struct srpt_rdma_ch *ch, int req_lim_min) { int delta; + delta = 0; /* superfluous -- to keep sparse happy */ while (unlikely(srpt_must_wait_for_cred(ch, req_lim_min, &delta))) schedule(); return delta;