108b48a1eSAndy Grover /*
2b7ff8b10SKa-Cheong Poon * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
308b48a1eSAndy Grover *
408b48a1eSAndy Grover * This software is available to you under a choice of one of two
508b48a1eSAndy Grover * licenses. You may choose to be licensed under the terms of the GNU
608b48a1eSAndy Grover * General Public License (GPL) Version 2, available from the file
708b48a1eSAndy Grover * COPYING in the main directory of this source tree, or the
808b48a1eSAndy Grover * OpenIB.org BSD license below:
908b48a1eSAndy Grover *
1008b48a1eSAndy Grover * Redistribution and use in source and binary forms, with or
1108b48a1eSAndy Grover * without modification, are permitted provided that the following
1208b48a1eSAndy Grover * conditions are met:
1308b48a1eSAndy Grover *
1408b48a1eSAndy Grover * - Redistributions of source code must retain the above
1508b48a1eSAndy Grover * copyright notice, this list of conditions and the following
1608b48a1eSAndy Grover * disclaimer.
1708b48a1eSAndy Grover *
1808b48a1eSAndy Grover * - Redistributions in binary form must reproduce the above
1908b48a1eSAndy Grover * copyright notice, this list of conditions and the following
2008b48a1eSAndy Grover * disclaimer in the documentation and/or other materials
2108b48a1eSAndy Grover * provided with the distribution.
2208b48a1eSAndy Grover *
2308b48a1eSAndy Grover * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2408b48a1eSAndy Grover * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2508b48a1eSAndy Grover * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2608b48a1eSAndy Grover * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
2708b48a1eSAndy Grover * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
2808b48a1eSAndy Grover * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2908b48a1eSAndy Grover * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3008b48a1eSAndy Grover * SOFTWARE.
3108b48a1eSAndy Grover *
3208b48a1eSAndy Grover */
3308b48a1eSAndy Grover #include <linux/kernel.h>
345a0e3ad6STejun Heo #include <linux/slab.h>
35764f2dd9SChris Mason #include <linux/rculist.h>
361bc144b6SHuang Ying #include <linux/llist.h>
3708b48a1eSAndy Grover
380cb43965SSowmini Varadhan #include "rds_single_path.h"
39f6df683fSsantosh.shilimkar@oracle.com #include "ib_mr.h"
402eafa174SHans Westgaard Ry #include "rds.h"
41f6df683fSsantosh.shilimkar@oracle.com
42f6df683fSsantosh.shilimkar@oracle.com struct workqueue_struct *rds_ib_mr_wq;
432eafa174SHans Westgaard Ry struct rds_ib_dereg_odp_mr {
442eafa174SHans Westgaard Ry struct work_struct work;
452eafa174SHans Westgaard Ry struct ib_mr *mr;
462eafa174SHans Westgaard Ry };
472eafa174SHans Westgaard Ry
482eafa174SHans Westgaard Ry static void rds_ib_odp_mr_worker(struct work_struct *work);
4908b48a1eSAndy Grover
rds_ib_get_device(__be32 ipaddr)5008b48a1eSAndy Grover static struct rds_ib_device *rds_ib_get_device(__be32 ipaddr)
5108b48a1eSAndy Grover {
5208b48a1eSAndy Grover struct rds_ib_device *rds_ibdev;
5308b48a1eSAndy Grover struct rds_ib_ipaddr *i_ipaddr;
5408b48a1eSAndy Grover
55764f2dd9SChris Mason rcu_read_lock();
56ea819867SZach Brown list_for_each_entry_rcu(rds_ibdev, &rds_ib_devices, list) {
57764f2dd9SChris Mason list_for_each_entry_rcu(i_ipaddr, &rds_ibdev->ipaddr_list, list) {
5808b48a1eSAndy Grover if (i_ipaddr->ipaddr == ipaddr) {
5950d61ff7SReshetova, Elena refcount_inc(&rds_ibdev->refcount);
60764f2dd9SChris Mason rcu_read_unlock();
6108b48a1eSAndy Grover return rds_ibdev;
6208b48a1eSAndy Grover }
6308b48a1eSAndy Grover }
6408b48a1eSAndy Grover }
65ea819867SZach Brown rcu_read_unlock();
6608b48a1eSAndy Grover
6708b48a1eSAndy Grover return NULL;
6808b48a1eSAndy Grover }
6908b48a1eSAndy Grover
rds_ib_add_ipaddr(struct rds_ib_device * rds_ibdev,__be32 ipaddr)7008b48a1eSAndy Grover static int rds_ib_add_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr)
7108b48a1eSAndy Grover {
7208b48a1eSAndy Grover struct rds_ib_ipaddr *i_ipaddr;
7308b48a1eSAndy Grover
7408b48a1eSAndy Grover i_ipaddr = kmalloc(sizeof *i_ipaddr, GFP_KERNEL);
7508b48a1eSAndy Grover if (!i_ipaddr)
7608b48a1eSAndy Grover return -ENOMEM;
7708b48a1eSAndy Grover
7808b48a1eSAndy Grover i_ipaddr->ipaddr = ipaddr;
7908b48a1eSAndy Grover
8008b48a1eSAndy Grover spin_lock_irq(&rds_ibdev->spinlock);
81764f2dd9SChris Mason list_add_tail_rcu(&i_ipaddr->list, &rds_ibdev->ipaddr_list);
8208b48a1eSAndy Grover spin_unlock_irq(&rds_ibdev->spinlock);
8308b48a1eSAndy Grover
8408b48a1eSAndy Grover return 0;
8508b48a1eSAndy Grover }
8608b48a1eSAndy Grover
rds_ib_remove_ipaddr(struct rds_ib_device * rds_ibdev,__be32 ipaddr)8708b48a1eSAndy Grover static void rds_ib_remove_ipaddr(struct rds_ib_device *rds_ibdev, __be32 ipaddr)
8808b48a1eSAndy Grover {
894a81802bSAndy Grover struct rds_ib_ipaddr *i_ipaddr;
90764f2dd9SChris Mason struct rds_ib_ipaddr *to_free = NULL;
91764f2dd9SChris Mason
9208b48a1eSAndy Grover
9308b48a1eSAndy Grover spin_lock_irq(&rds_ibdev->spinlock);
94764f2dd9SChris Mason list_for_each_entry_rcu(i_ipaddr, &rds_ibdev->ipaddr_list, list) {
9508b48a1eSAndy Grover if (i_ipaddr->ipaddr == ipaddr) {
96764f2dd9SChris Mason list_del_rcu(&i_ipaddr->list);
97764f2dd9SChris Mason to_free = i_ipaddr;
9808b48a1eSAndy Grover break;
9908b48a1eSAndy Grover }
10008b48a1eSAndy Grover }
10108b48a1eSAndy Grover spin_unlock_irq(&rds_ibdev->spinlock);
102764f2dd9SChris Mason
10359fe4606SSantosh Shilimkar if (to_free)
10459fe4606SSantosh Shilimkar kfree_rcu(to_free, rcu);
10508b48a1eSAndy Grover }
10608b48a1eSAndy Grover
rds_ib_update_ipaddr(struct rds_ib_device * rds_ibdev,struct in6_addr * ipaddr)107eee2fa6aSKa-Cheong Poon int rds_ib_update_ipaddr(struct rds_ib_device *rds_ibdev,
108eee2fa6aSKa-Cheong Poon struct in6_addr *ipaddr)
10908b48a1eSAndy Grover {
11008b48a1eSAndy Grover struct rds_ib_device *rds_ibdev_old;
11108b48a1eSAndy Grover
112eee2fa6aSKa-Cheong Poon rds_ibdev_old = rds_ib_get_device(ipaddr->s6_addr32[3]);
113e1f475a7Ssantosh.shilimkar@oracle.com if (!rds_ibdev_old)
114eee2fa6aSKa-Cheong Poon return rds_ib_add_ipaddr(rds_ibdev, ipaddr->s6_addr32[3]);
115e1f475a7Ssantosh.shilimkar@oracle.com
116e1f475a7Ssantosh.shilimkar@oracle.com if (rds_ibdev_old != rds_ibdev) {
117eee2fa6aSKa-Cheong Poon rds_ib_remove_ipaddr(rds_ibdev_old, ipaddr->s6_addr32[3]);
1183e0249f9SZach Brown rds_ib_dev_put(rds_ibdev_old);
119eee2fa6aSKa-Cheong Poon return rds_ib_add_ipaddr(rds_ibdev, ipaddr->s6_addr32[3]);
12008b48a1eSAndy Grover }
121e1f475a7Ssantosh.shilimkar@oracle.com rds_ib_dev_put(rds_ibdev_old);
122e1f475a7Ssantosh.shilimkar@oracle.com
123e1f475a7Ssantosh.shilimkar@oracle.com return 0;
124e1f475a7Ssantosh.shilimkar@oracle.com }
12508b48a1eSAndy Grover
rds_ib_add_conn(struct rds_ib_device * rds_ibdev,struct rds_connection * conn)126745cbccaSAndy Grover void rds_ib_add_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn)
12708b48a1eSAndy Grover {
12808b48a1eSAndy Grover struct rds_ib_connection *ic = conn->c_transport_data;
12908b48a1eSAndy Grover
13008b48a1eSAndy Grover /* conn was previously on the nodev_conns_list */
13108b48a1eSAndy Grover spin_lock_irq(&ib_nodev_conns_lock);
13208b48a1eSAndy Grover BUG_ON(list_empty(&ib_nodev_conns));
13308b48a1eSAndy Grover BUG_ON(list_empty(&ic->ib_node));
13408b48a1eSAndy Grover list_del(&ic->ib_node);
13508b48a1eSAndy Grover
136aef3ea33SDan Carpenter spin_lock(&rds_ibdev->spinlock);
13708b48a1eSAndy Grover list_add_tail(&ic->ib_node, &rds_ibdev->conn_list);
138aef3ea33SDan Carpenter spin_unlock(&rds_ibdev->spinlock);
13908b48a1eSAndy Grover spin_unlock_irq(&ib_nodev_conns_lock);
14008b48a1eSAndy Grover
141745cbccaSAndy Grover ic->rds_ibdev = rds_ibdev;
14250d61ff7SReshetova, Elena refcount_inc(&rds_ibdev->refcount);
14308b48a1eSAndy Grover }
14408b48a1eSAndy Grover
rds_ib_remove_conn(struct rds_ib_device * rds_ibdev,struct rds_connection * conn)145745cbccaSAndy Grover void rds_ib_remove_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn)
146745cbccaSAndy Grover {
147745cbccaSAndy Grover struct rds_ib_connection *ic = conn->c_transport_data;
148745cbccaSAndy Grover
149745cbccaSAndy Grover /* place conn on nodev_conns_list */
150745cbccaSAndy Grover spin_lock(&ib_nodev_conns_lock);
151745cbccaSAndy Grover
152745cbccaSAndy Grover spin_lock_irq(&rds_ibdev->spinlock);
153745cbccaSAndy Grover BUG_ON(list_empty(&ic->ib_node));
154745cbccaSAndy Grover list_del(&ic->ib_node);
155745cbccaSAndy Grover spin_unlock_irq(&rds_ibdev->spinlock);
156745cbccaSAndy Grover
157745cbccaSAndy Grover list_add_tail(&ic->ib_node, &ib_nodev_conns);
158745cbccaSAndy Grover
159745cbccaSAndy Grover spin_unlock(&ib_nodev_conns_lock);
160745cbccaSAndy Grover
161745cbccaSAndy Grover ic->rds_ibdev = NULL;
1623e0249f9SZach Brown rds_ib_dev_put(rds_ibdev);
163745cbccaSAndy Grover }
164745cbccaSAndy Grover
rds_ib_destroy_nodev_conns(void)1658aeb1ba6SZach Brown void rds_ib_destroy_nodev_conns(void)
16608b48a1eSAndy Grover {
16708b48a1eSAndy Grover struct rds_ib_connection *ic, *_ic;
16808b48a1eSAndy Grover LIST_HEAD(tmp_list);
16908b48a1eSAndy Grover
17008b48a1eSAndy Grover /* avoid calling conn_destroy with irqs off */
1718aeb1ba6SZach Brown spin_lock_irq(&ib_nodev_conns_lock);
1728aeb1ba6SZach Brown list_splice(&ib_nodev_conns, &tmp_list);
1738aeb1ba6SZach Brown spin_unlock_irq(&ib_nodev_conns_lock);
17408b48a1eSAndy Grover
175433d308dSAndy Grover list_for_each_entry_safe(ic, _ic, &tmp_list, ib_node)
17608b48a1eSAndy Grover rds_conn_destroy(ic->conn);
17708b48a1eSAndy Grover }
17808b48a1eSAndy Grover
rds_ib_get_mr_info(struct rds_ib_device * rds_ibdev,struct rds_info_rdma_connection * iinfo)17908b48a1eSAndy Grover void rds_ib_get_mr_info(struct rds_ib_device *rds_ibdev, struct rds_info_rdma_connection *iinfo)
18008b48a1eSAndy Grover {
18106766513SSantosh Shilimkar struct rds_ib_mr_pool *pool_1m = rds_ibdev->mr_1m_pool;
18208b48a1eSAndy Grover
18306766513SSantosh Shilimkar iinfo->rdma_mr_max = pool_1m->max_items;
184*07549ee2SMax Gurtovoy iinfo->rdma_mr_size = pool_1m->max_pages;
18508b48a1eSAndy Grover }
18608b48a1eSAndy Grover
187e65d4d96SKa-Cheong Poon #if IS_ENABLED(CONFIG_IPV6)
rds6_ib_get_mr_info(struct rds_ib_device * rds_ibdev,struct rds6_info_rdma_connection * iinfo6)188b7ff8b10SKa-Cheong Poon void rds6_ib_get_mr_info(struct rds_ib_device *rds_ibdev,
189b7ff8b10SKa-Cheong Poon struct rds6_info_rdma_connection *iinfo6)
190b7ff8b10SKa-Cheong Poon {
191b7ff8b10SKa-Cheong Poon struct rds_ib_mr_pool *pool_1m = rds_ibdev->mr_1m_pool;
192b7ff8b10SKa-Cheong Poon
193b7ff8b10SKa-Cheong Poon iinfo6->rdma_mr_max = pool_1m->max_items;
194*07549ee2SMax Gurtovoy iinfo6->rdma_mr_size = pool_1m->max_pages;
195b7ff8b10SKa-Cheong Poon }
196e65d4d96SKa-Cheong Poon #endif
197b7ff8b10SKa-Cheong Poon
rds_ib_reuse_mr(struct rds_ib_mr_pool * pool)198f6df683fSsantosh.shilimkar@oracle.com struct rds_ib_mr *rds_ib_reuse_mr(struct rds_ib_mr_pool *pool)
19908b48a1eSAndy Grover {
20008b48a1eSAndy Grover struct rds_ib_mr *ibmr = NULL;
2011bc144b6SHuang Ying struct llist_node *ret;
202c9467447SGerd Rausch unsigned long flags;
20308b48a1eSAndy Grover
204c9467447SGerd Rausch spin_lock_irqsave(&pool->clean_lock, flags);
2051bc144b6SHuang Ying ret = llist_del_first(&pool->clean_list);
206c9467447SGerd Rausch spin_unlock_irqrestore(&pool->clean_lock, flags);
207db42753aSsantosh.shilimkar@oracle.com if (ret) {
2081bc144b6SHuang Ying ibmr = llist_entry(ret, struct rds_ib_mr, llnode);
209db42753aSsantosh.shilimkar@oracle.com if (pool->pool_type == RDS_IB_MR_8K_POOL)
210db42753aSsantosh.shilimkar@oracle.com rds_ib_stats_inc(s_ib_rdma_mr_8k_reused);
211db42753aSsantosh.shilimkar@oracle.com else
212db42753aSsantosh.shilimkar@oracle.com rds_ib_stats_inc(s_ib_rdma_mr_1m_reused);
213db42753aSsantosh.shilimkar@oracle.com }
21408b48a1eSAndy Grover
21508b48a1eSAndy Grover return ibmr;
21608b48a1eSAndy Grover }
21708b48a1eSAndy Grover
rds_ib_sync_mr(void * trans_private,int direction)21808b48a1eSAndy Grover void rds_ib_sync_mr(void *trans_private, int direction)
21908b48a1eSAndy Grover {
22008b48a1eSAndy Grover struct rds_ib_mr *ibmr = trans_private;
22108b48a1eSAndy Grover struct rds_ib_device *rds_ibdev = ibmr->device;
22208b48a1eSAndy Grover
2232eafa174SHans Westgaard Ry if (ibmr->odp)
2242eafa174SHans Westgaard Ry return;
2252eafa174SHans Westgaard Ry
22608b48a1eSAndy Grover switch (direction) {
22708b48a1eSAndy Grover case DMA_FROM_DEVICE:
22808b48a1eSAndy Grover ib_dma_sync_sg_for_cpu(rds_ibdev->dev, ibmr->sg,
22908b48a1eSAndy Grover ibmr->sg_dma_len, DMA_BIDIRECTIONAL);
23008b48a1eSAndy Grover break;
23108b48a1eSAndy Grover case DMA_TO_DEVICE:
23208b48a1eSAndy Grover ib_dma_sync_sg_for_device(rds_ibdev->dev, ibmr->sg,
23308b48a1eSAndy Grover ibmr->sg_dma_len, DMA_BIDIRECTIONAL);
23408b48a1eSAndy Grover break;
23508b48a1eSAndy Grover }
23608b48a1eSAndy Grover }
23708b48a1eSAndy Grover
__rds_ib_teardown_mr(struct rds_ib_mr * ibmr)238f6df683fSsantosh.shilimkar@oracle.com void __rds_ib_teardown_mr(struct rds_ib_mr *ibmr)
23908b48a1eSAndy Grover {
24008b48a1eSAndy Grover struct rds_ib_device *rds_ibdev = ibmr->device;
24108b48a1eSAndy Grover
24208b48a1eSAndy Grover if (ibmr->sg_dma_len) {
24308b48a1eSAndy Grover ib_dma_unmap_sg(rds_ibdev->dev,
24408b48a1eSAndy Grover ibmr->sg, ibmr->sg_len,
24508b48a1eSAndy Grover DMA_BIDIRECTIONAL);
24608b48a1eSAndy Grover ibmr->sg_dma_len = 0;
24708b48a1eSAndy Grover }
24808b48a1eSAndy Grover
24908b48a1eSAndy Grover /* Release the s/g list */
25008b48a1eSAndy Grover if (ibmr->sg_len) {
25108b48a1eSAndy Grover unsigned int i;
25208b48a1eSAndy Grover
25308b48a1eSAndy Grover for (i = 0; i < ibmr->sg_len; ++i) {
25408b48a1eSAndy Grover struct page *page = sg_page(&ibmr->sg[i]);
25508b48a1eSAndy Grover
25608b48a1eSAndy Grover /* FIXME we need a way to tell a r/w MR
25708b48a1eSAndy Grover * from a r/o MR */
2585c240fa2Ssantosh.shilimkar@oracle.com WARN_ON(!page->mapping && irqs_disabled());
25908b48a1eSAndy Grover set_page_dirty(page);
26008b48a1eSAndy Grover put_page(page);
26108b48a1eSAndy Grover }
26208b48a1eSAndy Grover kfree(ibmr->sg);
26308b48a1eSAndy Grover
26408b48a1eSAndy Grover ibmr->sg = NULL;
26508b48a1eSAndy Grover ibmr->sg_len = 0;
26608b48a1eSAndy Grover }
26708b48a1eSAndy Grover }
26808b48a1eSAndy Grover
rds_ib_teardown_mr(struct rds_ib_mr * ibmr)269f6df683fSsantosh.shilimkar@oracle.com void rds_ib_teardown_mr(struct rds_ib_mr *ibmr)
27008b48a1eSAndy Grover {
27108b48a1eSAndy Grover unsigned int pinned = ibmr->sg_len;
27208b48a1eSAndy Grover
27308b48a1eSAndy Grover __rds_ib_teardown_mr(ibmr);
27408b48a1eSAndy Grover if (pinned) {
27526139dc1SSantosh Shilimkar struct rds_ib_mr_pool *pool = ibmr->pool;
27608b48a1eSAndy Grover
27708b48a1eSAndy Grover atomic_sub(pinned, &pool->free_pinned);
27808b48a1eSAndy Grover }
27908b48a1eSAndy Grover }
28008b48a1eSAndy Grover
rds_ib_flush_goal(struct rds_ib_mr_pool * pool,int free_all)28108b48a1eSAndy Grover static inline unsigned int rds_ib_flush_goal(struct rds_ib_mr_pool *pool, int free_all)
28208b48a1eSAndy Grover {
28308b48a1eSAndy Grover unsigned int item_count;
28408b48a1eSAndy Grover
28508b48a1eSAndy Grover item_count = atomic_read(&pool->item_count);
28608b48a1eSAndy Grover if (free_all)
28708b48a1eSAndy Grover return item_count;
28808b48a1eSAndy Grover
28908b48a1eSAndy Grover return 0;
29008b48a1eSAndy Grover }
29108b48a1eSAndy Grover
29208b48a1eSAndy Grover /*
2931bc144b6SHuang Ying * given an llist of mrs, put them all into the list_head for more processing
2946fa70da6SChris Mason */
llist_append_to_list(struct llist_head * llist,struct list_head * list)2956116c203SWengang Wang static unsigned int llist_append_to_list(struct llist_head *llist,
2966116c203SWengang Wang struct list_head *list)
2976fa70da6SChris Mason {
2986fa70da6SChris Mason struct rds_ib_mr *ibmr;
2991bc144b6SHuang Ying struct llist_node *node;
3001bc144b6SHuang Ying struct llist_node *next;
3016116c203SWengang Wang unsigned int count = 0;
3026fa70da6SChris Mason
3031bc144b6SHuang Ying node = llist_del_all(llist);
3041bc144b6SHuang Ying while (node) {
3051bc144b6SHuang Ying next = node->next;
3061bc144b6SHuang Ying ibmr = llist_entry(node, struct rds_ib_mr, llnode);
3076fa70da6SChris Mason list_add_tail(&ibmr->unmap_list, list);
3081bc144b6SHuang Ying node = next;
3096116c203SWengang Wang count++;
3106fa70da6SChris Mason }
3116116c203SWengang Wang return count;
3126fa70da6SChris Mason }
3136fa70da6SChris Mason
3146fa70da6SChris Mason /*
3151bc144b6SHuang Ying * this takes a list head of mrs and turns it into linked llist nodes
3161bc144b6SHuang Ying * of clusters. Each cluster has linked llist nodes of
3171bc144b6SHuang Ying * MR_CLUSTER_SIZE mrs that are ready for reuse.
3186fa70da6SChris Mason */
list_to_llist_nodes(struct list_head * list,struct llist_node ** nodes_head,struct llist_node ** nodes_tail)319c9467447SGerd Rausch static void list_to_llist_nodes(struct list_head *list,
3201bc144b6SHuang Ying struct llist_node **nodes_head,
3211bc144b6SHuang Ying struct llist_node **nodes_tail)
3226fa70da6SChris Mason {
3236fa70da6SChris Mason struct rds_ib_mr *ibmr;
3241bc144b6SHuang Ying struct llist_node *cur = NULL;
3251bc144b6SHuang Ying struct llist_node **next = nodes_head;
3266fa70da6SChris Mason
3276fa70da6SChris Mason list_for_each_entry(ibmr, list, unmap_list) {
3281bc144b6SHuang Ying cur = &ibmr->llnode;
3291bc144b6SHuang Ying *next = cur;
3301bc144b6SHuang Ying next = &cur->next;
3316fa70da6SChris Mason }
3321bc144b6SHuang Ying *next = NULL;
3331bc144b6SHuang Ying *nodes_tail = cur;
3346fa70da6SChris Mason }
3356fa70da6SChris Mason
3366fa70da6SChris Mason /*
33708b48a1eSAndy Grover * Flush our pool of MRs.
33808b48a1eSAndy Grover * At a minimum, all currently unused MRs are unmapped.
33908b48a1eSAndy Grover * If the number of MRs allocated exceeds the limit, we also try
34008b48a1eSAndy Grover * to free as many MRs as needed to get back to this limit.
34108b48a1eSAndy Grover */
rds_ib_flush_mr_pool(struct rds_ib_mr_pool * pool,int free_all,struct rds_ib_mr ** ibmr_ret)342f6df683fSsantosh.shilimkar@oracle.com int rds_ib_flush_mr_pool(struct rds_ib_mr_pool *pool,
3436fa70da6SChris Mason int free_all, struct rds_ib_mr **ibmr_ret)
34408b48a1eSAndy Grover {
345490ea596Ssantosh.shilimkar@oracle.com struct rds_ib_mr *ibmr;
3461bc144b6SHuang Ying struct llist_node *clean_nodes;
3471bc144b6SHuang Ying struct llist_node *clean_tail;
34808b48a1eSAndy Grover LIST_HEAD(unmap_list);
34908b48a1eSAndy Grover unsigned long unpinned = 0;
3506116c203SWengang Wang unsigned int nfreed = 0, dirty_to_clean = 0, free_goal;
35108b48a1eSAndy Grover
35206766513SSantosh Shilimkar if (pool->pool_type == RDS_IB_MR_8K_POOL)
35306766513SSantosh Shilimkar rds_ib_stats_inc(s_ib_rdma_mr_8k_pool_flush);
35406766513SSantosh Shilimkar else
35506766513SSantosh Shilimkar rds_ib_stats_inc(s_ib_rdma_mr_1m_pool_flush);
35608b48a1eSAndy Grover
3576fa70da6SChris Mason if (ibmr_ret) {
3586fa70da6SChris Mason DEFINE_WAIT(wait);
3596fa70da6SChris Mason while (!mutex_trylock(&pool->flush_lock)) {
360f6df683fSsantosh.shilimkar@oracle.com ibmr = rds_ib_reuse_mr(pool);
3616fa70da6SChris Mason if (ibmr) {
3626fa70da6SChris Mason *ibmr_ret = ibmr;
3636fa70da6SChris Mason finish_wait(&pool->flush_wait, &wait);
3646fa70da6SChris Mason goto out_nolock;
3656fa70da6SChris Mason }
3666fa70da6SChris Mason
3676fa70da6SChris Mason prepare_to_wait(&pool->flush_wait, &wait,
3686fa70da6SChris Mason TASK_UNINTERRUPTIBLE);
3691bc144b6SHuang Ying if (llist_empty(&pool->clean_list))
3706fa70da6SChris Mason schedule();
3716fa70da6SChris Mason
372f6df683fSsantosh.shilimkar@oracle.com ibmr = rds_ib_reuse_mr(pool);
3736fa70da6SChris Mason if (ibmr) {
3746fa70da6SChris Mason *ibmr_ret = ibmr;
3756fa70da6SChris Mason finish_wait(&pool->flush_wait, &wait);
3766fa70da6SChris Mason goto out_nolock;
3776fa70da6SChris Mason }
3786fa70da6SChris Mason }
3796fa70da6SChris Mason finish_wait(&pool->flush_wait, &wait);
3806fa70da6SChris Mason } else
38108b48a1eSAndy Grover mutex_lock(&pool->flush_lock);
38208b48a1eSAndy Grover
3836fa70da6SChris Mason if (ibmr_ret) {
384f6df683fSsantosh.shilimkar@oracle.com ibmr = rds_ib_reuse_mr(pool);
3856fa70da6SChris Mason if (ibmr) {
3866fa70da6SChris Mason *ibmr_ret = ibmr;
3876fa70da6SChris Mason goto out;
3886fa70da6SChris Mason }
3896fa70da6SChris Mason }
3906fa70da6SChris Mason
39108b48a1eSAndy Grover /* Get the list of all MRs to be dropped. Ordering matters -
3926fa70da6SChris Mason * we want to put drop_list ahead of free_list.
3936fa70da6SChris Mason */
3946116c203SWengang Wang dirty_to_clean = llist_append_to_list(&pool->drop_list, &unmap_list);
3956116c203SWengang Wang dirty_to_clean += llist_append_to_list(&pool->free_list, &unmap_list);
396c9467447SGerd Rausch if (free_all) {
397c9467447SGerd Rausch unsigned long flags;
398c9467447SGerd Rausch
399c9467447SGerd Rausch spin_lock_irqsave(&pool->clean_lock, flags);
4001bc144b6SHuang Ying llist_append_to_list(&pool->clean_list, &unmap_list);
401c9467447SGerd Rausch spin_unlock_irqrestore(&pool->clean_lock, flags);
402c9467447SGerd Rausch }
40308b48a1eSAndy Grover
40408b48a1eSAndy Grover free_goal = rds_ib_flush_goal(pool, free_all);
40508b48a1eSAndy Grover
40608b48a1eSAndy Grover if (list_empty(&unmap_list))
40708b48a1eSAndy Grover goto out;
40808b48a1eSAndy Grover
4091659185fSAvinash Repaka rds_ib_unreg_frmr(&unmap_list, &nfreed, &unpinned, free_goal);
41008b48a1eSAndy Grover
4116fa70da6SChris Mason if (!list_empty(&unmap_list)) {
412c9467447SGerd Rausch unsigned long flags;
4136fa70da6SChris Mason
414c9467447SGerd Rausch list_to_llist_nodes(&unmap_list, &clean_nodes, &clean_tail);
41585cb9287SZhu Yanjun if (ibmr_ret) {
4161bc144b6SHuang Ying *ibmr_ret = llist_entry(clean_nodes, struct rds_ib_mr, llnode);
41785cb9287SZhu Yanjun clean_nodes = clean_nodes->next;
41885cb9287SZhu Yanjun }
4191bc144b6SHuang Ying /* more than one entry in llist nodes */
420c9467447SGerd Rausch if (clean_nodes) {
421c9467447SGerd Rausch spin_lock_irqsave(&pool->clean_lock, flags);
42285cb9287SZhu Yanjun llist_add_batch(clean_nodes, clean_tail,
42385cb9287SZhu Yanjun &pool->clean_list);
424c9467447SGerd Rausch spin_unlock_irqrestore(&pool->clean_lock, flags);
425c9467447SGerd Rausch }
4266fa70da6SChris Mason }
42708b48a1eSAndy Grover
42808b48a1eSAndy Grover atomic_sub(unpinned, &pool->free_pinned);
4296116c203SWengang Wang atomic_sub(dirty_to_clean, &pool->dirty_count);
43008b48a1eSAndy Grover atomic_sub(nfreed, &pool->item_count);
43108b48a1eSAndy Grover
43208b48a1eSAndy Grover out:
43308b48a1eSAndy Grover mutex_unlock(&pool->flush_lock);
4346fa70da6SChris Mason if (waitqueue_active(&pool->flush_wait))
4356fa70da6SChris Mason wake_up(&pool->flush_wait);
4366fa70da6SChris Mason out_nolock:
437490ea596Ssantosh.shilimkar@oracle.com return 0;
438490ea596Ssantosh.shilimkar@oracle.com }
439490ea596Ssantosh.shilimkar@oracle.com
rds_ib_try_reuse_ibmr(struct rds_ib_mr_pool * pool)440490ea596Ssantosh.shilimkar@oracle.com struct rds_ib_mr *rds_ib_try_reuse_ibmr(struct rds_ib_mr_pool *pool)
441490ea596Ssantosh.shilimkar@oracle.com {
442490ea596Ssantosh.shilimkar@oracle.com struct rds_ib_mr *ibmr = NULL;
443490ea596Ssantosh.shilimkar@oracle.com int iter = 0;
444490ea596Ssantosh.shilimkar@oracle.com
445490ea596Ssantosh.shilimkar@oracle.com while (1) {
446490ea596Ssantosh.shilimkar@oracle.com ibmr = rds_ib_reuse_mr(pool);
447490ea596Ssantosh.shilimkar@oracle.com if (ibmr)
448490ea596Ssantosh.shilimkar@oracle.com return ibmr;
449490ea596Ssantosh.shilimkar@oracle.com
450490ea596Ssantosh.shilimkar@oracle.com if (atomic_inc_return(&pool->item_count) <= pool->max_items)
451490ea596Ssantosh.shilimkar@oracle.com break;
452490ea596Ssantosh.shilimkar@oracle.com
453490ea596Ssantosh.shilimkar@oracle.com atomic_dec(&pool->item_count);
454490ea596Ssantosh.shilimkar@oracle.com
455490ea596Ssantosh.shilimkar@oracle.com if (++iter > 2) {
456490ea596Ssantosh.shilimkar@oracle.com if (pool->pool_type == RDS_IB_MR_8K_POOL)
457490ea596Ssantosh.shilimkar@oracle.com rds_ib_stats_inc(s_ib_rdma_mr_8k_pool_depleted);
458490ea596Ssantosh.shilimkar@oracle.com else
459490ea596Ssantosh.shilimkar@oracle.com rds_ib_stats_inc(s_ib_rdma_mr_1m_pool_depleted);
460aea01a22SGerd Rausch break;
461490ea596Ssantosh.shilimkar@oracle.com }
462490ea596Ssantosh.shilimkar@oracle.com
463490ea596Ssantosh.shilimkar@oracle.com /* We do have some empty MRs. Flush them out. */
464490ea596Ssantosh.shilimkar@oracle.com if (pool->pool_type == RDS_IB_MR_8K_POOL)
465490ea596Ssantosh.shilimkar@oracle.com rds_ib_stats_inc(s_ib_rdma_mr_8k_pool_wait);
466490ea596Ssantosh.shilimkar@oracle.com else
467490ea596Ssantosh.shilimkar@oracle.com rds_ib_stats_inc(s_ib_rdma_mr_1m_pool_wait);
468490ea596Ssantosh.shilimkar@oracle.com
469490ea596Ssantosh.shilimkar@oracle.com rds_ib_flush_mr_pool(pool, 0, &ibmr);
470490ea596Ssantosh.shilimkar@oracle.com if (ibmr)
471490ea596Ssantosh.shilimkar@oracle.com return ibmr;
472490ea596Ssantosh.shilimkar@oracle.com }
473490ea596Ssantosh.shilimkar@oracle.com
474aea01a22SGerd Rausch return NULL;
47508b48a1eSAndy Grover }
47608b48a1eSAndy Grover
rds_ib_mr_pool_flush_worker(struct work_struct * work)47708b48a1eSAndy Grover static void rds_ib_mr_pool_flush_worker(struct work_struct *work)
47808b48a1eSAndy Grover {
4797a0ff5dbSChris Mason struct rds_ib_mr_pool *pool = container_of(work, struct rds_ib_mr_pool, flush_worker.work);
48008b48a1eSAndy Grover
4816fa70da6SChris Mason rds_ib_flush_mr_pool(pool, 0, NULL);
48208b48a1eSAndy Grover }
48308b48a1eSAndy Grover
rds_ib_free_mr(void * trans_private,int invalidate)48408b48a1eSAndy Grover void rds_ib_free_mr(void *trans_private, int invalidate)
48508b48a1eSAndy Grover {
48608b48a1eSAndy Grover struct rds_ib_mr *ibmr = trans_private;
48726139dc1SSantosh Shilimkar struct rds_ib_mr_pool *pool = ibmr->pool;
48808b48a1eSAndy Grover struct rds_ib_device *rds_ibdev = ibmr->device;
48908b48a1eSAndy Grover
49008b48a1eSAndy Grover rdsdebug("RDS/IB: free_mr nents %u\n", ibmr->sg_len);
49108b48a1eSAndy Grover
4922eafa174SHans Westgaard Ry if (ibmr->odp) {
4932eafa174SHans Westgaard Ry /* A MR created and marked as use_once. We use delayed work,
4942eafa174SHans Westgaard Ry * because there is a change that we are in interrupt and can't
4952eafa174SHans Westgaard Ry * call to ib_dereg_mr() directly.
4962eafa174SHans Westgaard Ry */
4972eafa174SHans Westgaard Ry INIT_DELAYED_WORK(&ibmr->work, rds_ib_odp_mr_worker);
4982eafa174SHans Westgaard Ry queue_delayed_work(rds_ib_mr_wq, &ibmr->work, 0);
4992eafa174SHans Westgaard Ry return;
5002eafa174SHans Westgaard Ry }
5012eafa174SHans Westgaard Ry
50208b48a1eSAndy Grover /* Return it to the pool's free list */
5031659185fSAvinash Repaka rds_ib_free_frmr_list(ibmr);
50408b48a1eSAndy Grover
50508b48a1eSAndy Grover atomic_add(ibmr->sg_len, &pool->free_pinned);
50608b48a1eSAndy Grover atomic_inc(&pool->dirty_count);
50708b48a1eSAndy Grover
50808b48a1eSAndy Grover /* If we've pinned too many pages, request a flush */
509f64f9e71SJoe Perches if (atomic_read(&pool->free_pinned) >= pool->max_free_pinned ||
510ef5217a6Ssantosh.shilimkar@oracle.com atomic_read(&pool->dirty_count) >= pool->max_items / 5)
511f6df683fSsantosh.shilimkar@oracle.com queue_delayed_work(rds_ib_mr_wq, &pool->flush_worker, 10);
51208b48a1eSAndy Grover
51308b48a1eSAndy Grover if (invalidate) {
51408b48a1eSAndy Grover if (likely(!in_interrupt())) {
5156fa70da6SChris Mason rds_ib_flush_mr_pool(pool, 0, NULL);
51608b48a1eSAndy Grover } else {
51708b48a1eSAndy Grover /* We get here if the user created a MR marked
518ad1d7dc0Ssantosh.shilimkar@oracle.com * as use_once and invalidate at the same time.
519ad1d7dc0Ssantosh.shilimkar@oracle.com */
520f6df683fSsantosh.shilimkar@oracle.com queue_delayed_work(rds_ib_mr_wq,
521ad1d7dc0Ssantosh.shilimkar@oracle.com &pool->flush_worker, 10);
52208b48a1eSAndy Grover }
52308b48a1eSAndy Grover }
5243e0249f9SZach Brown
5253e0249f9SZach Brown rds_ib_dev_put(rds_ibdev);
52608b48a1eSAndy Grover }
52708b48a1eSAndy Grover
rds_ib_flush_mrs(void)52808b48a1eSAndy Grover void rds_ib_flush_mrs(void)
52908b48a1eSAndy Grover {
53008b48a1eSAndy Grover struct rds_ib_device *rds_ibdev;
53108b48a1eSAndy Grover
532ea819867SZach Brown down_read(&rds_ib_devices_lock);
53308b48a1eSAndy Grover list_for_each_entry(rds_ibdev, &rds_ib_devices, list) {
53406766513SSantosh Shilimkar if (rds_ibdev->mr_8k_pool)
53506766513SSantosh Shilimkar rds_ib_flush_mr_pool(rds_ibdev->mr_8k_pool, 0, NULL);
53608b48a1eSAndy Grover
53706766513SSantosh Shilimkar if (rds_ibdev->mr_1m_pool)
53806766513SSantosh Shilimkar rds_ib_flush_mr_pool(rds_ibdev->mr_1m_pool, 0, NULL);
53908b48a1eSAndy Grover }
540ea819867SZach Brown up_read(&rds_ib_devices_lock);
54108b48a1eSAndy Grover }
54208b48a1eSAndy Grover
rds_ib_get_lkey(void * trans_private)5432eafa174SHans Westgaard Ry u32 rds_ib_get_lkey(void *trans_private)
5442eafa174SHans Westgaard Ry {
5452eafa174SHans Westgaard Ry struct rds_ib_mr *ibmr = trans_private;
5462eafa174SHans Westgaard Ry
5472eafa174SHans Westgaard Ry return ibmr->u.mr->lkey;
5482eafa174SHans Westgaard Ry }
5492eafa174SHans Westgaard Ry
rds_ib_get_mr(struct scatterlist * sg,unsigned long nents,struct rds_sock * rs,u32 * key_ret,struct rds_connection * conn,u64 start,u64 length,int need_odp)55008b48a1eSAndy Grover void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
5519e630bcbSAvinash Repaka struct rds_sock *rs, u32 *key_ret,
5522eafa174SHans Westgaard Ry struct rds_connection *conn,
5532eafa174SHans Westgaard Ry u64 start, u64 length, int need_odp)
55408b48a1eSAndy Grover {
55508b48a1eSAndy Grover struct rds_ib_device *rds_ibdev;
55608b48a1eSAndy Grover struct rds_ib_mr *ibmr = NULL;
5579e630bcbSAvinash Repaka struct rds_ib_connection *ic = NULL;
55808b48a1eSAndy Grover int ret;
55908b48a1eSAndy Grover
560eee2fa6aSKa-Cheong Poon rds_ibdev = rds_ib_get_device(rs->rs_bound_addr.s6_addr32[3]);
56108b48a1eSAndy Grover if (!rds_ibdev) {
56208b48a1eSAndy Grover ret = -ENODEV;
56308b48a1eSAndy Grover goto out;
56408b48a1eSAndy Grover }
56508b48a1eSAndy Grover
5662eafa174SHans Westgaard Ry if (need_odp == ODP_ZEROBASED || need_odp == ODP_VIRTUAL) {
5672eafa174SHans Westgaard Ry u64 virt_addr = need_odp == ODP_ZEROBASED ? 0 : start;
5682eafa174SHans Westgaard Ry int access_flags =
5692eafa174SHans Westgaard Ry (IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_READ |
5702eafa174SHans Westgaard Ry IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_ATOMIC |
5712eafa174SHans Westgaard Ry IB_ACCESS_ON_DEMAND);
572b2dfc676SHans Westgaard Ry struct ib_sge sge = {};
5732eafa174SHans Westgaard Ry struct ib_mr *ib_mr;
5742eafa174SHans Westgaard Ry
5752eafa174SHans Westgaard Ry if (!rds_ibdev->odp_capable) {
5762eafa174SHans Westgaard Ry ret = -EOPNOTSUPP;
5772eafa174SHans Westgaard Ry goto out;
5782eafa174SHans Westgaard Ry }
5792eafa174SHans Westgaard Ry
5802eafa174SHans Westgaard Ry ib_mr = ib_reg_user_mr(rds_ibdev->pd, start, length, virt_addr,
5812eafa174SHans Westgaard Ry access_flags);
5822eafa174SHans Westgaard Ry
5832eafa174SHans Westgaard Ry if (IS_ERR(ib_mr)) {
5842eafa174SHans Westgaard Ry rdsdebug("rds_ib_get_user_mr returned %d\n",
5852eafa174SHans Westgaard Ry IS_ERR(ib_mr));
5862eafa174SHans Westgaard Ry ret = PTR_ERR(ib_mr);
5872eafa174SHans Westgaard Ry goto out;
5882eafa174SHans Westgaard Ry }
5892eafa174SHans Westgaard Ry if (key_ret)
5902eafa174SHans Westgaard Ry *key_ret = ib_mr->rkey;
5912eafa174SHans Westgaard Ry
5922eafa174SHans Westgaard Ry ibmr = kzalloc(sizeof(*ibmr), GFP_KERNEL);
5932eafa174SHans Westgaard Ry if (!ibmr) {
5942eafa174SHans Westgaard Ry ib_dereg_mr(ib_mr);
5952eafa174SHans Westgaard Ry ret = -ENOMEM;
5962eafa174SHans Westgaard Ry goto out;
5972eafa174SHans Westgaard Ry }
5982eafa174SHans Westgaard Ry ibmr->u.mr = ib_mr;
5992eafa174SHans Westgaard Ry ibmr->odp = 1;
600b2dfc676SHans Westgaard Ry
601b2dfc676SHans Westgaard Ry sge.addr = virt_addr;
602b2dfc676SHans Westgaard Ry sge.length = length;
603b2dfc676SHans Westgaard Ry sge.lkey = ib_mr->lkey;
604b2dfc676SHans Westgaard Ry
605b2dfc676SHans Westgaard Ry ib_advise_mr(rds_ibdev->pd,
606b2dfc676SHans Westgaard Ry IB_UVERBS_ADVISE_MR_ADVICE_PREFETCH_WRITE,
607b2dfc676SHans Westgaard Ry IB_UVERBS_ADVISE_MR_FLAG_FLUSH, &sge, 1);
6082eafa174SHans Westgaard Ry return ibmr;
6092eafa174SHans Westgaard Ry }
6102eafa174SHans Westgaard Ry
6119e630bcbSAvinash Repaka if (conn)
6129e630bcbSAvinash Repaka ic = conn->c_transport_data;
6139e630bcbSAvinash Repaka
61406766513SSantosh Shilimkar if (!rds_ibdev->mr_8k_pool || !rds_ibdev->mr_1m_pool) {
61508b48a1eSAndy Grover ret = -ENODEV;
61608b48a1eSAndy Grover goto out;
61708b48a1eSAndy Grover }
61808b48a1eSAndy Grover
6191659185fSAvinash Repaka ibmr = rds_ib_reg_frmr(rds_ibdev, ic, sg, nents, key_ret);
6209e630bcbSAvinash Repaka if (IS_ERR(ibmr)) {
6219e630bcbSAvinash Repaka ret = PTR_ERR(ibmr);
6229e630bcbSAvinash Repaka pr_warn("RDS/IB: rds_ib_get_mr failed (errno=%d)\n", ret);
6239e630bcbSAvinash Repaka } else {
6249e630bcbSAvinash Repaka return ibmr;
6259e630bcbSAvinash Repaka }
62608b48a1eSAndy Grover
62708b48a1eSAndy Grover out:
6283e0249f9SZach Brown if (rds_ibdev)
6293e0249f9SZach Brown rds_ib_dev_put(rds_ibdev);
630490ea596Ssantosh.shilimkar@oracle.com
6319e630bcbSAvinash Repaka return ERR_PTR(ret);
63208b48a1eSAndy Grover }
6336fa70da6SChris Mason
rds_ib_destroy_mr_pool(struct rds_ib_mr_pool * pool)634f6df683fSsantosh.shilimkar@oracle.com void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *pool)
635f6df683fSsantosh.shilimkar@oracle.com {
636f6df683fSsantosh.shilimkar@oracle.com cancel_delayed_work_sync(&pool->flush_worker);
637f6df683fSsantosh.shilimkar@oracle.com rds_ib_flush_mr_pool(pool, 1, NULL);
638f6df683fSsantosh.shilimkar@oracle.com WARN_ON(atomic_read(&pool->item_count));
639f6df683fSsantosh.shilimkar@oracle.com WARN_ON(atomic_read(&pool->free_pinned));
640f6df683fSsantosh.shilimkar@oracle.com kfree(pool);
641f6df683fSsantosh.shilimkar@oracle.com }
642f6df683fSsantosh.shilimkar@oracle.com
rds_ib_create_mr_pool(struct rds_ib_device * rds_ibdev,int pool_type)643f6df683fSsantosh.shilimkar@oracle.com struct rds_ib_mr_pool *rds_ib_create_mr_pool(struct rds_ib_device *rds_ibdev,
644f6df683fSsantosh.shilimkar@oracle.com int pool_type)
645f6df683fSsantosh.shilimkar@oracle.com {
646f6df683fSsantosh.shilimkar@oracle.com struct rds_ib_mr_pool *pool;
647f6df683fSsantosh.shilimkar@oracle.com
648f6df683fSsantosh.shilimkar@oracle.com pool = kzalloc(sizeof(*pool), GFP_KERNEL);
649f6df683fSsantosh.shilimkar@oracle.com if (!pool)
650f6df683fSsantosh.shilimkar@oracle.com return ERR_PTR(-ENOMEM);
651f6df683fSsantosh.shilimkar@oracle.com
652f6df683fSsantosh.shilimkar@oracle.com pool->pool_type = pool_type;
653f6df683fSsantosh.shilimkar@oracle.com init_llist_head(&pool->free_list);
654f6df683fSsantosh.shilimkar@oracle.com init_llist_head(&pool->drop_list);
655f6df683fSsantosh.shilimkar@oracle.com init_llist_head(&pool->clean_list);
656c9467447SGerd Rausch spin_lock_init(&pool->clean_lock);
657f6df683fSsantosh.shilimkar@oracle.com mutex_init(&pool->flush_lock);
658f6df683fSsantosh.shilimkar@oracle.com init_waitqueue_head(&pool->flush_wait);
659f6df683fSsantosh.shilimkar@oracle.com INIT_DELAYED_WORK(&pool->flush_worker, rds_ib_mr_pool_flush_worker);
660f6df683fSsantosh.shilimkar@oracle.com
661f6df683fSsantosh.shilimkar@oracle.com if (pool_type == RDS_IB_MR_1M_POOL) {
662f6df683fSsantosh.shilimkar@oracle.com /* +1 allows for unaligned MRs */
663*07549ee2SMax Gurtovoy pool->max_pages = RDS_MR_1M_MSG_SIZE + 1;
664b1fb67faSAvinash Repaka pool->max_items = rds_ibdev->max_1m_mrs;
665f6df683fSsantosh.shilimkar@oracle.com } else {
666f6df683fSsantosh.shilimkar@oracle.com /* pool_type == RDS_IB_MR_8K_POOL */
667*07549ee2SMax Gurtovoy pool->max_pages = RDS_MR_8K_MSG_SIZE + 1;
668b1fb67faSAvinash Repaka pool->max_items = rds_ibdev->max_8k_mrs;
669f6df683fSsantosh.shilimkar@oracle.com }
670f6df683fSsantosh.shilimkar@oracle.com
671*07549ee2SMax Gurtovoy pool->max_free_pinned = pool->max_items * pool->max_pages / 4;
672f6df683fSsantosh.shilimkar@oracle.com pool->max_items_soft = rds_ibdev->max_mrs * 3 / 4;
673f6df683fSsantosh.shilimkar@oracle.com
674f6df683fSsantosh.shilimkar@oracle.com return pool;
675f6df683fSsantosh.shilimkar@oracle.com }
676f6df683fSsantosh.shilimkar@oracle.com
rds_ib_mr_init(void)677f6df683fSsantosh.shilimkar@oracle.com int rds_ib_mr_init(void)
678f6df683fSsantosh.shilimkar@oracle.com {
679231edca9SBhaktipriya Shridhar rds_ib_mr_wq = alloc_workqueue("rds_mr_flushd", WQ_MEM_RECLAIM, 0);
680f6df683fSsantosh.shilimkar@oracle.com if (!rds_ib_mr_wq)
681f6df683fSsantosh.shilimkar@oracle.com return -ENOMEM;
682f6df683fSsantosh.shilimkar@oracle.com return 0;
683f6df683fSsantosh.shilimkar@oracle.com }
684f6df683fSsantosh.shilimkar@oracle.com
685f6df683fSsantosh.shilimkar@oracle.com /* By the time this is called all the IB devices should have been torn down and
686f6df683fSsantosh.shilimkar@oracle.com * had their pools freed. As each pool is freed its work struct is waited on,
687f6df683fSsantosh.shilimkar@oracle.com * so the pool flushing work queue should be idle by the time we get here.
688f6df683fSsantosh.shilimkar@oracle.com */
rds_ib_mr_exit(void)689f6df683fSsantosh.shilimkar@oracle.com void rds_ib_mr_exit(void)
690f6df683fSsantosh.shilimkar@oracle.com {
691f6df683fSsantosh.shilimkar@oracle.com destroy_workqueue(rds_ib_mr_wq);
692f6df683fSsantosh.shilimkar@oracle.com }
6932eafa174SHans Westgaard Ry
rds_ib_odp_mr_worker(struct work_struct * work)6942eafa174SHans Westgaard Ry static void rds_ib_odp_mr_worker(struct work_struct *work)
6952eafa174SHans Westgaard Ry {
6962eafa174SHans Westgaard Ry struct rds_ib_mr *ibmr;
6972eafa174SHans Westgaard Ry
6982eafa174SHans Westgaard Ry ibmr = container_of(work, struct rds_ib_mr, work.work);
6992eafa174SHans Westgaard Ry ib_dereg_mr(ibmr->u.mr);
7002eafa174SHans Westgaard Ry kfree(ibmr);
7012eafa174SHans Westgaard Ry }
702