wext: Fix 32 bit iwpriv compatibility issue with 64 bit Kernel
[cascardo/linux.git] / drivers / staging / rdma / hfi1 / mmu_rb.c
index b3f0682..2b0e91d 100644 (file)
@@ -91,7 +91,7 @@ static unsigned long mmu_node_start(struct mmu_rb_node *node)
 
 static unsigned long mmu_node_last(struct mmu_rb_node *node)
 {
-       return PAGE_ALIGN((node->addr & PAGE_MASK) + node->len) - 1;
+       return PAGE_ALIGN(node->addr + node->len) - 1;
 }
 
 int hfi1_mmu_rb_register(struct rb_root *root, struct mmu_rb_ops *ops)
@@ -126,10 +126,15 @@ void hfi1_mmu_rb_unregister(struct rb_root *root)
        if (!handler)
                return;
 
+       /* Unregister first so we don't get any more notifications. */
+       if (current->mm)
+               mmu_notifier_unregister(&handler->mn, current->mm);
+
        spin_lock_irqsave(&mmu_rb_lock, flags);
        list_del(&handler->list);
        spin_unlock_irqrestore(&mmu_rb_lock, flags);
 
+       spin_lock_irqsave(&handler->lock, flags);
        if (!RB_EMPTY_ROOT(root)) {
                struct rb_node *node;
                struct mmu_rb_node *rbnode;
@@ -141,9 +146,8 @@ void hfi1_mmu_rb_unregister(struct rb_root *root)
                                handler->ops->remove(root, rbnode, NULL);
                }
        }
+       spin_unlock_irqrestore(&handler->lock, flags);
 
-       if (current->mm)
-               mmu_notifier_unregister(&handler->mn, current->mm);
        kfree(handler);
 }
 
@@ -235,6 +239,25 @@ struct mmu_rb_node *hfi1_mmu_rb_search(struct rb_root *root, unsigned long addr,
        return node;
 }
 
+struct mmu_rb_node *hfi1_mmu_rb_extract(struct rb_root *root,
+                                       unsigned long addr, unsigned long len)
+{
+       struct mmu_rb_handler *handler = find_mmu_handler(root);
+       struct mmu_rb_node *node;
+       unsigned long flags;
+
+       if (!handler)
+               return ERR_PTR(-EINVAL);
+
+       spin_lock_irqsave(&handler->lock, flags);
+       node = __mmu_rb_search(handler, addr, len);
+       if (node)
+               __mmu_int_rb_remove(node, handler->root);
+       spin_unlock_irqrestore(&handler->lock, flags);
+
+       return node;
+}
+
 void hfi1_mmu_rb_remove(struct rb_root *root, struct mmu_rb_node *node)
 {
        struct mmu_rb_handler *handler = find_mmu_handler(root);
@@ -293,9 +316,9 @@ static void mmu_notifier_mem_invalidate(struct mmu_notifier *mn,
                hfi1_cdbg(MMU, "Invalidating node addr 0x%llx, len %u",
                          node->addr, node->len);
                if (handler->ops->invalidate(root, node)) {
-                       spin_unlock_irqrestore(&handler->lock, flags);
-                       __mmu_rb_remove(handler, node, mm);
-                       spin_lock_irqsave(&handler->lock, flags);
+                       __mmu_int_rb_remove(node, root);
+                       if (handler->ops->remove)
+                               handler->ops->remove(root, node, mm);
                }
        }
        spin_unlock_irqrestore(&handler->lock, flags);