aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2008-07-22 17:20:05 -0400
committerRoland Dreier <rolandd@cisco.com>2008-07-22 17:20:05 -0400
commite8bb4beb2b1f90d499134f2849727ed04c3bedc4 (patch)
tree3c4be492134aa4a738d1eeef144642d3e2bc9509 /drivers/infiniband/hw
parentd35cb360c29956510b2fe1a953bd4968536f7216 (diff)
IB/mthca: 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>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c26
2 files changed, 19 insertions, 8 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index ee4d073c889f..252590116df5 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -202,6 +202,7 @@ struct mthca_pd_table {
202 202
203struct mthca_buddy { 203struct mthca_buddy {
204 unsigned long **bits; 204 unsigned long **bits;
205 int *num_free;
205 int max_order; 206 int max_order;
206 spinlock_t lock; 207 spinlock_t lock;
207}; 208};
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index 8489b1e81c0f..882e6b735915 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -89,23 +89,26 @@ static u32 mthca_buddy_alloc(struct mthca_buddy *buddy, int order)
89 89
90 spin_lock(&buddy->lock); 90 spin_lock(&buddy->lock);
91 91
92 for (o = order; o <= buddy->max_order; ++o) { 92 for (o = order; o <= buddy->max_order; ++o)
93 m = 1 << (buddy->max_order - o); 93 if (buddy->num_free[o]) {
94 seg = find_first_bit(buddy->bits[o], m); 94 m = 1 << (buddy->max_order - o);
95 if (seg < m) 95 seg = find_first_bit(buddy->bits[o], m);
96 goto found; 96 if (seg < m)
97 } 97 goto found;
98 }
98 99
99 spin_unlock(&buddy->lock); 100 spin_unlock(&buddy->lock);
100 return -1; 101 return -1;
101 102
102 found: 103 found:
103 clear_bit(seg, buddy->bits[o]); 104 clear_bit(seg, buddy->bits[o]);
105 --buddy->num_free[o];
104 106
105 while (o > order) { 107 while (o > order) {
106 --o; 108 --o;
107 seg <<= 1; 109 seg <<= 1;
108 set_bit(seg ^ 1, buddy->bits[o]); 110 set_bit(seg ^ 1, buddy->bits[o]);
111 ++buddy->num_free[o];
109 } 112 }
110 113
111 spin_unlock(&buddy->lock); 114 spin_unlock(&buddy->lock);
@@ -123,11 +126,13 @@ static void mthca_buddy_free(struct mthca_buddy *buddy, u32 seg, int order)
123 126
124 while (test_bit(seg ^ 1, buddy->bits[order])) { 127 while (test_bit(seg ^ 1, buddy->bits[order])) {
125 clear_bit(seg ^ 1, buddy->bits[order]); 128 clear_bit(seg ^ 1, buddy->bits[order]);
129 --buddy->num_free[order];
126 seg >>= 1; 130 seg >>= 1;
127 ++order; 131 ++order;
128 } 132 }
129 133
130 set_bit(seg, buddy->bits[order]); 134 set_bit(seg, buddy->bits[order]);
135 ++buddy->num_free[order];
131 136
132 spin_unlock(&buddy->lock); 137 spin_unlock(&buddy->lock);
133} 138}
@@ -141,7 +146,9 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
141 146
142 buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *), 147 buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
143 GFP_KERNEL); 148 GFP_KERNEL);
144 if (!buddy->bits) 149 buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *),
150 GFP_KERNEL);
151 if (!buddy->bits || !buddy->num_free)
145 goto err_out; 152 goto err_out;
146 153
147 for (i = 0; i <= buddy->max_order; ++i) { 154 for (i = 0; i <= buddy->max_order; ++i) {
@@ -154,6 +161,7 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
154 } 161 }
155 162
156 set_bit(0, buddy->bits[buddy->max_order]); 163 set_bit(0, buddy->bits[buddy->max_order]);
164 buddy->num_free[buddy->max_order] = 1;
157 165
158 return 0; 166 return 0;
159 167
@@ -161,9 +169,10 @@ err_out_free:
161 for (i = 0; i <= buddy->max_order; ++i) 169 for (i = 0; i <= buddy->max_order; ++i)
162 kfree(buddy->bits[i]); 170 kfree(buddy->bits[i]);
163 171
172err_out:
164 kfree(buddy->bits); 173 kfree(buddy->bits);
174 kfree(buddy->num_free);
165 175
166err_out:
167 return -ENOMEM; 176 return -ENOMEM;
168} 177}
169 178
@@ -175,6 +184,7 @@ static void mthca_buddy_cleanup(struct mthca_buddy *buddy)
175 kfree(buddy->bits[i]); 184 kfree(buddy->bits[i]);
176 185
177 kfree(buddy->bits); 186 kfree(buddy->bits);
187 kfree(buddy->num_free);
178} 188}
179 189
180static u32 mthca_alloc_mtt_range(struct mthca_dev *dev, int order, 190static u32 mthca_alloc_mtt_range(struct mthca_dev *dev, int order,