// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016 HGST, a Western Digital Company. */ #include #include struct ib_mr *ib_mr_pool_get(struct ib_qp *qp, struct list_head *list) { struct ib_mr *mr; unsigned long flags; spin_lock_irqsave(&qp->mr_lock, flags); mr = list_first_entry_or_null(list, struct ib_mr, qp_entry); if (mr) { list_del(&mr->qp_entry); qp->mrs_used++; } spin_unlock_irqrestore(&qp->mr_lock, flags); return mr; } EXPORT_SYMBOL(ib_mr_pool_get); void ib_mr_pool_put(struct ib_qp *qp, struct list_head *list, struct ib_mr *mr) { unsigned long flags; spin_lock_irqsave(&qp->mr_lock, flags); list_add(&mr->qp_entry, list); qp->mrs_used--; spin_unlock_irqrestore(&qp->mr_lock, flags); } EXPORT_SYMBOL(ib_mr_pool_put); int ib_mr_pool_init(struct ib_qp *qp, struct list_head *list, int nr, enum ib_mr_type type, u32 max_num_sg, u32 max_num_meta_sg) { struct ib_mr *mr; unsigned long flags; int ret, i; for (i = 0; i < nr; i++) { if (type == IB_MR_TYPE_INTEGRITY) mr = ib_alloc_mr_integrity(qp->pd, max_num_sg, max_num_meta_sg); else mr = ib_alloc_mr(qp->pd, type, max_num_sg); if (IS_ERR(mr)) { ret = PTR_ERR(mr); goto out; } spin_lock_irqsave(&qp->mr_lock, flags); list_add_tail(&mr->qp_entry, list); spin_unlock_irqrestore(&qp->mr_lock, flags); } return 0; out: ib_mr_pool_destroy(qp, list); return ret; } EXPORT_SYMBOL(ib_mr_pool_init); void ib_mr_pool_destroy(struct ib_qp *qp, struct list_head *list) { struct ib_mr *mr; unsigned long flags; spin_lock_irqsave(&qp->mr_lock, flags); while (!list_empty(list)) { mr = list_first_entry(list, struct ib_mr, qp_entry); list_del(&mr->qp_entry); spin_unlock_irqrestore(&qp->mr_lock, flags); ib_dereg_mr(mr); spin_lock_irqsave(&qp->mr_lock, flags); } spin_unlock_irqrestore(&qp->mr_lock, flags); } EXPORT_SYMBOL(ib_mr_pool_destroy);