iova RB tree setup tweak.
Subsystems (2)
The following patch merges two functions into one allowing for a 3% reduction in overhead in locating, allocating and inserting pages for use in IOMMU operations.
Its a bit of a eye-crosser so I welcome any RB-tree / MM experts to take a look. It works by re-using some of the information gathered in the search for the pages to use in setting up the IOTLB's in the insertion of the iova structure into the RB tree.
--mgross
drivers/pci/iova.c +36 -14
@@ -72,20 +72,25 @@return pad_size; } -static int __alloc_iova_range (struct iova_domain *iovad,unsigned long size, -unsigned long limit_pfn,struct iova *new,bool size_aligned) +static int __alloc_and_insert_iova_range (struct iova_domain *iovad, +unsigned long size,unsigned long limit_pfn, +struct iova *new,bool size_aligned) { -struct rb_node *curr =NULL ; +struct rb_node *prev, *curr =NULL ;unsigned long flags;unsigned long saved_pfn;unsigned int pad_size =0 ;/* Walk the tree backwards */ spin_lock_irqsave (&iovad->iova_rbtree_lock, flags); saved_pfn = limit_pfn; curr =__get_cached_rbnode (iovad, &limit_pfn); + prev = curr;while (curr) { struct iova *curr_iova = container_of(curr, struct iova, node); +if (limit_pfn < curr_iova->pfn_lo) goto move_left;else if (limit_pfn < curr_iova->pfn_hi)
@@ -99,6 +104,7 @@ adjust_limit_pfn: limit_pfn = curr_iova->pfn_lo -1 ; move_left: + prev = curr; curr =rb_prev (curr); }
@@ -115,7 +121,33 @@ new->pfn_lo = limit_pfn - (size + pad_size) +1 ; new->pfn_hi = new->pfn_lo + size -1 ; +/* Insert the new_iova into domain rbtree by holding writer lock */ +/* Add new node and rebalance tree. */ + { +struct rb_node **entry = &((prev)), *parent =NULL ; +/* Figure out where to put new node */ +while (*entry) { +struct iova *this =container_of (*entry, + struct iova, node); + parent = *entry; + +if (new->pfn_lo < this->pfn_lo) + entry = &((*entry)->rb_left); +else if (new->pfn_lo > this->pfn_lo) + entry = &((*entry)->rb_right); +else +BUG ();/* this should not happen */ + } + +/* Add new node and rebalance tree. */ +rb_link_node (&new->node, parent, entry); +rb_insert_color (&new->node, &iovad->rbroot); + } +__cached_rbnode_insert_update (iovad, saved_pfn, new); +spin_unlock_irqrestore (&iovad->iova_rbtree_lock, flags); + +return 0 ; }
@@ -171,23 +203,15 @@ size =__roundup_pow_of_two (size);spin_lock_irqsave (&iovad->iova_alloc_lock, flags); - ret =__alloc_iova_range (iovad, size, limit_pfn, new_iova, - size_aligned); + ret =__alloc_and_insert_iova_range (iovad, size, limit_pfn, + new_iova, size_aligned); +spin_unlock_irqrestore (&iovad->iova_alloc_lock, flags);if (ret) { -spin_unlock_irqrestore (&iovad->iova_alloc_lock, flags);free_iova_mem (new_iova);return NULL ; } -/* Insert the new_iova into domain rbtree by holding writer lock */ -spin_lock (&iovad->iova_rbtree_lock); -iova_insert_rbtree (&iovad->rbroot, new_iova); -__cached_rbnode_insert_update (iovad, limit_pfn, new_iova); -spin_unlock (&iovad->iova_rbtree_lock); - -spin_unlock_irqrestore (&iovad->iova_alloc_lock, flags); -return new_iova; }
Andrew Morton
maintainerQuoted 9 lines · On Mon, 11 Feb 2008 13:56:51 -0800 mark gross <[email protected]> wrote:
The following patch merges two functions into one allowing for a 3% reduction in overhead in locating, allocating and inserting pages for use in IOMMU operations.
Its a bit of a eye-crosser so I welcome any RB-tree / MM experts to take a look. It works by re-using some of the information gathered in the search for the pages to use in setting up the IOTLB's in the insertion of the iova structure into the RB tree.
I guess this is a PCI patch hence I'd be tagging is as to-be-merged-via-greg's-pci-tree.
Quoted 3 lines
Singed-off-by <[email protected]>
ow, that musta hurt.
drivers/pci/iova.c
Quoted 33 lines
Index:
linux-2.6.24-mm1/drivers/pci/iova.c
===================================================================drivers/pci/iova.c +6
-3@@ -72,20 +72,25 @@return pad_size; } -static int __alloc_iova_range (struct iova_domain *iovad,unsigned long size, -unsigned long limit_pfn,struct iova *new,bool size_aligned) +static int __alloc_and_insert_iova_range (struct iova_domain *iovad, +unsigned long size,unsigned long limit_pfn, +struct iova *new,bool size_aligned) { -struct rb_node *curr =NULL ; +struct rb_node *prev, *curr =NULL ;unsigned long flags;unsigned long saved_pfn;unsigned int pad_size =0 ;/* Walk the tree backwards */ spin_lock_irqsave (&iovad->iova_rbtree_lock, flags); saved_pfn = limit_pfn; curr =__get_cached_rbnode (iovad, &limit_pfn); + prev = curr;while (curr) { struct iova *curr_iova = container_of(curr, struct iova, node); +if (limit_pfn < curr_iova->pfn_lo) goto move_left;else if (limit_pfn < curr_iova->pfn_hi)@@ -99,6 +104,7 @@
For some reason patch(1) claims that the patch is corrupted at this line.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 13 lines · Andrew Morton
Quoted 9 lines · On Mon, 11 Feb 2008 13:56:51 -0800 mark gross <[email protected]> wrote:
The following patch merges two functions into one allowing for a 3% reduction in overhead in locating, allocating and inserting pages for use in IOMMU operations.
Its a bit of a eye-crosser so I welcome any RB-tree / MM experts to take a look. It works by re-using some of the information gathered in the search for the pages to use in setting up the IOTLB's in the insertion of the iova structure into the RB tree.
Quoted 8 lines
I guess this is a PCI patch hence I'd be tagging is as to-be-merged-via-greg's-pci-tree.
Quoted 3 lines
Singed-off-by <[email protected]>ow, that musta hurt.
Not at first but ever since I posted the patch its been a bit.
Quoted 22 lines
Quoted 22 lines
Index:
linux-2.6.24-mm1/drivers/pci/iova.c
===================================================================drivers/pci/iova.c +4
-3@@ -72,20 +72,25 @@return pad_size; } -static int __alloc_iova_range (struct iova_domain *iovad,unsigned long size, -unsigned long limit_pfn,struct iova *new,bool size_aligned) +static int __alloc_and_insert_iova_range (struct iova_domain *iovad, +unsigned long size,unsigned long limit_pfn, +struct iova *new,bool size_aligned) { -struct rb_node *curr =NULL ; +struct rb_node *prev, *curr =NULL ;unsigned long flags;unsigned long saved_pfn;unsigned int pad_size =0 ;
Quoted 15 lines
drivers/pci/iova.c
Quoted 12 lines
drivers/pci/iova.c +2
-0/* Walk the tree backwards */ spin_lock_irqsave (&iovad->iova_rbtree_lock, flags); saved_pfn = limit_pfn; curr =__get_cached_rbnode (iovad, &limit_pfn); + prev = curr;while (curr) { struct iova *curr_iova = container_of(curr, struct iova, node); +if (limit_pfn < curr_iova->pfn_lo) goto move_left;else if (limit_pfn < curr_iova->pfn_hi)@@ -99,6 +104,7 @@For some reason patch(1) claims that the patch is corrupted at this line.
My bad. Try the following:
--mgross
drivers/pci/iova.c +36 -14
@@ -72,10 +72,11 @@return pad_size; } -static int __alloc_iova_range (struct iova_domain *iovad,unsigned long size, -unsigned long limit_pfn,struct iova *new,bool size_aligned) +static int __alloc_and_insert_iova_range (struct iova_domain *iovad, +unsigned long size,unsigned long limit_pfn, +struct iova *new,bool size_aligned) { -struct rb_node *curr =NULL ; +struct rb_node *prev, *curr =NULL ;unsigned long flags;unsigned long saved_pfn;unsigned int pad_size =0 ;
@@ -84,8 +85,10 @@spin_lock_irqsave (&iovad->iova_rbtree_lock, flags); saved_pfn = limit_pfn; curr =__get_cached_rbnode (iovad, &limit_pfn); + prev = curr;while (curr) { struct iova *curr_iova = container_of(curr, struct iova, node); +if (limit_pfn < curr_iova->pfn_lo) goto move_left;else if (limit_pfn < curr_iova->pfn_hi)
@@ -99,6 +102,7 @@ adjust_limit_pfn: limit_pfn = curr_iova->pfn_lo -1 ; move_left: + prev = curr; curr =rb_prev (curr); }
@@ -115,7 +119,33 @@ new->pfn_lo = limit_pfn - (size + pad_size) +1 ; new->pfn_hi = new->pfn_lo + size -1 ; +/* Insert the new_iova into domain rbtree by holding writer lock */ +/* Add new node and rebalance tree. */ + { +struct rb_node **entry = &((prev)), *parent =NULL ; +/* Figure out where to put new node */ +while (*entry) { +struct iova *this =container_of (*entry, + struct iova, node); + parent = *entry; + +if (new->pfn_lo < this->pfn_lo) + entry = &((*entry)->rb_left); +else if (new->pfn_lo > this->pfn_lo) + entry = &((*entry)->rb_right); +else +BUG ();/* this should not happen */ + } + +/* Add new node and rebalance tree. */ +rb_link_node (&new->node, parent, entry); +rb_insert_color (&new->node, &iovad->rbroot); + } +__cached_rbnode_insert_update (iovad, saved_pfn, new); +spin_unlock_irqrestore (&iovad->iova_rbtree_lock, flags); + +return 0 ; }
@@ -171,23 +201,15 @@ size =__roundup_pow_of_two (size);spin_lock_irqsave (&iovad->iova_alloc_lock, flags); - ret =__alloc_iova_range (iovad, size, limit_pfn, new_iova, - size_aligned); + ret =__alloc_and_insert_iova_range (iovad, size, limit_pfn, + new_iova, size_aligned); +spin_unlock_irqrestore (&iovad->iova_alloc_lock, flags);if (ret) { -spin_unlock_irqrestore (&iovad->iova_alloc_lock, flags);free_iova_mem (new_iova);return NULL ; } -/* Insert the new_iova into domain rbtree by holding writer lock */ -spin_lock (&iovad->iova_rbtree_lock); -iova_insert_rbtree (&iovad->rbroot, new_iova); -__cached_rbnode_insert_update (iovad, limit_pfn, new_iova); -spin_unlock (&iovad->iova_rbtree_lock); - -spin_unlock_irqrestore (&iovad->iova_alloc_lock, flags); -return new_iova; }