1 /* 2 * Copyright (c) 2016 HGST, a Western Digital Company. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 */ 13 #include <rdma/ib_verbs.h> 14 #include <rdma/mr_pool.h> 15 16 struct ib_mr *ib_mr_pool_get(struct ib_qp *qp, struct list_head *list) 17 { 18 struct ib_mr *mr; 19 unsigned long flags; 20 21 spin_lock_irqsave(&qp->mr_lock, flags); 22 mr = list_first_entry_or_null(list, struct ib_mr, qp_entry); 23 if (mr) { 24 list_del(&mr->qp_entry); 25 qp->mrs_used++; 26 } 27 spin_unlock_irqrestore(&qp->mr_lock, flags); 28 29 return mr; 30 } 31 EXPORT_SYMBOL(ib_mr_pool_get); 32 33 void ib_mr_pool_put(struct ib_qp *qp, struct list_head *list, struct ib_mr *mr) 34 { 35 unsigned long flags; 36 37 spin_lock_irqsave(&qp->mr_lock, flags); 38 list_add(&mr->qp_entry, list); 39 qp->mrs_used--; 40 spin_unlock_irqrestore(&qp->mr_lock, flags); 41 } 42 EXPORT_SYMBOL(ib_mr_pool_put); 43 44 int ib_mr_pool_init(struct ib_qp *qp, struct list_head *list, int nr, 45 enum ib_mr_type type, u32 max_num_sg) 46 { 47 struct ib_mr *mr; 48 unsigned long flags; 49 int ret, i; 50 51 for (i = 0; i < nr; i++) { 52 mr = ib_alloc_mr(qp->pd, type, max_num_sg); 53 if (IS_ERR(mr)) { 54 ret = PTR_ERR(mr); 55 goto out; 56 } 57 58 spin_lock_irqsave(&qp->mr_lock, flags); 59 list_add_tail(&mr->qp_entry, list); 60 spin_unlock_irqrestore(&qp->mr_lock, flags); 61 } 62 63 return 0; 64 out: 65 ib_mr_pool_destroy(qp, list); 66 return ret; 67 } 68 EXPORT_SYMBOL(ib_mr_pool_init); 69 70 void ib_mr_pool_destroy(struct ib_qp *qp, struct list_head *list) 71 { 72 struct ib_mr *mr; 73 unsigned long flags; 74 75 spin_lock_irqsave(&qp->mr_lock, flags); 76 while (!list_empty(list)) { 77 mr = list_first_entry(list, struct ib_mr, qp_entry); 78 list_del(&mr->qp_entry); 79 80 spin_unlock_irqrestore(&qp->mr_lock, flags); 81 ib_dereg_mr(mr); 82 spin_lock_irqsave(&qp->mr_lock, flags); 83 } 84 spin_unlock_irqrestore(&qp->mr_lock, flags); 85 } 86 EXPORT_SYMBOL(ib_mr_pool_destroy); 87