xref: /openbmc/linux/drivers/infiniband/hw/hfi1/mmu_rb.c (revision f48ad614c100783be1e7e777dc36328001b83999)
1*f48ad614SDennis Dalessandro /*
2*f48ad614SDennis Dalessandro  * Copyright(c) 2016 Intel Corporation.
3*f48ad614SDennis Dalessandro  *
4*f48ad614SDennis Dalessandro  * This file is provided under a dual BSD/GPLv2 license.  When using or
5*f48ad614SDennis Dalessandro  * redistributing this file, you may do so under either license.
6*f48ad614SDennis Dalessandro  *
7*f48ad614SDennis Dalessandro  * GPL LICENSE SUMMARY
8*f48ad614SDennis Dalessandro  *
9*f48ad614SDennis Dalessandro  * This program is free software; you can redistribute it and/or modify
10*f48ad614SDennis Dalessandro  * it under the terms of version 2 of the GNU General Public License as
11*f48ad614SDennis Dalessandro  * published by the Free Software Foundation.
12*f48ad614SDennis Dalessandro  *
13*f48ad614SDennis Dalessandro  * This program is distributed in the hope that it will be useful, but
14*f48ad614SDennis Dalessandro  * WITHOUT ANY WARRANTY; without even the implied warranty of
15*f48ad614SDennis Dalessandro  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*f48ad614SDennis Dalessandro  * General Public License for more details.
17*f48ad614SDennis Dalessandro  *
18*f48ad614SDennis Dalessandro  * BSD LICENSE
19*f48ad614SDennis Dalessandro  *
20*f48ad614SDennis Dalessandro  * Redistribution and use in source and binary forms, with or without
21*f48ad614SDennis Dalessandro  * modification, are permitted provided that the following conditions
22*f48ad614SDennis Dalessandro  * are met:
23*f48ad614SDennis Dalessandro  *
24*f48ad614SDennis Dalessandro  *  - Redistributions of source code must retain the above copyright
25*f48ad614SDennis Dalessandro  *    notice, this list of conditions and the following disclaimer.
26*f48ad614SDennis Dalessandro  *  - Redistributions in binary form must reproduce the above copyright
27*f48ad614SDennis Dalessandro  *    notice, this list of conditions and the following disclaimer in
28*f48ad614SDennis Dalessandro  *    the documentation and/or other materials provided with the
29*f48ad614SDennis Dalessandro  *    distribution.
30*f48ad614SDennis Dalessandro  *  - Neither the name of Intel Corporation nor the names of its
31*f48ad614SDennis Dalessandro  *    contributors may be used to endorse or promote products derived
32*f48ad614SDennis Dalessandro  *    from this software without specific prior written permission.
33*f48ad614SDennis Dalessandro  *
34*f48ad614SDennis Dalessandro  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35*f48ad614SDennis Dalessandro  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36*f48ad614SDennis Dalessandro  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37*f48ad614SDennis Dalessandro  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
38*f48ad614SDennis Dalessandro  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39*f48ad614SDennis Dalessandro  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40*f48ad614SDennis Dalessandro  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41*f48ad614SDennis Dalessandro  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42*f48ad614SDennis Dalessandro  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43*f48ad614SDennis Dalessandro  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44*f48ad614SDennis Dalessandro  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45*f48ad614SDennis Dalessandro  *
46*f48ad614SDennis Dalessandro  */
47*f48ad614SDennis Dalessandro #include <linux/list.h>
48*f48ad614SDennis Dalessandro #include <linux/rculist.h>
49*f48ad614SDennis Dalessandro #include <linux/mmu_notifier.h>
50*f48ad614SDennis Dalessandro #include <linux/interval_tree_generic.h>
51*f48ad614SDennis Dalessandro 
52*f48ad614SDennis Dalessandro #include "mmu_rb.h"
53*f48ad614SDennis Dalessandro #include "trace.h"
54*f48ad614SDennis Dalessandro 
55*f48ad614SDennis Dalessandro struct mmu_rb_handler {
56*f48ad614SDennis Dalessandro 	struct list_head list;
57*f48ad614SDennis Dalessandro 	struct mmu_notifier mn;
58*f48ad614SDennis Dalessandro 	struct rb_root *root;
59*f48ad614SDennis Dalessandro 	spinlock_t lock;        /* protect the RB tree */
60*f48ad614SDennis Dalessandro 	struct mmu_rb_ops *ops;
61*f48ad614SDennis Dalessandro };
62*f48ad614SDennis Dalessandro 
63*f48ad614SDennis Dalessandro static LIST_HEAD(mmu_rb_handlers);
64*f48ad614SDennis Dalessandro static DEFINE_SPINLOCK(mmu_rb_lock); /* protect mmu_rb_handlers list */
65*f48ad614SDennis Dalessandro 
66*f48ad614SDennis Dalessandro static unsigned long mmu_node_start(struct mmu_rb_node *);
67*f48ad614SDennis Dalessandro static unsigned long mmu_node_last(struct mmu_rb_node *);
68*f48ad614SDennis Dalessandro static struct mmu_rb_handler *find_mmu_handler(struct rb_root *);
69*f48ad614SDennis Dalessandro static inline void mmu_notifier_page(struct mmu_notifier *, struct mm_struct *,
70*f48ad614SDennis Dalessandro 				     unsigned long);
71*f48ad614SDennis Dalessandro static inline void mmu_notifier_range_start(struct mmu_notifier *,
72*f48ad614SDennis Dalessandro 					    struct mm_struct *,
73*f48ad614SDennis Dalessandro 					    unsigned long, unsigned long);
74*f48ad614SDennis Dalessandro static void mmu_notifier_mem_invalidate(struct mmu_notifier *,
75*f48ad614SDennis Dalessandro 					struct mm_struct *,
76*f48ad614SDennis Dalessandro 					unsigned long, unsigned long);
77*f48ad614SDennis Dalessandro static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *,
78*f48ad614SDennis Dalessandro 					   unsigned long, unsigned long);
79*f48ad614SDennis Dalessandro 
80*f48ad614SDennis Dalessandro static struct mmu_notifier_ops mn_opts = {
81*f48ad614SDennis Dalessandro 	.invalidate_page = mmu_notifier_page,
82*f48ad614SDennis Dalessandro 	.invalidate_range_start = mmu_notifier_range_start,
83*f48ad614SDennis Dalessandro };
84*f48ad614SDennis Dalessandro 
85*f48ad614SDennis Dalessandro INTERVAL_TREE_DEFINE(struct mmu_rb_node, node, unsigned long, __last,
86*f48ad614SDennis Dalessandro 		     mmu_node_start, mmu_node_last, static, __mmu_int_rb);
87*f48ad614SDennis Dalessandro 
88*f48ad614SDennis Dalessandro static unsigned long mmu_node_start(struct mmu_rb_node *node)
89*f48ad614SDennis Dalessandro {
90*f48ad614SDennis Dalessandro 	return node->addr & PAGE_MASK;
91*f48ad614SDennis Dalessandro }
92*f48ad614SDennis Dalessandro 
93*f48ad614SDennis Dalessandro static unsigned long mmu_node_last(struct mmu_rb_node *node)
94*f48ad614SDennis Dalessandro {
95*f48ad614SDennis Dalessandro 	return PAGE_ALIGN(node->addr + node->len) - 1;
96*f48ad614SDennis Dalessandro }
97*f48ad614SDennis Dalessandro 
98*f48ad614SDennis Dalessandro int hfi1_mmu_rb_register(struct rb_root *root, struct mmu_rb_ops *ops)
99*f48ad614SDennis Dalessandro {
100*f48ad614SDennis Dalessandro 	struct mmu_rb_handler *handlr;
101*f48ad614SDennis Dalessandro 
102*f48ad614SDennis Dalessandro 	if (!ops->invalidate)
103*f48ad614SDennis Dalessandro 		return -EINVAL;
104*f48ad614SDennis Dalessandro 
105*f48ad614SDennis Dalessandro 	handlr = kmalloc(sizeof(*handlr), GFP_KERNEL);
106*f48ad614SDennis Dalessandro 	if (!handlr)
107*f48ad614SDennis Dalessandro 		return -ENOMEM;
108*f48ad614SDennis Dalessandro 
109*f48ad614SDennis Dalessandro 	handlr->root = root;
110*f48ad614SDennis Dalessandro 	handlr->ops = ops;
111*f48ad614SDennis Dalessandro 	INIT_HLIST_NODE(&handlr->mn.hlist);
112*f48ad614SDennis Dalessandro 	spin_lock_init(&handlr->lock);
113*f48ad614SDennis Dalessandro 	handlr->mn.ops = &mn_opts;
114*f48ad614SDennis Dalessandro 	spin_lock(&mmu_rb_lock);
115*f48ad614SDennis Dalessandro 	list_add_tail_rcu(&handlr->list, &mmu_rb_handlers);
116*f48ad614SDennis Dalessandro 	spin_unlock(&mmu_rb_lock);
117*f48ad614SDennis Dalessandro 
118*f48ad614SDennis Dalessandro 	return mmu_notifier_register(&handlr->mn, current->mm);
119*f48ad614SDennis Dalessandro }
120*f48ad614SDennis Dalessandro 
121*f48ad614SDennis Dalessandro void hfi1_mmu_rb_unregister(struct rb_root *root)
122*f48ad614SDennis Dalessandro {
123*f48ad614SDennis Dalessandro 	struct mmu_rb_handler *handler = find_mmu_handler(root);
124*f48ad614SDennis Dalessandro 	unsigned long flags;
125*f48ad614SDennis Dalessandro 
126*f48ad614SDennis Dalessandro 	if (!handler)
127*f48ad614SDennis Dalessandro 		return;
128*f48ad614SDennis Dalessandro 
129*f48ad614SDennis Dalessandro 	/* Unregister first so we don't get any more notifications. */
130*f48ad614SDennis Dalessandro 	if (current->mm)
131*f48ad614SDennis Dalessandro 		mmu_notifier_unregister(&handler->mn, current->mm);
132*f48ad614SDennis Dalessandro 
133*f48ad614SDennis Dalessandro 	spin_lock(&mmu_rb_lock);
134*f48ad614SDennis Dalessandro 	list_del_rcu(&handler->list);
135*f48ad614SDennis Dalessandro 	spin_unlock(&mmu_rb_lock);
136*f48ad614SDennis Dalessandro 	synchronize_rcu();
137*f48ad614SDennis Dalessandro 
138*f48ad614SDennis Dalessandro 	spin_lock_irqsave(&handler->lock, flags);
139*f48ad614SDennis Dalessandro 	if (!RB_EMPTY_ROOT(root)) {
140*f48ad614SDennis Dalessandro 		struct rb_node *node;
141*f48ad614SDennis Dalessandro 		struct mmu_rb_node *rbnode;
142*f48ad614SDennis Dalessandro 
143*f48ad614SDennis Dalessandro 		while ((node = rb_first(root))) {
144*f48ad614SDennis Dalessandro 			rbnode = rb_entry(node, struct mmu_rb_node, node);
145*f48ad614SDennis Dalessandro 			rb_erase(node, root);
146*f48ad614SDennis Dalessandro 			if (handler->ops->remove)
147*f48ad614SDennis Dalessandro 				handler->ops->remove(root, rbnode, NULL);
148*f48ad614SDennis Dalessandro 		}
149*f48ad614SDennis Dalessandro 	}
150*f48ad614SDennis Dalessandro 	spin_unlock_irqrestore(&handler->lock, flags);
151*f48ad614SDennis Dalessandro 
152*f48ad614SDennis Dalessandro 	kfree(handler);
153*f48ad614SDennis Dalessandro }
154*f48ad614SDennis Dalessandro 
155*f48ad614SDennis Dalessandro int hfi1_mmu_rb_insert(struct rb_root *root, struct mmu_rb_node *mnode)
156*f48ad614SDennis Dalessandro {
157*f48ad614SDennis Dalessandro 	struct mmu_rb_handler *handler = find_mmu_handler(root);
158*f48ad614SDennis Dalessandro 	struct mmu_rb_node *node;
159*f48ad614SDennis Dalessandro 	unsigned long flags;
160*f48ad614SDennis Dalessandro 	int ret = 0;
161*f48ad614SDennis Dalessandro 
162*f48ad614SDennis Dalessandro 	if (!handler)
163*f48ad614SDennis Dalessandro 		return -EINVAL;
164*f48ad614SDennis Dalessandro 
165*f48ad614SDennis Dalessandro 	spin_lock_irqsave(&handler->lock, flags);
166*f48ad614SDennis Dalessandro 	hfi1_cdbg(MMU, "Inserting node addr 0x%llx, len %u", mnode->addr,
167*f48ad614SDennis Dalessandro 		  mnode->len);
168*f48ad614SDennis Dalessandro 	node = __mmu_rb_search(handler, mnode->addr, mnode->len);
169*f48ad614SDennis Dalessandro 	if (node) {
170*f48ad614SDennis Dalessandro 		ret = -EINVAL;
171*f48ad614SDennis Dalessandro 		goto unlock;
172*f48ad614SDennis Dalessandro 	}
173*f48ad614SDennis Dalessandro 	__mmu_int_rb_insert(mnode, root);
174*f48ad614SDennis Dalessandro 
175*f48ad614SDennis Dalessandro 	if (handler->ops->insert) {
176*f48ad614SDennis Dalessandro 		ret = handler->ops->insert(root, mnode);
177*f48ad614SDennis Dalessandro 		if (ret)
178*f48ad614SDennis Dalessandro 			__mmu_int_rb_remove(mnode, root);
179*f48ad614SDennis Dalessandro 	}
180*f48ad614SDennis Dalessandro unlock:
181*f48ad614SDennis Dalessandro 	spin_unlock_irqrestore(&handler->lock, flags);
182*f48ad614SDennis Dalessandro 	return ret;
183*f48ad614SDennis Dalessandro }
184*f48ad614SDennis Dalessandro 
185*f48ad614SDennis Dalessandro /* Caller must hold handler lock */
186*f48ad614SDennis Dalessandro static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *handler,
187*f48ad614SDennis Dalessandro 					   unsigned long addr,
188*f48ad614SDennis Dalessandro 					   unsigned long len)
189*f48ad614SDennis Dalessandro {
190*f48ad614SDennis Dalessandro 	struct mmu_rb_node *node = NULL;
191*f48ad614SDennis Dalessandro 
192*f48ad614SDennis Dalessandro 	hfi1_cdbg(MMU, "Searching for addr 0x%llx, len %u", addr, len);
193*f48ad614SDennis Dalessandro 	if (!handler->ops->filter) {
194*f48ad614SDennis Dalessandro 		node = __mmu_int_rb_iter_first(handler->root, addr,
195*f48ad614SDennis Dalessandro 					       (addr + len) - 1);
196*f48ad614SDennis Dalessandro 	} else {
197*f48ad614SDennis Dalessandro 		for (node = __mmu_int_rb_iter_first(handler->root, addr,
198*f48ad614SDennis Dalessandro 						    (addr + len) - 1);
199*f48ad614SDennis Dalessandro 		     node;
200*f48ad614SDennis Dalessandro 		     node = __mmu_int_rb_iter_next(node, addr,
201*f48ad614SDennis Dalessandro 						   (addr + len) - 1)) {
202*f48ad614SDennis Dalessandro 			if (handler->ops->filter(node, addr, len))
203*f48ad614SDennis Dalessandro 				return node;
204*f48ad614SDennis Dalessandro 		}
205*f48ad614SDennis Dalessandro 	}
206*f48ad614SDennis Dalessandro 	return node;
207*f48ad614SDennis Dalessandro }
208*f48ad614SDennis Dalessandro 
209*f48ad614SDennis Dalessandro /* Caller must *not* hold handler lock. */
210*f48ad614SDennis Dalessandro static void __mmu_rb_remove(struct mmu_rb_handler *handler,
211*f48ad614SDennis Dalessandro 			    struct mmu_rb_node *node, struct mm_struct *mm)
212*f48ad614SDennis Dalessandro {
213*f48ad614SDennis Dalessandro 	unsigned long flags;
214*f48ad614SDennis Dalessandro 
215*f48ad614SDennis Dalessandro 	/* Validity of handler and node pointers has been checked by caller. */
216*f48ad614SDennis Dalessandro 	hfi1_cdbg(MMU, "Removing node addr 0x%llx, len %u", node->addr,
217*f48ad614SDennis Dalessandro 		  node->len);
218*f48ad614SDennis Dalessandro 	spin_lock_irqsave(&handler->lock, flags);
219*f48ad614SDennis Dalessandro 	__mmu_int_rb_remove(node, handler->root);
220*f48ad614SDennis Dalessandro 	spin_unlock_irqrestore(&handler->lock, flags);
221*f48ad614SDennis Dalessandro 
222*f48ad614SDennis Dalessandro 	if (handler->ops->remove)
223*f48ad614SDennis Dalessandro 		handler->ops->remove(handler->root, node, mm);
224*f48ad614SDennis Dalessandro }
225*f48ad614SDennis Dalessandro 
226*f48ad614SDennis Dalessandro struct mmu_rb_node *hfi1_mmu_rb_search(struct rb_root *root, unsigned long addr,
227*f48ad614SDennis Dalessandro 				       unsigned long len)
228*f48ad614SDennis Dalessandro {
229*f48ad614SDennis Dalessandro 	struct mmu_rb_handler *handler = find_mmu_handler(root);
230*f48ad614SDennis Dalessandro 	struct mmu_rb_node *node;
231*f48ad614SDennis Dalessandro 	unsigned long flags;
232*f48ad614SDennis Dalessandro 
233*f48ad614SDennis Dalessandro 	if (!handler)
234*f48ad614SDennis Dalessandro 		return ERR_PTR(-EINVAL);
235*f48ad614SDennis Dalessandro 
236*f48ad614SDennis Dalessandro 	spin_lock_irqsave(&handler->lock, flags);
237*f48ad614SDennis Dalessandro 	node = __mmu_rb_search(handler, addr, len);
238*f48ad614SDennis Dalessandro 	spin_unlock_irqrestore(&handler->lock, flags);
239*f48ad614SDennis Dalessandro 
240*f48ad614SDennis Dalessandro 	return node;
241*f48ad614SDennis Dalessandro }
242*f48ad614SDennis Dalessandro 
243*f48ad614SDennis Dalessandro struct mmu_rb_node *hfi1_mmu_rb_extract(struct rb_root *root,
244*f48ad614SDennis Dalessandro 					unsigned long addr, unsigned long len)
245*f48ad614SDennis Dalessandro {
246*f48ad614SDennis Dalessandro 	struct mmu_rb_handler *handler = find_mmu_handler(root);
247*f48ad614SDennis Dalessandro 	struct mmu_rb_node *node;
248*f48ad614SDennis Dalessandro 	unsigned long flags;
249*f48ad614SDennis Dalessandro 
250*f48ad614SDennis Dalessandro 	if (!handler)
251*f48ad614SDennis Dalessandro 		return ERR_PTR(-EINVAL);
252*f48ad614SDennis Dalessandro 
253*f48ad614SDennis Dalessandro 	spin_lock_irqsave(&handler->lock, flags);
254*f48ad614SDennis Dalessandro 	node = __mmu_rb_search(handler, addr, len);
255*f48ad614SDennis Dalessandro 	if (node)
256*f48ad614SDennis Dalessandro 		__mmu_int_rb_remove(node, handler->root);
257*f48ad614SDennis Dalessandro 	spin_unlock_irqrestore(&handler->lock, flags);
258*f48ad614SDennis Dalessandro 
259*f48ad614SDennis Dalessandro 	return node;
260*f48ad614SDennis Dalessandro }
261*f48ad614SDennis Dalessandro 
262*f48ad614SDennis Dalessandro void hfi1_mmu_rb_remove(struct rb_root *root, struct mmu_rb_node *node)
263*f48ad614SDennis Dalessandro {
264*f48ad614SDennis Dalessandro 	struct mmu_rb_handler *handler = find_mmu_handler(root);
265*f48ad614SDennis Dalessandro 
266*f48ad614SDennis Dalessandro 	if (!handler || !node)
267*f48ad614SDennis Dalessandro 		return;
268*f48ad614SDennis Dalessandro 
269*f48ad614SDennis Dalessandro 	__mmu_rb_remove(handler, node, NULL);
270*f48ad614SDennis Dalessandro }
271*f48ad614SDennis Dalessandro 
272*f48ad614SDennis Dalessandro static struct mmu_rb_handler *find_mmu_handler(struct rb_root *root)
273*f48ad614SDennis Dalessandro {
274*f48ad614SDennis Dalessandro 	struct mmu_rb_handler *handler;
275*f48ad614SDennis Dalessandro 
276*f48ad614SDennis Dalessandro 	rcu_read_lock();
277*f48ad614SDennis Dalessandro 	list_for_each_entry_rcu(handler, &mmu_rb_handlers, list) {
278*f48ad614SDennis Dalessandro 		if (handler->root == root)
279*f48ad614SDennis Dalessandro 			goto unlock;
280*f48ad614SDennis Dalessandro 	}
281*f48ad614SDennis Dalessandro 	handler = NULL;
282*f48ad614SDennis Dalessandro unlock:
283*f48ad614SDennis Dalessandro 	rcu_read_unlock();
284*f48ad614SDennis Dalessandro 	return handler;
285*f48ad614SDennis Dalessandro }
286*f48ad614SDennis Dalessandro 
287*f48ad614SDennis Dalessandro static inline void mmu_notifier_page(struct mmu_notifier *mn,
288*f48ad614SDennis Dalessandro 				     struct mm_struct *mm, unsigned long addr)
289*f48ad614SDennis Dalessandro {
290*f48ad614SDennis Dalessandro 	mmu_notifier_mem_invalidate(mn, mm, addr, addr + PAGE_SIZE);
291*f48ad614SDennis Dalessandro }
292*f48ad614SDennis Dalessandro 
293*f48ad614SDennis Dalessandro static inline void mmu_notifier_range_start(struct mmu_notifier *mn,
294*f48ad614SDennis Dalessandro 					    struct mm_struct *mm,
295*f48ad614SDennis Dalessandro 					    unsigned long start,
296*f48ad614SDennis Dalessandro 					    unsigned long end)
297*f48ad614SDennis Dalessandro {
298*f48ad614SDennis Dalessandro 	mmu_notifier_mem_invalidate(mn, mm, start, end);
299*f48ad614SDennis Dalessandro }
300*f48ad614SDennis Dalessandro 
301*f48ad614SDennis Dalessandro static void mmu_notifier_mem_invalidate(struct mmu_notifier *mn,
302*f48ad614SDennis Dalessandro 					struct mm_struct *mm,
303*f48ad614SDennis Dalessandro 					unsigned long start, unsigned long end)
304*f48ad614SDennis Dalessandro {
305*f48ad614SDennis Dalessandro 	struct mmu_rb_handler *handler =
306*f48ad614SDennis Dalessandro 		container_of(mn, struct mmu_rb_handler, mn);
307*f48ad614SDennis Dalessandro 	struct rb_root *root = handler->root;
308*f48ad614SDennis Dalessandro 	struct mmu_rb_node *node, *ptr = NULL;
309*f48ad614SDennis Dalessandro 	unsigned long flags;
310*f48ad614SDennis Dalessandro 
311*f48ad614SDennis Dalessandro 	spin_lock_irqsave(&handler->lock, flags);
312*f48ad614SDennis Dalessandro 	for (node = __mmu_int_rb_iter_first(root, start, end - 1);
313*f48ad614SDennis Dalessandro 	     node; node = ptr) {
314*f48ad614SDennis Dalessandro 		/* Guard against node removal. */
315*f48ad614SDennis Dalessandro 		ptr = __mmu_int_rb_iter_next(node, start, end - 1);
316*f48ad614SDennis Dalessandro 		hfi1_cdbg(MMU, "Invalidating node addr 0x%llx, len %u",
317*f48ad614SDennis Dalessandro 			  node->addr, node->len);
318*f48ad614SDennis Dalessandro 		if (handler->ops->invalidate(root, node)) {
319*f48ad614SDennis Dalessandro 			__mmu_int_rb_remove(node, root);
320*f48ad614SDennis Dalessandro 			if (handler->ops->remove)
321*f48ad614SDennis Dalessandro 				handler->ops->remove(root, node, mm);
322*f48ad614SDennis Dalessandro 		}
323*f48ad614SDennis Dalessandro 	}
324*f48ad614SDennis Dalessandro 	spin_unlock_irqrestore(&handler->lock, flags);
325*f48ad614SDennis Dalessandro }
326