diff options
Diffstat (limited to 'drivers/net/mlx4/mr.c')
-rw-r--r-- | drivers/net/mlx4/mr.c | 49 |
1 files changed, 36 insertions, 13 deletions
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c index 03a9abcce524..a3c04c5f12c2 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c | |||
@@ -47,7 +47,7 @@ struct mlx4_mpt_entry { | |||
47 | __be32 flags; | 47 | __be32 flags; |
48 | __be32 qpn; | 48 | __be32 qpn; |
49 | __be32 key; | 49 | __be32 key; |
50 | __be32 pd; | 50 | __be32 pd_flags; |
51 | __be64 start; | 51 | __be64 start; |
52 | __be64 length; | 52 | __be64 length; |
53 | __be32 lkey; | 53 | __be32 lkey; |
@@ -61,11 +61,15 @@ struct mlx4_mpt_entry { | |||
61 | } __attribute__((packed)); | 61 | } __attribute__((packed)); |
62 | 62 | ||
63 | #define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28) | 63 | #define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28) |
64 | #define MLX4_MPT_FLAG_FREE (0x3UL << 28) | ||
64 | #define MLX4_MPT_FLAG_MIO (1 << 17) | 65 | #define MLX4_MPT_FLAG_MIO (1 << 17) |
65 | #define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15) | 66 | #define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15) |
66 | #define MLX4_MPT_FLAG_PHYSICAL (1 << 9) | 67 | #define MLX4_MPT_FLAG_PHYSICAL (1 << 9) |
67 | #define MLX4_MPT_FLAG_REGION (1 << 8) | 68 | #define MLX4_MPT_FLAG_REGION (1 << 8) |
68 | 69 | ||
70 | #define MLX4_MPT_PD_FLAG_FAST_REG (1 << 26) | ||
71 | #define MLX4_MPT_PD_FLAG_EN_INV (3 << 24) | ||
72 | |||
69 | #define MLX4_MTT_FLAG_PRESENT 1 | 73 | #define MLX4_MTT_FLAG_PRESENT 1 |
70 | 74 | ||
71 | #define MLX4_MPT_STATUS_SW 0xF0 | 75 | #define MLX4_MPT_STATUS_SW 0xF0 |
@@ -79,23 +83,26 @@ static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order) | |||
79 | 83 | ||
80 | spin_lock(&buddy->lock); | 84 | spin_lock(&buddy->lock); |
81 | 85 | ||
82 | for (o = order; o <= buddy->max_order; ++o) { | 86 | for (o = order; o <= buddy->max_order; ++o) |
83 | m = 1 << (buddy->max_order - o); | 87 | if (buddy->num_free[o]) { |
84 | seg = find_first_bit(buddy->bits[o], m); | 88 | m = 1 << (buddy->max_order - o); |
85 | if (seg < m) | 89 | seg = find_first_bit(buddy->bits[o], m); |
86 | goto found; | 90 | if (seg < m) |
87 | } | 91 | goto found; |
92 | } | ||
88 | 93 | ||
89 | spin_unlock(&buddy->lock); | 94 | spin_unlock(&buddy->lock); |
90 | return -1; | 95 | return -1; |
91 | 96 | ||
92 | found: | 97 | found: |
93 | clear_bit(seg, buddy->bits[o]); | 98 | clear_bit(seg, buddy->bits[o]); |
99 | --buddy->num_free[o]; | ||
94 | 100 | ||
95 | while (o > order) { | 101 | while (o > order) { |
96 | --o; | 102 | --o; |
97 | seg <<= 1; | 103 | seg <<= 1; |
98 | set_bit(seg ^ 1, buddy->bits[o]); | 104 | set_bit(seg ^ 1, buddy->bits[o]); |
105 | ++buddy->num_free[o]; | ||
99 | } | 106 | } |
100 | 107 | ||
101 | spin_unlock(&buddy->lock); | 108 | spin_unlock(&buddy->lock); |
@@ -113,11 +120,13 @@ static void mlx4_buddy_free(struct mlx4_buddy *buddy, u32 seg, int order) | |||
113 | 120 | ||
114 | while (test_bit(seg ^ 1, buddy->bits[order])) { | 121 | while (test_bit(seg ^ 1, buddy->bits[order])) { |
115 | clear_bit(seg ^ 1, buddy->bits[order]); | 122 | clear_bit(seg ^ 1, buddy->bits[order]); |
123 | --buddy->num_free[order]; | ||
116 | seg >>= 1; | 124 | seg >>= 1; |
117 | ++order; | 125 | ++order; |
118 | } | 126 | } |
119 | 127 | ||
120 | set_bit(seg, buddy->bits[order]); | 128 | set_bit(seg, buddy->bits[order]); |
129 | ++buddy->num_free[order]; | ||
121 | 130 | ||
122 | spin_unlock(&buddy->lock); | 131 | spin_unlock(&buddy->lock); |
123 | } | 132 | } |
@@ -131,7 +140,9 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) | |||
131 | 140 | ||
132 | buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *), | 141 | buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *), |
133 | GFP_KERNEL); | 142 | GFP_KERNEL); |
134 | if (!buddy->bits) | 143 | buddy->num_free = kzalloc((buddy->max_order + 1) * sizeof (int *), |
144 | GFP_KERNEL); | ||
145 | if (!buddy->bits || !buddy->num_free) | ||
135 | goto err_out; | 146 | goto err_out; |
136 | 147 | ||
137 | for (i = 0; i <= buddy->max_order; ++i) { | 148 | for (i = 0; i <= buddy->max_order; ++i) { |
@@ -143,6 +154,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) | |||
143 | } | 154 | } |
144 | 155 | ||
145 | set_bit(0, buddy->bits[buddy->max_order]); | 156 | set_bit(0, buddy->bits[buddy->max_order]); |
157 | buddy->num_free[buddy->max_order] = 1; | ||
146 | 158 | ||
147 | return 0; | 159 | return 0; |
148 | 160 | ||
@@ -150,9 +162,10 @@ err_out_free: | |||
150 | for (i = 0; i <= buddy->max_order; ++i) | 162 | for (i = 0; i <= buddy->max_order; ++i) |
151 | kfree(buddy->bits[i]); | 163 | kfree(buddy->bits[i]); |
152 | 164 | ||
165 | err_out: | ||
153 | kfree(buddy->bits); | 166 | kfree(buddy->bits); |
167 | kfree(buddy->num_free); | ||
154 | 168 | ||
155 | err_out: | ||
156 | return -ENOMEM; | 169 | return -ENOMEM; |
157 | } | 170 | } |
158 | 171 | ||
@@ -164,6 +177,7 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy) | |||
164 | kfree(buddy->bits[i]); | 177 | kfree(buddy->bits[i]); |
165 | 178 | ||
166 | kfree(buddy->bits); | 179 | kfree(buddy->bits); |
180 | kfree(buddy->num_free); | ||
167 | } | 181 | } |
168 | 182 | ||
169 | static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order) | 183 | static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order) |
@@ -314,21 +328,30 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) | |||
314 | 328 | ||
315 | memset(mpt_entry, 0, sizeof *mpt_entry); | 329 | memset(mpt_entry, 0, sizeof *mpt_entry); |
316 | 330 | ||
317 | mpt_entry->flags = cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS | | 331 | mpt_entry->flags = cpu_to_be32(MLX4_MPT_FLAG_MIO | |
318 | MLX4_MPT_FLAG_MIO | | ||
319 | MLX4_MPT_FLAG_REGION | | 332 | MLX4_MPT_FLAG_REGION | |
320 | mr->access); | 333 | mr->access); |
321 | 334 | ||
322 | mpt_entry->key = cpu_to_be32(key_to_hw_index(mr->key)); | 335 | mpt_entry->key = cpu_to_be32(key_to_hw_index(mr->key)); |
323 | mpt_entry->pd = cpu_to_be32(mr->pd); | 336 | mpt_entry->pd_flags = cpu_to_be32(mr->pd | MLX4_MPT_PD_FLAG_EN_INV); |
324 | mpt_entry->start = cpu_to_be64(mr->iova); | 337 | mpt_entry->start = cpu_to_be64(mr->iova); |
325 | mpt_entry->length = cpu_to_be64(mr->size); | 338 | mpt_entry->length = cpu_to_be64(mr->size); |
326 | mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift); | 339 | mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift); |
340 | |||
327 | if (mr->mtt.order < 0) { | 341 | if (mr->mtt.order < 0) { |
328 | mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL); | 342 | mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL); |
329 | mpt_entry->mtt_seg = 0; | 343 | mpt_entry->mtt_seg = 0; |
330 | } else | 344 | } else { |
331 | mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt)); | 345 | mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt)); |
346 | } | ||
347 | |||
348 | if (mr->mtt.order >= 0 && mr->mtt.page_shift == 0) { | ||
349 | /* fast register MR in free state */ | ||
350 | mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE); | ||
351 | mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG); | ||
352 | } else { | ||
353 | mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS); | ||
354 | } | ||
332 | 355 | ||
333 | err = mlx4_SW2HW_MPT(dev, mailbox, | 356 | err = mlx4_SW2HW_MPT(dev, mailbox, |
334 | key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1)); | 357 | key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1)); |