Skip to content

Commit

Permalink
RDMA/nes: Account for freed PBL after HW operation
Browse files Browse the repository at this point in the history
Fix occurrences where the software PBL counts were changed before the
hardware was updated.  This bug allowed another thread to overallocate
the hardware resources.

Add proper PBL accounting in case nes_reg_mr() fails.

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 Mar 6, 2009
1 parent f3b8436 commit dae5d13
Showing 1 changed file with 42 additions and 28 deletions.
70 changes: 42 additions & 28 deletions drivers/infiniband/hw/nes/nes_verbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ static int nes_dealloc_fmr(struct ib_fmr *ibfmr)
struct nes_device *nesdev = nesvnic->nesdev;
struct nes_adapter *nesadapter = nesdev->nesadapter;
int i = 0;
int rc;

/* free the resources */
if (nesfmr->leaf_pbl_cnt == 0) {
Expand All @@ -572,7 +573,9 @@ static int nes_dealloc_fmr(struct ib_fmr *ibfmr)
nesmr->ibmw.rkey = ibfmr->rkey;
nesmr->ibmw.uobject = NULL;

if (nesfmr->nesmr.pbls_used != 0) {
rc = nes_dealloc_mw(&nesmr->ibmw);

if ((rc == 0) && (nesfmr->nesmr.pbls_used != 0)) {
spin_lock_irqsave(&nesadapter->pbl_lock, flags);
if (nesfmr->nesmr.pbl_4k) {
nesadapter->free_4kpbl += nesfmr->nesmr.pbls_used;
Expand All @@ -584,7 +587,7 @@ static int nes_dealloc_fmr(struct ib_fmr *ibfmr)
spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
}

return nes_dealloc_mw(&nesmr->ibmw);
return rc;
}


Expand Down Expand Up @@ -1993,7 +1996,16 @@ static int nes_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd,
stag, ret, cqp_request->major_code, cqp_request->minor_code);
major_code = cqp_request->major_code;
nes_put_cqp_request(nesdev, cqp_request);

if ((!ret || major_code) && pbl_count != 0) {
spin_lock_irqsave(&nesadapter->pbl_lock, flags);
if (pbl_count > 1)
nesadapter->free_4kpbl += pbl_count+1;
else if (residual_page_count > 32)
nesadapter->free_4kpbl += pbl_count;
else
nesadapter->free_256pbl += pbl_count;
spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
}
if (!ret)
return -ETIME;
else if (major_code)
Expand Down Expand Up @@ -2607,24 +2619,6 @@ static int nes_dereg_mr(struct ib_mr *ib_mr)
cqp_request->waiting = 1;
cqp_wqe = &cqp_request->cqp_wqe;

spin_lock_irqsave(&nesadapter->pbl_lock, flags);
if (nesmr->pbls_used != 0) {
if (nesmr->pbl_4k) {
nesadapter->free_4kpbl += nesmr->pbls_used;
if (nesadapter->free_4kpbl > nesadapter->max_4kpbl) {
printk(KERN_ERR PFX "free 4KB PBLs(%u) has exceeded the max(%u)\n",
nesadapter->free_4kpbl, nesadapter->max_4kpbl);
}
} else {
nesadapter->free_256pbl += nesmr->pbls_used;
if (nesadapter->free_256pbl > nesadapter->max_256pbl) {
printk(KERN_ERR PFX "free 256B PBLs(%u) has exceeded the max(%u)\n",
nesadapter->free_256pbl, nesadapter->max_256pbl);
}
}
}

spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
NES_CQP_DEALLOCATE_STAG | NES_CQP_STAG_VA_TO |
Expand All @@ -2642,11 +2636,6 @@ static int nes_dereg_mr(struct ib_mr *ib_mr)
" CQP Major:Minor codes = 0x%04X:0x%04X\n",
ib_mr->rkey, ret, cqp_request->major_code, cqp_request->minor_code);

nes_free_resource(nesadapter, nesadapter->allocated_mrs,
(ib_mr->rkey & 0x0fffff00) >> 8);

kfree(nesmr);

major_code = cqp_request->major_code;
minor_code = cqp_request->minor_code;

Expand All @@ -2662,8 +2651,33 @@ static int nes_dereg_mr(struct ib_mr *ib_mr)
" to destroy STag, ib_mr=%p, rkey = 0x%08X\n",
major_code, minor_code, ib_mr, ib_mr->rkey);
return -EIO;
} else
return 0;
}

if (nesmr->pbls_used != 0) {
spin_lock_irqsave(&nesadapter->pbl_lock, flags);
if (nesmr->pbl_4k) {
nesadapter->free_4kpbl += nesmr->pbls_used;
if (nesadapter->free_4kpbl > nesadapter->max_4kpbl)
printk(KERN_ERR PFX "free 4KB PBLs(%u) has "
"exceeded the max(%u)\n",
nesadapter->free_4kpbl,
nesadapter->max_4kpbl);
} else {
nesadapter->free_256pbl += nesmr->pbls_used;
if (nesadapter->free_256pbl > nesadapter->max_256pbl)
printk(KERN_ERR PFX "free 256B PBLs(%u) has "
"exceeded the max(%u)\n",
nesadapter->free_256pbl,
nesadapter->max_256pbl);
}
spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
}
nes_free_resource(nesadapter, nesadapter->allocated_mrs,
(ib_mr->rkey & 0x0fffff00) >> 8);

kfree(nesmr);

return 0;
}


Expand Down

0 comments on commit dae5d13

Please sign in to comment.