aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorTatyana Nikolova <Tatyana.E.Nikolova@intel.com>2012-11-02 19:17:54 -0400
committerRoland Dreier <roland@purestorage.com>2012-11-22 03:49:14 -0500
commitfc8d7547b1e19e1bb8f3206837ee0c7c6538e2e5 (patch)
tree065f0c71fc066a386f56b3cefb16ef10efbe0547 /drivers/infiniband
parentbff3976bef4f917554292d48ce43636f3d040182 (diff)
RDMA/nes: Fix for sending fpdus in order to hardware
Locking fix to prevent race conditions. Fpdus (per qp) need to be forwarded to hardware in the order of their sequence numbers. Signed-off-by: Tatyana Nikolova <Tatyana.E.Nikolova@intel.com> Signed-off-by: Donald Wood <Donald.E.Wood@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/nes/nes_mgt.c23
1 files changed, 10 insertions, 13 deletions
diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c
index 1f5d69e7793a..4d6d77fd18b6 100644
--- a/drivers/infiniband/hw/nes/nes_mgt.c
+++ b/drivers/infiniband/hw/nes/nes_mgt.c
@@ -247,7 +247,6 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
247 struct nes_rskb_cb *cb; 247 struct nes_rskb_cb *cb;
248 struct pau_fpdu_info *fpdu_info = NULL; 248 struct pau_fpdu_info *fpdu_info = NULL;
249 struct pau_fpdu_frag frags[MAX_FPDU_FRAGS]; 249 struct pau_fpdu_frag frags[MAX_FPDU_FRAGS];
250 unsigned long flags;
251 u32 fpdu_len = 0; 250 u32 fpdu_len = 0;
252 u32 tmp_len; 251 u32 tmp_len;
253 int frag_cnt = 0; 252 int frag_cnt = 0;
@@ -262,12 +261,10 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
262 261
263 *pau_fpdu_info = NULL; 262 *pau_fpdu_info = NULL;
264 263
265 spin_lock_irqsave(&nesqp->pau_lock, flags);
266 skb = nes_get_next_skb(nesdev, nesqp, NULL, nesqp->pau_rcv_nxt, &ack, &wnd, &fin_rcvd, &rst_rcvd); 264 skb = nes_get_next_skb(nesdev, nesqp, NULL, nesqp->pau_rcv_nxt, &ack, &wnd, &fin_rcvd, &rst_rcvd);
267 if (!skb) { 265 if (!skb)
268 spin_unlock_irqrestore(&nesqp->pau_lock, flags);
269 goto out; 266 goto out;
270 } 267
271 cb = (struct nes_rskb_cb *)&skb->cb[0]; 268 cb = (struct nes_rskb_cb *)&skb->cb[0];
272 if (skb->len) { 269 if (skb->len) {
273 fpdu_len = be16_to_cpu(*(__be16 *) skb->data) + MPA_FRAMING; 270 fpdu_len = be16_to_cpu(*(__be16 *) skb->data) + MPA_FRAMING;
@@ -292,10 +289,9 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
292 289
293 skb = nes_get_next_skb(nesdev, nesqp, skb, 290 skb = nes_get_next_skb(nesdev, nesqp, skb,
294 nesqp->pau_rcv_nxt + frag_tot, &ack, &wnd, &fin_rcvd, &rst_rcvd); 291 nesqp->pau_rcv_nxt + frag_tot, &ack, &wnd, &fin_rcvd, &rst_rcvd);
295 if (!skb) { 292 if (!skb)
296 spin_unlock_irqrestore(&nesqp->pau_lock, flags);
297 goto out; 293 goto out;
298 } else if (rst_rcvd) { 294 if (rst_rcvd) {
299 /* rst received in the middle of fpdu */ 295 /* rst received in the middle of fpdu */
300 for (; i >= 0; i--) { 296 for (; i >= 0; i--) {
301 skb_unlink(frags[i].skb, &nesqp->pau_list); 297 skb_unlink(frags[i].skb, &nesqp->pau_list);
@@ -322,8 +318,6 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
322 frag_cnt = 1; 318 frag_cnt = 1;
323 } 319 }
324 320
325 spin_unlock_irqrestore(&nesqp->pau_lock, flags);
326
327 /* Found one */ 321 /* Found one */
328 fpdu_info = kzalloc(sizeof(*fpdu_info), GFP_ATOMIC); 322 fpdu_info = kzalloc(sizeof(*fpdu_info), GFP_ATOMIC);
329 if (fpdu_info == NULL) { 323 if (fpdu_info == NULL) {
@@ -385,10 +379,8 @@ static int get_fpdu_info(struct nes_device *nesdev, struct nes_qp *nesqp,
385 379
386 if (frags[i].skb->len == 0) { 380 if (frags[i].skb->len == 0) {
387 /* Pull skb off the list - it will be freed in the callback */ 381 /* Pull skb off the list - it will be freed in the callback */
388 spin_lock_irqsave(&nesqp->pau_lock, flags);
389 if (!skb_queue_empty(&nesqp->pau_list)) 382 if (!skb_queue_empty(&nesqp->pau_list))
390 skb_unlink(frags[i].skb, &nesqp->pau_list); 383 skb_unlink(frags[i].skb, &nesqp->pau_list);
391 spin_unlock_irqrestore(&nesqp->pau_lock, flags);
392 } else { 384 } else {
393 /* Last skb still has data so update the seq */ 385 /* Last skb still has data so update the seq */
394 iph = (struct iphdr *)(cb->data_start + ETH_HLEN); 386 iph = (struct iphdr *)(cb->data_start + ETH_HLEN);
@@ -417,14 +409,18 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
417 struct pau_fpdu_info *fpdu_info; 409 struct pau_fpdu_info *fpdu_info;
418 struct nes_hw_cqp_wqe *cqp_wqe; 410 struct nes_hw_cqp_wqe *cqp_wqe;
419 struct nes_cqp_request *cqp_request; 411 struct nes_cqp_request *cqp_request;
412 unsigned long flags;
420 u64 u64tmp; 413 u64 u64tmp;
421 u32 u32tmp; 414 u32 u32tmp;
422 int rc; 415 int rc;
423 416
424 while (1) { 417 while (1) {
418 spin_lock_irqsave(&nesqp->pau_lock, flags);
425 rc = get_fpdu_info(nesdev, nesqp, &fpdu_info); 419 rc = get_fpdu_info(nesdev, nesqp, &fpdu_info);
426 if (fpdu_info == NULL) 420 if (rc || (fpdu_info == NULL)) {
421 spin_unlock_irqrestore(&nesqp->pau_lock, flags);
427 return rc; 422 return rc;
423 }
428 424
429 cqp_request = fpdu_info->cqp_request; 425 cqp_request = fpdu_info->cqp_request;
430 cqp_wqe = &cqp_request->cqp_wqe; 426 cqp_wqe = &cqp_request->cqp_wqe;
@@ -478,6 +474,7 @@ static int forward_fpdus(struct nes_vnic *nesvnic, struct nes_qp *nesqp)
478 474
479 atomic_set(&cqp_request->refcount, 1); 475 atomic_set(&cqp_request->refcount, 1);
480 nes_post_cqp_request(nesdev, cqp_request); 476 nes_post_cqp_request(nesdev, cqp_request);
477 spin_unlock_irqrestore(&nesqp->pau_lock, flags);
481 } 478 }
482 479
483 return 0; 480 return 0;