aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2008-07-22 17:19:40 -0400
committerRoland Dreier <rolandd@cisco.com>2008-07-22 17:19:40 -0400
commite4044cfc493338cd09870bd45dc646336bb66e9f (patch)
tree2385c18ee6a79393b4e1c5c25ee1f0f980d7da93
parent899698dad72340b562478b8b770317f2f0fe0c09 (diff)
mlx4_core: Keep free count for MTT buddy allocator
MTT entries are allocated with a buddy allocator, which just keeps bitmaps for each level of the buddy table. However, all free space starts out at the highest order, and small allocations start scanning from the lowest order. When the lowest order tables have no free space, this can lead to scanning potentially millions of bits before finding a free entry at a higher order. We can avoid this by just keeping a count of how many free entries each order has, and skipping the bitmap scan when an order is completely empty. This provides a nice performance boost for a negligible increase in memory usage. Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/net/mlx4/mlx4.h1
-rw-r--r--drivers/net/mlx4/mr.c26
2 files changed, 19 insertions, 8 deletions
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index a4023c2dd050..78038499cff5 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -118,6 +118,7 @@ struct mlx4_bitmap {
118 118
119struct mlx4_buddy { 119struct mlx4_buddy {
120 unsigned long **bits; 120 unsigned long **bits;
121 unsigned int *num_free;
121 int max_order; 122 int max_order;
122 spinlock_t lock; 123 spinlock_t lock;
123}; 124};
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
index 03a9abcce524..b3ea93b98689 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/mlx4/mr.c
@@ -79,23 +79,26 @@ static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order)
79 79
80 spin_lock(&buddy->lock); 80 spin_lock(&buddy->lock);
81 81
82 for (o = order; o <= buddy->max_order; ++o) { 82 for (o = order; o <= buddy->max_order; ++o)
83 m = 1 << (buddy->max_order - o); 83 if (buddy->num_free[o]) {
84 seg = find_first_bit(buddy->bits[o], m); 84 m = 1 << (buddy->max_order - o);
85 if (seg < m) 85 seg = find_first_bit(buddy->bits[o], m);
86 goto found; 86 if (seg < m)
87 } 87 goto found;
88 }
88 89
89 spin_unlock(&buddy->lock); 90 spin_unlock(&buddy->lock);
90 return -1; 91 return -1;
91 92
92 found: 93 found:
93 clear_bit(seg, buddy->bits[o]); 94 clear_bit(seg, buddy->bits[o]);
95 --buddy->num_free[o];
94 96
95 while (o > order) { 97 while (o > order) {
96 --o; 98 --o;
97 seg <<= 1; 99 seg <<= 1;
98 set_bit(seg ^ 1, buddy->bits[o]); 100 set_bit(seg ^ 1, buddy->bits[o]);
101 ++buddy->num_free[o];
99 } 102 }
100 103
101 spin_unlock(&buddy->lock); 104 spin_unlock(&buddy->lock);
@@ -113,11 +116,13 @@ static void mlx4_buddy_free(struct mlx4_buddy *buddy, u32 seg, int order)
113 116
114 while (test_bit(seg ^ 1, buddy->bits[order])) { 117 while (test_bit(seg ^ 1, buddy->bits[order])) {
115 clear_bit(seg ^ 1, buddy->bits[order]); 118 clear_bit(seg ^ 1, buddy->bits[order]);
119 --buddy->num_free[order];
116 seg >>= 1; 120 seg >>= 1;
117 ++order; 121 ++order;
118 } 122 }
119 123
120 set_bit(seg, buddy->bits[order]); 124 set_bit(seg, buddy->bits[order]);
125 ++buddy->num_free[order];
121 126
122 spin_unlock(&buddy->lock); 127 spin_unlock(&buddy->lock);
123} 128}
@@ -131,7 +136,9 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
131 136
132 buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *), 137 buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
133 GFP_KERNEL); 138 GFP_KERNEL);
134 if (!buddy->bits) 139 buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
140 GFP_KERNEL);
141 if (!buddy->bits || !buddy->num_free)
135 goto err_out; 142 goto err_out;
136 143
137 for (i = 0; i <= buddy->max_order; ++i) { 144 for (i = 0; i <= buddy->max_order; ++i) {
@@ -143,6 +150,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
143 } 150 }
144 151
145 set_bit(0, buddy->bits[buddy->max_order]); 152 set_bit(0, buddy->bits[buddy->max_order]);
153 buddy->num_free[buddy->max_order] = 1;
146 154
147 return 0; 155 return 0;
148 156
@@ -150,9 +158,10 @@ err_out_free:
150 for (i = 0; i <= buddy->max_order; ++i) 158 for (i = 0; i <= buddy->max_order; ++i)
151 kfree(buddy->bits[i]); 159 kfree(buddy->bits[i]);
152 160
161err_out:
153 kfree(buddy->bits); 162 kfree(buddy->bits);
163 kfree(buddy->num_free);
154 164
155err_out:
156 return -ENOMEM; 165 return -ENOMEM;
157} 166}
158 167
@@ -164,6 +173,7 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)
164 kfree(buddy->bits[i]); 173 kfree(buddy->bits[i]);
165 174
166 kfree(buddy->bits); 175 kfree(buddy->bits);
176 kfree(buddy->num_free);
167} 177}
168 178
169static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order) 179static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)