aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)