linux/drivers/infiniband/core/mr_pool.c
<<
>>
Prefs
   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
  16struct 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}
  31EXPORT_SYMBOL(ib_mr_pool_get);
  32
  33void 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}
  42EXPORT_SYMBOL(ib_mr_pool_put);
  43
  44int 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;
  64out:
  65        ib_mr_pool_destroy(qp, list);
  66        return ret;
  67}
  68EXPORT_SYMBOL(ib_mr_pool_init);
  69
  70void 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}
  86EXPORT_SYMBOL(ib_mr_pool_destroy);
  87