diff options
author | David S. Miller <davem@davemloft.net> | 2014-12-11 14:47:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-12-11 14:47:40 -0500 |
commit | efef793926f1baec7f2c8638c6d13576e6fe8997 (patch) | |
tree | 91215913abb8d16177517d254f677c7119461875 | |
parent | 630f4b70567fa0e2dc9283829f7cee04a5de3be2 (diff) | |
parent | 7d077cd34eabb2ffd05abe0f2cad01da1ef11712 (diff) |
Merge branch 'mlx4-next'
Or Gerlitz says:
====================
mlx4 driver update
This series from Matan, Jenny, Dotan and myself is mostly about adding
support to a new performance optimized flow steering mode (patches 4-10).
The 1st two patches are small fixes (one for VXLAN and one for SRIOV),
and the third patch is a fix to avoid hard-lockup situation when many
(hunderds) processes holding user-space QPs/CQs get events.
Matan and Or.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/infiniband/hw/mlx4/cq.c | 5 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/qp.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/alloc.c | 425 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/cq.c | 50 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_rx.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_tx.c | 14 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/eq.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.c | 225 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.h | 42 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 218 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mcg.c | 21 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 97 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/qp.c | 303 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 7 | ||||
-rw-r--r-- | include/linux/mlx4/device.h | 51 |
18 files changed, 1342 insertions, 170 deletions
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index 1066eec854a9..a3b70f6c4035 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c | |||
@@ -233,7 +233,10 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector | |||
233 | if (err) | 233 | if (err) |
234 | goto err_dbmap; | 234 | goto err_dbmap; |
235 | 235 | ||
236 | cq->mcq.comp = mlx4_ib_cq_comp; | 236 | if (context) |
237 | cq->mcq.tasklet_ctx.comp = mlx4_ib_cq_comp; | ||
238 | else | ||
239 | cq->mcq.comp = mlx4_ib_cq_comp; | ||
237 | cq->mcq.event = mlx4_ib_cq_event; | 240 | cq->mcq.event = mlx4_ib_cq_event; |
238 | 241 | ||
239 | if (context) | 242 | if (context) |
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 0c3375524a64..57ecc5b204f3 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -2227,7 +2227,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
2227 | ibdev->steer_qpn_count = MLX4_IB_UC_MAX_NUM_QPS; | 2227 | ibdev->steer_qpn_count = MLX4_IB_UC_MAX_NUM_QPS; |
2228 | err = mlx4_qp_reserve_range(dev, ibdev->steer_qpn_count, | 2228 | err = mlx4_qp_reserve_range(dev, ibdev->steer_qpn_count, |
2229 | MLX4_IB_UC_STEER_QPN_ALIGN, | 2229 | MLX4_IB_UC_STEER_QPN_ALIGN, |
2230 | &ibdev->steer_qpn_base); | 2230 | &ibdev->steer_qpn_base, 0); |
2231 | if (err) | 2231 | if (err) |
2232 | goto err_counter; | 2232 | goto err_counter; |
2233 | 2233 | ||
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 9c5150c3cb31..cf000b7ad64f 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c | |||
@@ -802,16 +802,21 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, | |||
802 | } | 802 | } |
803 | } | 803 | } |
804 | } else { | 804 | } else { |
805 | /* Raw packet QPNs must be aligned to 8 bits. If not, the WQE | 805 | /* Raw packet QPNs may not have bits 6,7 set in their qp_num; |
806 | * BlueFlame setup flow wrongly causes VLAN insertion. */ | 806 | * otherwise, the WQE BlueFlame setup flow wrongly causes |
807 | * VLAN insertion. */ | ||
807 | if (init_attr->qp_type == IB_QPT_RAW_PACKET) | 808 | if (init_attr->qp_type == IB_QPT_RAW_PACKET) |
808 | err = mlx4_qp_reserve_range(dev->dev, 1, 1 << 8, &qpn); | 809 | err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn, |
810 | (init_attr->cap.max_send_wr ? | ||
811 | MLX4_RESERVE_ETH_BF_QP : 0) | | ||
812 | (init_attr->cap.max_recv_wr ? | ||
813 | MLX4_RESERVE_A0_QP : 0)); | ||
809 | else | 814 | else |
810 | if (qp->flags & MLX4_IB_QP_NETIF) | 815 | if (qp->flags & MLX4_IB_QP_NETIF) |
811 | err = mlx4_ib_steer_qp_alloc(dev, 1, &qpn); | 816 | err = mlx4_ib_steer_qp_alloc(dev, 1, &qpn); |
812 | else | 817 | else |
813 | err = mlx4_qp_reserve_range(dev->dev, 1, 1, | 818 | err = mlx4_qp_reserve_range(dev->dev, 1, 1, |
814 | &qpn); | 819 | &qpn, 0); |
815 | if (err) | 820 | if (err) |
816 | goto err_proxy; | 821 | goto err_proxy; |
817 | } | 822 | } |
diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c index b0297da50304..963dd7e6d547 100644 --- a/drivers/net/ethernet/mellanox/mlx4/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c | |||
@@ -76,22 +76,53 @@ void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr) | |||
76 | mlx4_bitmap_free_range(bitmap, obj, 1, use_rr); | 76 | mlx4_bitmap_free_range(bitmap, obj, 1, use_rr); |
77 | } | 77 | } |
78 | 78 | ||
79 | u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align) | 79 | static unsigned long find_aligned_range(unsigned long *bitmap, |
80 | u32 start, u32 nbits, | ||
81 | int len, int align, u32 skip_mask) | ||
82 | { | ||
83 | unsigned long end, i; | ||
84 | |||
85 | again: | ||
86 | start = ALIGN(start, align); | ||
87 | |||
88 | while ((start < nbits) && (test_bit(start, bitmap) || | ||
89 | (start & skip_mask))) | ||
90 | start += align; | ||
91 | |||
92 | if (start >= nbits) | ||
93 | return -1; | ||
94 | |||
95 | end = start+len; | ||
96 | if (end > nbits) | ||
97 | return -1; | ||
98 | |||
99 | for (i = start + 1; i < end; i++) { | ||
100 | if (test_bit(i, bitmap) || ((u32)i & skip_mask)) { | ||
101 | start = i + 1; | ||
102 | goto again; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | return start; | ||
107 | } | ||
108 | |||
109 | u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, | ||
110 | int align, u32 skip_mask) | ||
80 | { | 111 | { |
81 | u32 obj; | 112 | u32 obj; |
82 | 113 | ||
83 | if (likely(cnt == 1 && align == 1)) | 114 | if (likely(cnt == 1 && align == 1 && !skip_mask)) |
84 | return mlx4_bitmap_alloc(bitmap); | 115 | return mlx4_bitmap_alloc(bitmap); |
85 | 116 | ||
86 | spin_lock(&bitmap->lock); | 117 | spin_lock(&bitmap->lock); |
87 | 118 | ||
88 | obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max, | 119 | obj = find_aligned_range(bitmap->table, bitmap->last, |
89 | bitmap->last, cnt, align - 1); | 120 | bitmap->max, cnt, align, skip_mask); |
90 | if (obj >= bitmap->max) { | 121 | if (obj >= bitmap->max) { |
91 | bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) | 122 | bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) |
92 | & bitmap->mask; | 123 | & bitmap->mask; |
93 | obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max, | 124 | obj = find_aligned_range(bitmap->table, 0, bitmap->max, |
94 | 0, cnt, align - 1); | 125 | cnt, align, skip_mask); |
95 | } | 126 | } |
96 | 127 | ||
97 | if (obj < bitmap->max) { | 128 | if (obj < bitmap->max) { |
@@ -118,6 +149,11 @@ u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap) | |||
118 | return bitmap->avail; | 149 | return bitmap->avail; |
119 | } | 150 | } |
120 | 151 | ||
152 | static u32 mlx4_bitmap_masked_value(struct mlx4_bitmap *bitmap, u32 obj) | ||
153 | { | ||
154 | return obj & (bitmap->max + bitmap->reserved_top - 1); | ||
155 | } | ||
156 | |||
121 | void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt, | 157 | void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt, |
122 | int use_rr) | 158 | int use_rr) |
123 | { | 159 | { |
@@ -147,6 +183,7 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, | |||
147 | bitmap->mask = mask; | 183 | bitmap->mask = mask; |
148 | bitmap->reserved_top = reserved_top; | 184 | bitmap->reserved_top = reserved_top; |
149 | bitmap->avail = num - reserved_top - reserved_bot; | 185 | bitmap->avail = num - reserved_top - reserved_bot; |
186 | bitmap->effective_len = bitmap->avail; | ||
150 | spin_lock_init(&bitmap->lock); | 187 | spin_lock_init(&bitmap->lock); |
151 | bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) * | 188 | bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) * |
152 | sizeof (long), GFP_KERNEL); | 189 | sizeof (long), GFP_KERNEL); |
@@ -163,6 +200,382 @@ void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap) | |||
163 | kfree(bitmap->table); | 200 | kfree(bitmap->table); |
164 | } | 201 | } |
165 | 202 | ||
203 | struct mlx4_zone_allocator { | ||
204 | struct list_head entries; | ||
205 | struct list_head prios; | ||
206 | u32 last_uid; | ||
207 | u32 mask; | ||
208 | /* protect the zone_allocator from concurrent accesses */ | ||
209 | spinlock_t lock; | ||
210 | enum mlx4_zone_alloc_flags flags; | ||
211 | }; | ||
212 | |||
213 | struct mlx4_zone_entry { | ||
214 | struct list_head list; | ||
215 | struct list_head prio_list; | ||
216 | u32 uid; | ||
217 | struct mlx4_zone_allocator *allocator; | ||
218 | struct mlx4_bitmap *bitmap; | ||
219 | int use_rr; | ||
220 | int priority; | ||
221 | int offset; | ||
222 | enum mlx4_zone_flags flags; | ||
223 | }; | ||
224 | |||
225 | struct mlx4_zone_allocator *mlx4_zone_allocator_create(enum mlx4_zone_alloc_flags flags) | ||
226 | { | ||
227 | struct mlx4_zone_allocator *zones = kmalloc(sizeof(*zones), GFP_KERNEL); | ||
228 | |||
229 | if (NULL == zones) | ||
230 | return NULL; | ||
231 | |||
232 | INIT_LIST_HEAD(&zones->entries); | ||
233 | INIT_LIST_HEAD(&zones->prios); | ||
234 | spin_lock_init(&zones->lock); | ||
235 | zones->last_uid = 0; | ||
236 | zones->mask = 0; | ||
237 | zones->flags = flags; | ||
238 | |||
239 | return zones; | ||
240 | } | ||
241 | |||
242 | int mlx4_zone_add_one(struct mlx4_zone_allocator *zone_alloc, | ||
243 | struct mlx4_bitmap *bitmap, | ||
244 | u32 flags, | ||
245 | int priority, | ||
246 | int offset, | ||
247 | u32 *puid) | ||
248 | { | ||
249 | u32 mask = mlx4_bitmap_masked_value(bitmap, (u32)-1); | ||
250 | struct mlx4_zone_entry *it; | ||
251 | struct mlx4_zone_entry *zone = kmalloc(sizeof(*zone), GFP_KERNEL); | ||
252 | |||
253 | if (NULL == zone) | ||
254 | return -ENOMEM; | ||
255 | |||
256 | zone->flags = flags; | ||
257 | zone->bitmap = bitmap; | ||
258 | zone->use_rr = (flags & MLX4_ZONE_USE_RR) ? MLX4_USE_RR : 0; | ||
259 | zone->priority = priority; | ||
260 | zone->offset = offset; | ||
261 | |||
262 | spin_lock(&zone_alloc->lock); | ||
263 | |||
264 | zone->uid = zone_alloc->last_uid++; | ||
265 | zone->allocator = zone_alloc; | ||
266 | |||
267 | if (zone_alloc->mask < mask) | ||
268 | zone_alloc->mask = mask; | ||
269 | |||
270 | list_for_each_entry(it, &zone_alloc->prios, prio_list) | ||
271 | if (it->priority >= priority) | ||
272 | break; | ||
273 | |||
274 | if (&it->prio_list == &zone_alloc->prios || it->priority > priority) | ||
275 | list_add_tail(&zone->prio_list, &it->prio_list); | ||
276 | list_add_tail(&zone->list, &it->list); | ||
277 | |||
278 | spin_unlock(&zone_alloc->lock); | ||
279 | |||
280 | *puid = zone->uid; | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | /* Should be called under a lock */ | ||
286 | static int __mlx4_zone_remove_one_entry(struct mlx4_zone_entry *entry) | ||
287 | { | ||
288 | struct mlx4_zone_allocator *zone_alloc = entry->allocator; | ||
289 | |||
290 | if (!list_empty(&entry->prio_list)) { | ||
291 | /* Check if we need to add an alternative node to the prio list */ | ||
292 | if (!list_is_last(&entry->list, &zone_alloc->entries)) { | ||
293 | struct mlx4_zone_entry *next = list_first_entry(&entry->list, | ||
294 | typeof(*next), | ||
295 | list); | ||
296 | |||
297 | if (next->priority == entry->priority) | ||
298 | list_add_tail(&next->prio_list, &entry->prio_list); | ||
299 | } | ||
300 | |||
301 | list_del(&entry->prio_list); | ||
302 | } | ||
303 | |||
304 | list_del(&entry->list); | ||
305 | |||
306 | if (zone_alloc->flags & MLX4_ZONE_ALLOC_FLAGS_NO_OVERLAP) { | ||
307 | u32 mask = 0; | ||
308 | struct mlx4_zone_entry *it; | ||
309 | |||
310 | list_for_each_entry(it, &zone_alloc->prios, prio_list) { | ||
311 | u32 cur_mask = mlx4_bitmap_masked_value(it->bitmap, (u32)-1); | ||
312 | |||
313 | if (mask < cur_mask) | ||
314 | mask = cur_mask; | ||
315 | } | ||
316 | zone_alloc->mask = mask; | ||
317 | } | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | void mlx4_zone_allocator_destroy(struct mlx4_zone_allocator *zone_alloc) | ||
323 | { | ||
324 | struct mlx4_zone_entry *zone, *tmp; | ||
325 | |||
326 | spin_lock(&zone_alloc->lock); | ||
327 | |||
328 | list_for_each_entry_safe(zone, tmp, &zone_alloc->entries, list) { | ||
329 | list_del(&zone->list); | ||
330 | list_del(&zone->prio_list); | ||
331 | kfree(zone); | ||
332 | } | ||
333 | |||
334 | spin_unlock(&zone_alloc->lock); | ||
335 | kfree(zone_alloc); | ||
336 | } | ||
337 | |||
338 | /* Should be called under a lock */ | ||
339 | static u32 __mlx4_alloc_from_zone(struct mlx4_zone_entry *zone, int count, | ||
340 | int align, u32 skip_mask, u32 *puid) | ||
341 | { | ||
342 | u32 uid; | ||
343 | u32 res; | ||
344 | struct mlx4_zone_allocator *zone_alloc = zone->allocator; | ||
345 | struct mlx4_zone_entry *curr_node; | ||
346 | |||
347 | res = mlx4_bitmap_alloc_range(zone->bitmap, count, | ||
348 | align, skip_mask); | ||
349 | |||
350 | if (res != (u32)-1) { | ||
351 | res += zone->offset; | ||
352 | uid = zone->uid; | ||
353 | goto out; | ||
354 | } | ||
355 | |||
356 | list_for_each_entry(curr_node, &zone_alloc->prios, prio_list) { | ||
357 | if (unlikely(curr_node->priority == zone->priority)) | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | if (zone->flags & MLX4_ZONE_ALLOW_ALLOC_FROM_LOWER_PRIO) { | ||
362 | struct mlx4_zone_entry *it = curr_node; | ||
363 | |||
364 | list_for_each_entry_continue_reverse(it, &zone_alloc->entries, list) { | ||
365 | res = mlx4_bitmap_alloc_range(it->bitmap, count, | ||
366 | align, skip_mask); | ||
367 | if (res != (u32)-1) { | ||
368 | res += it->offset; | ||
369 | uid = it->uid; | ||
370 | goto out; | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | |||
375 | if (zone->flags & MLX4_ZONE_ALLOW_ALLOC_FROM_EQ_PRIO) { | ||
376 | struct mlx4_zone_entry *it = curr_node; | ||
377 | |||
378 | list_for_each_entry_from(it, &zone_alloc->entries, list) { | ||
379 | if (unlikely(it == zone)) | ||
380 | continue; | ||
381 | |||
382 | if (unlikely(it->priority != curr_node->priority)) | ||
383 | break; | ||
384 | |||
385 | res = mlx4_bitmap_alloc_range(it->bitmap, count, | ||
386 | align, skip_mask); | ||
387 | if (res != (u32)-1) { | ||
388 | res += it->offset; | ||
389 | uid = it->uid; | ||
390 | goto out; | ||
391 | } | ||
392 | } | ||
393 | } | ||
394 | |||
395 | if (zone->flags & MLX4_ZONE_FALLBACK_TO_HIGHER_PRIO) { | ||
396 | if (list_is_last(&curr_node->prio_list, &zone_alloc->prios)) | ||
397 | goto out; | ||
398 | |||
399 | curr_node = list_first_entry(&curr_node->prio_list, | ||
400 | typeof(*curr_node), | ||
401 | prio_list); | ||
402 | |||
403 | list_for_each_entry_from(curr_node, &zone_alloc->entries, list) { | ||
404 | res = mlx4_bitmap_alloc_range(curr_node->bitmap, count, | ||
405 | align, skip_mask); | ||
406 | if (res != (u32)-1) { | ||
407 | res += curr_node->offset; | ||
408 | uid = curr_node->uid; | ||
409 | goto out; | ||
410 | } | ||
411 | } | ||
412 | } | ||
413 | |||
414 | out: | ||
415 | if (NULL != puid && res != (u32)-1) | ||
416 | *puid = uid; | ||
417 | return res; | ||
418 | } | ||
419 | |||
420 | /* Should be called under a lock */ | ||
421 | static void __mlx4_free_from_zone(struct mlx4_zone_entry *zone, u32 obj, | ||
422 | u32 count) | ||
423 | { | ||
424 | mlx4_bitmap_free_range(zone->bitmap, obj - zone->offset, count, zone->use_rr); | ||
425 | } | ||
426 | |||
427 | /* Should be called under a lock */ | ||
428 | static struct mlx4_zone_entry *__mlx4_find_zone_by_uid( | ||
429 | struct mlx4_zone_allocator *zones, u32 uid) | ||
430 | { | ||
431 | struct mlx4_zone_entry *zone; | ||
432 | |||
433 | list_for_each_entry(zone, &zones->entries, list) { | ||
434 | if (zone->uid == uid) | ||
435 | return zone; | ||
436 | } | ||
437 | |||
438 | return NULL; | ||
439 | } | ||
440 | |||
441 | struct mlx4_bitmap *mlx4_zone_get_bitmap(struct mlx4_zone_allocator *zones, u32 uid) | ||
442 | { | ||
443 | struct mlx4_zone_entry *zone; | ||
444 | struct mlx4_bitmap *bitmap; | ||
445 | |||
446 | spin_lock(&zones->lock); | ||
447 | |||
448 | zone = __mlx4_find_zone_by_uid(zones, uid); | ||
449 | |||
450 | bitmap = zone == NULL ? NULL : zone->bitmap; | ||
451 | |||
452 | spin_unlock(&zones->lock); | ||
453 | |||
454 | return bitmap; | ||
455 | } | ||
456 | |||
457 | int mlx4_zone_remove_one(struct mlx4_zone_allocator *zones, u32 uid) | ||
458 | { | ||
459 | struct mlx4_zone_entry *zone; | ||
460 | int res; | ||
461 | |||
462 | spin_lock(&zones->lock); | ||
463 | |||
464 | zone = __mlx4_find_zone_by_uid(zones, uid); | ||
465 | |||
466 | if (NULL == zone) { | ||
467 | res = -1; | ||
468 | goto out; | ||
469 | } | ||
470 | |||
471 | res = __mlx4_zone_remove_one_entry(zone); | ||
472 | |||
473 | out: | ||
474 | spin_unlock(&zones->lock); | ||
475 | kfree(zone); | ||
476 | |||
477 | return res; | ||
478 | } | ||
479 | |||
480 | /* Should be called under a lock */ | ||
481 | static struct mlx4_zone_entry *__mlx4_find_zone_by_uid_unique( | ||
482 | struct mlx4_zone_allocator *zones, u32 obj) | ||
483 | { | ||
484 | struct mlx4_zone_entry *zone, *zone_candidate = NULL; | ||
485 | u32 dist = (u32)-1; | ||
486 | |||
487 | /* Search for the smallest zone that this obj could be | ||
488 | * allocated from. This is done in order to handle | ||
489 | * situations when small bitmaps are allocated from bigger | ||
490 | * bitmaps (and the allocated space is marked as reserved in | ||
491 | * the bigger bitmap. | ||
492 | */ | ||
493 | list_for_each_entry(zone, &zones->entries, list) { | ||
494 | if (obj >= zone->offset) { | ||
495 | u32 mobj = (obj - zone->offset) & zones->mask; | ||
496 | |||
497 | if (mobj < zone->bitmap->max) { | ||
498 | u32 curr_dist = zone->bitmap->effective_len; | ||
499 | |||
500 | if (curr_dist < dist) { | ||
501 | dist = curr_dist; | ||
502 | zone_candidate = zone; | ||
503 | } | ||
504 | } | ||
505 | } | ||
506 | } | ||
507 | |||
508 | return zone_candidate; | ||
509 | } | ||
510 | |||
511 | u32 mlx4_zone_alloc_entries(struct mlx4_zone_allocator *zones, u32 uid, int count, | ||
512 | int align, u32 skip_mask, u32 *puid) | ||
513 | { | ||
514 | struct mlx4_zone_entry *zone; | ||
515 | int res = -1; | ||
516 | |||
517 | spin_lock(&zones->lock); | ||
518 | |||
519 | zone = __mlx4_find_zone_by_uid(zones, uid); | ||
520 | |||
521 | if (NULL == zone) | ||
522 | goto out; | ||
523 | |||
524 | res = __mlx4_alloc_from_zone(zone, count, align, skip_mask, puid); | ||
525 | |||
526 | out: | ||
527 | spin_unlock(&zones->lock); | ||
528 | |||
529 | return res; | ||
530 | } | ||
531 | |||
532 | u32 mlx4_zone_free_entries(struct mlx4_zone_allocator *zones, u32 uid, u32 obj, u32 count) | ||
533 | { | ||
534 | struct mlx4_zone_entry *zone; | ||
535 | int res = 0; | ||
536 | |||
537 | spin_lock(&zones->lock); | ||
538 | |||
539 | zone = __mlx4_find_zone_by_uid(zones, uid); | ||
540 | |||
541 | if (NULL == zone) { | ||
542 | res = -1; | ||
543 | goto out; | ||
544 | } | ||
545 | |||
546 | __mlx4_free_from_zone(zone, obj, count); | ||
547 | |||
548 | out: | ||
549 | spin_unlock(&zones->lock); | ||
550 | |||
551 | return res; | ||
552 | } | ||
553 | |||
554 | u32 mlx4_zone_free_entries_unique(struct mlx4_zone_allocator *zones, u32 obj, u32 count) | ||
555 | { | ||
556 | struct mlx4_zone_entry *zone; | ||
557 | int res; | ||
558 | |||
559 | if (!(zones->flags & MLX4_ZONE_ALLOC_FLAGS_NO_OVERLAP)) | ||
560 | return -EFAULT; | ||
561 | |||
562 | spin_lock(&zones->lock); | ||
563 | |||
564 | zone = __mlx4_find_zone_by_uid_unique(zones, obj); | ||
565 | |||
566 | if (NULL == zone) { | ||
567 | res = -1; | ||
568 | goto out; | ||
569 | } | ||
570 | |||
571 | __mlx4_free_from_zone(zone, obj, count); | ||
572 | res = 0; | ||
573 | |||
574 | out: | ||
575 | spin_unlock(&zones->lock); | ||
576 | |||
577 | return res; | ||
578 | } | ||
166 | /* | 579 | /* |
167 | * Handling for queue buffers -- we allocate a bunch of memory and | 580 | * Handling for queue buffers -- we allocate a bunch of memory and |
168 | * register it in a memory region at HCA virtual address 0. If the | 581 | * register it in a memory region at HCA virtual address 0. If the |
diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c index 56022d647837..e71f31387ac6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/cq.c | |||
@@ -52,6 +52,51 @@ | |||
52 | #define MLX4_CQ_STATE_ARMED_SOL ( 6 << 8) | 52 | #define MLX4_CQ_STATE_ARMED_SOL ( 6 << 8) |
53 | #define MLX4_EQ_STATE_FIRED (10 << 8) | 53 | #define MLX4_EQ_STATE_FIRED (10 << 8) |
54 | 54 | ||
55 | #define TASKLET_MAX_TIME 2 | ||
56 | #define TASKLET_MAX_TIME_JIFFIES msecs_to_jiffies(TASKLET_MAX_TIME) | ||
57 | |||
58 | void mlx4_cq_tasklet_cb(unsigned long data) | ||
59 | { | ||
60 | unsigned long flags; | ||
61 | unsigned long end = jiffies + TASKLET_MAX_TIME_JIFFIES; | ||
62 | struct mlx4_eq_tasklet *ctx = (struct mlx4_eq_tasklet *)data; | ||
63 | struct mlx4_cq *mcq, *temp; | ||
64 | |||
65 | spin_lock_irqsave(&ctx->lock, flags); | ||
66 | list_splice_tail_init(&ctx->list, &ctx->process_list); | ||
67 | spin_unlock_irqrestore(&ctx->lock, flags); | ||
68 | |||
69 | list_for_each_entry_safe(mcq, temp, &ctx->process_list, tasklet_ctx.list) { | ||
70 | list_del_init(&mcq->tasklet_ctx.list); | ||
71 | mcq->tasklet_ctx.comp(mcq); | ||
72 | if (atomic_dec_and_test(&mcq->refcount)) | ||
73 | complete(&mcq->free); | ||
74 | if (time_after(jiffies, end)) | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | if (!list_empty(&ctx->process_list)) | ||
79 | tasklet_schedule(&ctx->task); | ||
80 | } | ||
81 | |||
82 | static void mlx4_add_cq_to_tasklet(struct mlx4_cq *cq) | ||
83 | { | ||
84 | unsigned long flags; | ||
85 | struct mlx4_eq_tasklet *tasklet_ctx = cq->tasklet_ctx.priv; | ||
86 | |||
87 | spin_lock_irqsave(&tasklet_ctx->lock, flags); | ||
88 | /* When migrating CQs between EQs will be implemented, please note | ||
89 | * that you need to sync this point. It is possible that | ||
90 | * while migrating a CQ, completions on the old EQs could | ||
91 | * still arrive. | ||
92 | */ | ||
93 | if (list_empty_careful(&cq->tasklet_ctx.list)) { | ||
94 | atomic_inc(&cq->refcount); | ||
95 | list_add_tail(&cq->tasklet_ctx.list, &tasklet_ctx->list); | ||
96 | } | ||
97 | spin_unlock_irqrestore(&tasklet_ctx->lock, flags); | ||
98 | } | ||
99 | |||
55 | void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn) | 100 | void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn) |
56 | { | 101 | { |
57 | struct mlx4_cq *cq; | 102 | struct mlx4_cq *cq; |
@@ -292,6 +337,11 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, | |||
292 | cq->uar = uar; | 337 | cq->uar = uar; |
293 | atomic_set(&cq->refcount, 1); | 338 | atomic_set(&cq->refcount, 1); |
294 | init_completion(&cq->free); | 339 | init_completion(&cq->free); |
340 | cq->comp = mlx4_add_cq_to_tasklet; | ||
341 | cq->tasklet_ctx.priv = | ||
342 | &priv->eq_table.eq[cq->vector].tasklet_ctx; | ||
343 | INIT_LIST_HEAD(&cq->tasklet_ctx.list); | ||
344 | |||
295 | 345 | ||
296 | cq->irq = priv->eq_table.eq[cq->vector].irq; | 346 | cq->irq = priv->eq_table.eq[cq->vector].irq; |
297 | return 0; | 347 | return 0; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index dccf0e1f86be..6ff214de1111 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
@@ -595,7 +595,7 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv) | |||
595 | return 0; | 595 | return 0; |
596 | } | 596 | } |
597 | 597 | ||
598 | err = mlx4_qp_reserve_range(dev, 1, 1, qpn); | 598 | err = mlx4_qp_reserve_range(dev, 1, 1, qpn, MLX4_RESERVE_A0_QP); |
599 | en_dbg(DRV, priv, "Reserved qp %d\n", *qpn); | 599 | en_dbg(DRV, priv, "Reserved qp %d\n", *qpn); |
600 | if (err) { | 600 | if (err) { |
601 | en_err(priv, "Failed to reserve qp for mac registration\n"); | 601 | en_err(priv, "Failed to reserve qp for mac registration\n"); |
@@ -1974,15 +1974,8 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) | |||
1974 | { | 1974 | { |
1975 | struct mlx4_en_port_profile *prof = priv->prof; | 1975 | struct mlx4_en_port_profile *prof = priv->prof; |
1976 | int i; | 1976 | int i; |
1977 | int err; | ||
1978 | int node; | 1977 | int node; |
1979 | 1978 | ||
1980 | err = mlx4_qp_reserve_range(priv->mdev->dev, priv->tx_ring_num, 256, &priv->base_tx_qpn); | ||
1981 | if (err) { | ||
1982 | en_err(priv, "failed reserving range for TX rings\n"); | ||
1983 | return err; | ||
1984 | } | ||
1985 | |||
1986 | /* Create tx Rings */ | 1979 | /* Create tx Rings */ |
1987 | for (i = 0; i < priv->tx_ring_num; i++) { | 1980 | for (i = 0; i < priv->tx_ring_num; i++) { |
1988 | node = cpu_to_node(i % num_online_cpus()); | 1981 | node = cpu_to_node(i % num_online_cpus()); |
@@ -1991,7 +1984,6 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) | |||
1991 | goto err; | 1984 | goto err; |
1992 | 1985 | ||
1993 | if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i], | 1986 | if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i], |
1994 | priv->base_tx_qpn + i, | ||
1995 | prof->tx_ring_size, TXBB_SIZE, | 1987 | prof->tx_ring_size, TXBB_SIZE, |
1996 | node, i)) | 1988 | node, i)) |
1997 | goto err; | 1989 | goto err; |
@@ -2602,7 +2594,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, | |||
2602 | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; | 2594 | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; |
2603 | 2595 | ||
2604 | if (mdev->dev->caps.steering_mode == | 2596 | if (mdev->dev->caps.steering_mode == |
2605 | MLX4_STEERING_MODE_DEVICE_MANAGED) | 2597 | MLX4_STEERING_MODE_DEVICE_MANAGED && |
2598 | mdev->dev->caps.dmfs_high_steer_mode != MLX4_STEERING_DMFS_A0_STATIC) | ||
2606 | dev->hw_features |= NETIF_F_NTUPLE; | 2599 | dev->hw_features |= NETIF_F_NTUPLE; |
2607 | 2600 | ||
2608 | if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0) | 2601 | if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0) |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 4ca396e3168f..a0474eb94aa3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c | |||
@@ -888,7 +888,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud | |||
888 | gro_skb->ip_summed = ip_summed; | 888 | gro_skb->ip_summed = ip_summed; |
889 | 889 | ||
890 | if (l2_tunnel && ip_summed == CHECKSUM_UNNECESSARY) | 890 | if (l2_tunnel && ip_summed == CHECKSUM_UNNECESSARY) |
891 | gro_skb->encapsulation = 1; | 891 | gro_skb->csum_level = 1; |
892 | |||
892 | if ((cqe->vlan_my_qpn & | 893 | if ((cqe->vlan_my_qpn & |
893 | cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) && | 894 | cpu_to_be32(MLX4_CQE_VLAN_PRESENT_MASK)) && |
894 | (dev->features & NETIF_F_HW_VLAN_CTAG_RX)) { | 895 | (dev->features & NETIF_F_HW_VLAN_CTAG_RX)) { |
@@ -1130,7 +1131,8 @@ int mlx4_en_create_drop_qp(struct mlx4_en_priv *priv) | |||
1130 | int err; | 1131 | int err; |
1131 | u32 qpn; | 1132 | u32 qpn; |
1132 | 1133 | ||
1133 | err = mlx4_qp_reserve_range(priv->mdev->dev, 1, 1, &qpn); | 1134 | err = mlx4_qp_reserve_range(priv->mdev->dev, 1, 1, &qpn, |
1135 | MLX4_RESERVE_A0_QP); | ||
1134 | if (err) { | 1136 | if (err) { |
1135 | en_err(priv, "Failed reserving drop qpn\n"); | 1137 | en_err(priv, "Failed reserving drop qpn\n"); |
1136 | return err; | 1138 | return err; |
@@ -1173,7 +1175,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv) | |||
1173 | en_dbg(DRV, priv, "Configuring rss steering\n"); | 1175 | en_dbg(DRV, priv, "Configuring rss steering\n"); |
1174 | err = mlx4_qp_reserve_range(mdev->dev, priv->rx_ring_num, | 1176 | err = mlx4_qp_reserve_range(mdev->dev, priv->rx_ring_num, |
1175 | priv->rx_ring_num, | 1177 | priv->rx_ring_num, |
1176 | &rss_map->base_qpn); | 1178 | &rss_map->base_qpn, 0); |
1177 | if (err) { | 1179 | if (err) { |
1178 | en_err(priv, "Failed reserving %d qps\n", priv->rx_ring_num); | 1180 | en_err(priv, "Failed reserving %d qps\n", priv->rx_ring_num); |
1179 | return err; | 1181 | return err; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index d0cecbdd9ba8..a308d41e4de0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include "mlx4_en.h" | 46 | #include "mlx4_en.h" |
47 | 47 | ||
48 | int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, | 48 | int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, |
49 | struct mlx4_en_tx_ring **pring, int qpn, u32 size, | 49 | struct mlx4_en_tx_ring **pring, u32 size, |
50 | u16 stride, int node, int queue_index) | 50 | u16 stride, int node, int queue_index) |
51 | { | 51 | { |
52 | struct mlx4_en_dev *mdev = priv->mdev; | 52 | struct mlx4_en_dev *mdev = priv->mdev; |
@@ -112,11 +112,17 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, | |||
112 | ring, ring->buf, ring->size, ring->buf_size, | 112 | ring, ring->buf, ring->size, ring->buf_size, |
113 | (unsigned long long) ring->wqres.buf.direct.map); | 113 | (unsigned long long) ring->wqres.buf.direct.map); |
114 | 114 | ||
115 | ring->qpn = qpn; | 115 | err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &ring->qpn, |
116 | MLX4_RESERVE_ETH_BF_QP); | ||
117 | if (err) { | ||
118 | en_err(priv, "failed reserving qp for TX ring\n"); | ||
119 | goto err_map; | ||
120 | } | ||
121 | |||
116 | err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp, GFP_KERNEL); | 122 | err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp, GFP_KERNEL); |
117 | if (err) { | 123 | if (err) { |
118 | en_err(priv, "Failed allocating qp %d\n", ring->qpn); | 124 | en_err(priv, "Failed allocating qp %d\n", ring->qpn); |
119 | goto err_map; | 125 | goto err_reserve; |
120 | } | 126 | } |
121 | ring->qp.event = mlx4_en_sqp_event; | 127 | ring->qp.event = mlx4_en_sqp_event; |
122 | 128 | ||
@@ -143,6 +149,8 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, | |||
143 | *pring = ring; | 149 | *pring = ring; |
144 | return 0; | 150 | return 0; |
145 | 151 | ||
152 | err_reserve: | ||
153 | mlx4_qp_release_range(mdev->dev, ring->qpn, 1); | ||
146 | err_map: | 154 | err_map: |
147 | mlx4_en_unmap_buffer(&ring->wqres.buf); | 155 | mlx4_en_unmap_buffer(&ring->wqres.buf); |
148 | err_hwq_res: | 156 | err_hwq_res: |
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index d68b264cee4d..3d275fbaf0eb 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c | |||
@@ -450,7 +450,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) | |||
450 | { | 450 | { |
451 | struct mlx4_priv *priv = mlx4_priv(dev); | 451 | struct mlx4_priv *priv = mlx4_priv(dev); |
452 | struct mlx4_eqe *eqe; | 452 | struct mlx4_eqe *eqe; |
453 | int cqn; | 453 | int cqn = -1; |
454 | int eqes_found = 0; | 454 | int eqes_found = 0; |
455 | int set_ci = 0; | 455 | int set_ci = 0; |
456 | int port; | 456 | int port; |
@@ -758,6 +758,13 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) | |||
758 | 758 | ||
759 | eq_set_ci(eq, 1); | 759 | eq_set_ci(eq, 1); |
760 | 760 | ||
761 | /* cqn is 24bit wide but is initialized such that its higher bits | ||
762 | * are ones too. Thus, if we got any event, cqn's high bits should be off | ||
763 | * and we need to schedule the tasklet. | ||
764 | */ | ||
765 | if (!(cqn & ~0xffffff)) | ||
766 | tasklet_schedule(&eq->tasklet_ctx.task); | ||
767 | |||
761 | return eqes_found; | 768 | return eqes_found; |
762 | } | 769 | } |
763 | 770 | ||
@@ -971,6 +978,12 @@ static int mlx4_create_eq(struct mlx4_dev *dev, int nent, | |||
971 | 978 | ||
972 | eq->cons_index = 0; | 979 | eq->cons_index = 0; |
973 | 980 | ||
981 | INIT_LIST_HEAD(&eq->tasklet_ctx.list); | ||
982 | INIT_LIST_HEAD(&eq->tasklet_ctx.process_list); | ||
983 | spin_lock_init(&eq->tasklet_ctx.lock); | ||
984 | tasklet_init(&eq->tasklet_ctx.task, mlx4_cq_tasklet_cb, | ||
985 | (unsigned long)&eq->tasklet_ctx); | ||
986 | |||
974 | return err; | 987 | return err; |
975 | 988 | ||
976 | err_out_free_mtt: | 989 | err_out_free_mtt: |
@@ -1027,6 +1040,7 @@ static void mlx4_free_eq(struct mlx4_dev *dev, | |||
1027 | } | 1040 | } |
1028 | } | 1041 | } |
1029 | synchronize_irq(eq->irq); | 1042 | synchronize_irq(eq->irq); |
1043 | tasklet_disable(&eq->tasklet_ctx.task); | ||
1030 | 1044 | ||
1031 | mlx4_mtt_cleanup(dev, &eq->mtt); | 1045 | mlx4_mtt_cleanup(dev, &eq->mtt); |
1032 | for (i = 0; i < npages; ++i) | 1046 | for (i = 0; i < npages; ++i) |
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 4251f81a0275..ef3b95bac2ad 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c | |||
@@ -144,7 +144,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) | |||
144 | [15] = "Ethernet Backplane autoneg support", | 144 | [15] = "Ethernet Backplane autoneg support", |
145 | [16] = "CONFIG DEV support", | 145 | [16] = "CONFIG DEV support", |
146 | [17] = "Asymmetric EQs support", | 146 | [17] = "Asymmetric EQs support", |
147 | [18] = "More than 80 VFs support" | 147 | [18] = "More than 80 VFs support", |
148 | [19] = "Performance optimized for limited rule configuration flow steering support" | ||
148 | }; | 149 | }; |
149 | int i; | 150 | int i; |
150 | 151 | ||
@@ -266,10 +267,16 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
266 | #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x64 | 267 | #define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x64 |
267 | #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x68 | 268 | #define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x68 |
268 | 269 | ||
270 | #define QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET 0x6c | ||
271 | |||
269 | #define QUERY_FUNC_CAP_FMR_FLAG 0x80 | 272 | #define QUERY_FUNC_CAP_FMR_FLAG 0x80 |
270 | #define QUERY_FUNC_CAP_FLAG_RDMA 0x40 | 273 | #define QUERY_FUNC_CAP_FLAG_RDMA 0x40 |
271 | #define QUERY_FUNC_CAP_FLAG_ETH 0x80 | 274 | #define QUERY_FUNC_CAP_FLAG_ETH 0x80 |
272 | #define QUERY_FUNC_CAP_FLAG_QUOTAS 0x10 | 275 | #define QUERY_FUNC_CAP_FLAG_QUOTAS 0x10 |
276 | #define QUERY_FUNC_CAP_FLAG_VALID_MAILBOX 0x04 | ||
277 | |||
278 | #define QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG (1UL << 31) | ||
279 | #define QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG (1UL << 30) | ||
273 | 280 | ||
274 | /* when opcode modifier = 1 */ | 281 | /* when opcode modifier = 1 */ |
275 | #define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3 | 282 | #define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3 |
@@ -339,7 +346,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
339 | mlx4_get_active_ports(dev, slave); | 346 | mlx4_get_active_ports(dev, slave); |
340 | /* enable rdma and ethernet interfaces, and new quota locations */ | 347 | /* enable rdma and ethernet interfaces, and new quota locations */ |
341 | field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA | | 348 | field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA | |
342 | QUERY_FUNC_CAP_FLAG_QUOTAS); | 349 | QUERY_FUNC_CAP_FLAG_QUOTAS | QUERY_FUNC_CAP_FLAG_VALID_MAILBOX); |
343 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); | 350 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); |
344 | 351 | ||
345 | field = min( | 352 | field = min( |
@@ -401,6 +408,9 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
401 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); | 408 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); |
402 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP); | 409 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP); |
403 | 410 | ||
411 | size = QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG | | ||
412 | QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG; | ||
413 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET); | ||
404 | } else | 414 | } else |
405 | err = -EINVAL; | 415 | err = -EINVAL; |
406 | 416 | ||
@@ -493,6 +503,19 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port, | |||
493 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); | 503 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); |
494 | func_cap->reserved_eq = size & 0xFFFFFF; | 504 | func_cap->reserved_eq = size & 0xFFFFFF; |
495 | 505 | ||
506 | func_cap->extra_flags = 0; | ||
507 | |||
508 | /* Mailbox data from 0x6c and onward should only be treated if | ||
509 | * QUERY_FUNC_CAP_FLAG_VALID_MAILBOX is set in func_cap->flags | ||
510 | */ | ||
511 | if (func_cap->flags & QUERY_FUNC_CAP_FLAG_VALID_MAILBOX) { | ||
512 | MLX4_GET(size, outbox, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET); | ||
513 | if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG) | ||
514 | func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_BF_RES_QP; | ||
515 | if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG) | ||
516 | func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_A0_RES_QP; | ||
517 | } | ||
518 | |||
496 | goto out; | 519 | goto out; |
497 | } | 520 | } |
498 | 521 | ||
@@ -658,6 +681,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
658 | #define QUERY_DEV_CAP_FW_REASSIGN_MAC 0x9d | 681 | #define QUERY_DEV_CAP_FW_REASSIGN_MAC 0x9d |
659 | #define QUERY_DEV_CAP_VXLAN 0x9e | 682 | #define QUERY_DEV_CAP_VXLAN 0x9e |
660 | #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET 0xb0 | 683 | #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET 0xb0 |
684 | #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET 0xa8 | ||
685 | #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET 0xac | ||
661 | 686 | ||
662 | dev_cap->flags2 = 0; | 687 | dev_cap->flags2 = 0; |
663 | mailbox = mlx4_alloc_cmd_mailbox(dev); | 688 | mailbox = mlx4_alloc_cmd_mailbox(dev); |
@@ -854,6 +879,13 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
854 | if (field32 & (1 << 0)) | 879 | if (field32 & (1 << 0)) |
855 | dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_MAD_DEMUX; | 880 | dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_MAD_DEMUX; |
856 | 881 | ||
882 | MLX4_GET(dev_cap->dmfs_high_rate_qpn_base, outbox, | ||
883 | QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET); | ||
884 | dev_cap->dmfs_high_rate_qpn_base &= MGM_QPN_MASK; | ||
885 | MLX4_GET(dev_cap->dmfs_high_rate_qpn_range, outbox, | ||
886 | QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET); | ||
887 | dev_cap->dmfs_high_rate_qpn_range &= MGM_QPN_MASK; | ||
888 | |||
857 | MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); | 889 | MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); |
858 | if (field32 & (1 << 16)) | 890 | if (field32 & (1 << 16)) |
859 | dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP; | 891 | dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP; |
@@ -864,61 +896,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
864 | if (field32 & (1 << 21)) | 896 | if (field32 & (1 << 21)) |
865 | dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_80_VFS; | 897 | dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_80_VFS; |
866 | 898 | ||
867 | if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { | 899 | for (i = 1; i <= dev_cap->num_ports; i++) { |
868 | for (i = 1; i <= dev_cap->num_ports; ++i) { | 900 | err = mlx4_QUERY_PORT(dev, i, dev_cap->port_cap + i); |
869 | MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); | 901 | if (err) |
870 | dev_cap->max_vl[i] = field >> 4; | 902 | goto out; |
871 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET); | ||
872 | dev_cap->ib_mtu[i] = field >> 4; | ||
873 | dev_cap->max_port_width[i] = field & 0xf; | ||
874 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET); | ||
875 | dev_cap->max_gids[i] = 1 << (field & 0xf); | ||
876 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET); | ||
877 | dev_cap->max_pkeys[i] = 1 << (field & 0xf); | ||
878 | } | ||
879 | } else { | ||
880 | #define QUERY_PORT_SUPPORTED_TYPE_OFFSET 0x00 | ||
881 | #define QUERY_PORT_MTU_OFFSET 0x01 | ||
882 | #define QUERY_PORT_ETH_MTU_OFFSET 0x02 | ||
883 | #define QUERY_PORT_WIDTH_OFFSET 0x06 | ||
884 | #define QUERY_PORT_MAX_GID_PKEY_OFFSET 0x07 | ||
885 | #define QUERY_PORT_MAX_MACVLAN_OFFSET 0x0a | ||
886 | #define QUERY_PORT_MAX_VL_OFFSET 0x0b | ||
887 | #define QUERY_PORT_MAC_OFFSET 0x10 | ||
888 | #define QUERY_PORT_TRANS_VENDOR_OFFSET 0x18 | ||
889 | #define QUERY_PORT_WAVELENGTH_OFFSET 0x1c | ||
890 | #define QUERY_PORT_TRANS_CODE_OFFSET 0x20 | ||
891 | |||
892 | for (i = 1; i <= dev_cap->num_ports; ++i) { | ||
893 | err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT, | ||
894 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); | ||
895 | if (err) | ||
896 | goto out; | ||
897 | |||
898 | MLX4_GET(field, outbox, QUERY_PORT_SUPPORTED_TYPE_OFFSET); | ||
899 | dev_cap->supported_port_types[i] = field & 3; | ||
900 | dev_cap->suggested_type[i] = (field >> 3) & 1; | ||
901 | dev_cap->default_sense[i] = (field >> 4) & 1; | ||
902 | MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET); | ||
903 | dev_cap->ib_mtu[i] = field & 0xf; | ||
904 | MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET); | ||
905 | dev_cap->max_port_width[i] = field & 0xf; | ||
906 | MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET); | ||
907 | dev_cap->max_gids[i] = 1 << (field >> 4); | ||
908 | dev_cap->max_pkeys[i] = 1 << (field & 0xf); | ||
909 | MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET); | ||
910 | dev_cap->max_vl[i] = field & 0xf; | ||
911 | MLX4_GET(field, outbox, QUERY_PORT_MAX_MACVLAN_OFFSET); | ||
912 | dev_cap->log_max_macs[i] = field & 0xf; | ||
913 | dev_cap->log_max_vlans[i] = field >> 4; | ||
914 | MLX4_GET(dev_cap->eth_mtu[i], outbox, QUERY_PORT_ETH_MTU_OFFSET); | ||
915 | MLX4_GET(dev_cap->def_mac[i], outbox, QUERY_PORT_MAC_OFFSET); | ||
916 | MLX4_GET(field32, outbox, QUERY_PORT_TRANS_VENDOR_OFFSET); | ||
917 | dev_cap->trans_type[i] = field32 >> 24; | ||
918 | dev_cap->vendor_oui[i] = field32 & 0xffffff; | ||
919 | MLX4_GET(dev_cap->wavelength[i], outbox, QUERY_PORT_WAVELENGTH_OFFSET); | ||
920 | MLX4_GET(dev_cap->trans_code[i], outbox, QUERY_PORT_TRANS_CODE_OFFSET); | ||
921 | } | ||
922 | } | 903 | } |
923 | 904 | ||
924 | mlx4_dbg(dev, "Base MM extensions: flags %08x, rsvd L_Key %08x\n", | 905 | mlx4_dbg(dev, "Base MM extensions: flags %08x, rsvd L_Key %08x\n", |
@@ -955,8 +936,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
955 | mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", | 936 | mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", |
956 | dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz); | 937 | dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz); |
957 | mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n", | 938 | mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n", |
958 | dev_cap->local_ca_ack_delay, 128 << dev_cap->ib_mtu[1], | 939 | dev_cap->local_ca_ack_delay, 128 << dev_cap->port_cap[1].ib_mtu, |
959 | dev_cap->max_port_width[1]); | 940 | dev_cap->port_cap[1].max_port_width); |
960 | mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n", | 941 | mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n", |
961 | dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg); | 942 | dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg); |
962 | mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n", | 943 | mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n", |
@@ -964,6 +945,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
964 | mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz); | 945 | mlx4_dbg(dev, "Max GSO size: %d\n", dev_cap->max_gso_sz); |
965 | mlx4_dbg(dev, "Max counters: %d\n", dev_cap->max_counters); | 946 | mlx4_dbg(dev, "Max counters: %d\n", dev_cap->max_counters); |
966 | mlx4_dbg(dev, "Max RSS Table size: %d\n", dev_cap->max_rss_tbl_sz); | 947 | mlx4_dbg(dev, "Max RSS Table size: %d\n", dev_cap->max_rss_tbl_sz); |
948 | mlx4_dbg(dev, "DMFS high rate steer QPn base: %d\n", | ||
949 | dev_cap->dmfs_high_rate_qpn_base); | ||
950 | mlx4_dbg(dev, "DMFS high rate steer QPn range: %d\n", | ||
951 | dev_cap->dmfs_high_rate_qpn_range); | ||
967 | 952 | ||
968 | dump_dev_cap_flags(dev, dev_cap->flags); | 953 | dump_dev_cap_flags(dev, dev_cap->flags); |
969 | dump_dev_cap_flags2(dev, dev_cap->flags2); | 954 | dump_dev_cap_flags2(dev, dev_cap->flags2); |
@@ -973,6 +958,89 @@ out: | |||
973 | return err; | 958 | return err; |
974 | } | 959 | } |
975 | 960 | ||
961 | int mlx4_QUERY_PORT(struct mlx4_dev *dev, int port, struct mlx4_port_cap *port_cap) | ||
962 | { | ||
963 | struct mlx4_cmd_mailbox *mailbox; | ||
964 | u32 *outbox; | ||
965 | u8 field; | ||
966 | u32 field32; | ||
967 | int err; | ||
968 | |||
969 | mailbox = mlx4_alloc_cmd_mailbox(dev); | ||
970 | if (IS_ERR(mailbox)) | ||
971 | return PTR_ERR(mailbox); | ||
972 | outbox = mailbox->buf; | ||
973 | |||
974 | if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { | ||
975 | err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, | ||
976 | MLX4_CMD_TIME_CLASS_A, | ||
977 | MLX4_CMD_NATIVE); | ||
978 | |||
979 | if (err) | ||
980 | goto out; | ||
981 | |||
982 | MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); | ||
983 | port_cap->max_vl = field >> 4; | ||
984 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET); | ||
985 | port_cap->ib_mtu = field >> 4; | ||
986 | port_cap->max_port_width = field & 0xf; | ||
987 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET); | ||
988 | port_cap->max_gids = 1 << (field & 0xf); | ||
989 | MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET); | ||
990 | port_cap->max_pkeys = 1 << (field & 0xf); | ||
991 | } else { | ||
992 | #define QUERY_PORT_SUPPORTED_TYPE_OFFSET 0x00 | ||
993 | #define QUERY_PORT_MTU_OFFSET 0x01 | ||
994 | #define QUERY_PORT_ETH_MTU_OFFSET 0x02 | ||
995 | #define QUERY_PORT_WIDTH_OFFSET 0x06 | ||
996 | #define QUERY_PORT_MAX_GID_PKEY_OFFSET 0x07 | ||
997 | #define QUERY_PORT_MAX_MACVLAN_OFFSET 0x0a | ||
998 | #define QUERY_PORT_MAX_VL_OFFSET 0x0b | ||
999 | #define QUERY_PORT_MAC_OFFSET 0x10 | ||
1000 | #define QUERY_PORT_TRANS_VENDOR_OFFSET 0x18 | ||
1001 | #define QUERY_PORT_WAVELENGTH_OFFSET 0x1c | ||
1002 | #define QUERY_PORT_TRANS_CODE_OFFSET 0x20 | ||
1003 | |||
1004 | err = mlx4_cmd_box(dev, 0, mailbox->dma, port, 0, MLX4_CMD_QUERY_PORT, | ||
1005 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); | ||
1006 | if (err) | ||
1007 | goto out; | ||
1008 | |||
1009 | MLX4_GET(field, outbox, QUERY_PORT_SUPPORTED_TYPE_OFFSET); | ||
1010 | port_cap->supported_port_types = field & 3; | ||
1011 | port_cap->suggested_type = (field >> 3) & 1; | ||
1012 | port_cap->default_sense = (field >> 4) & 1; | ||
1013 | port_cap->dmfs_optimized_state = (field >> 5) & 1; | ||
1014 | MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET); | ||
1015 | port_cap->ib_mtu = field & 0xf; | ||
1016 | MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET); | ||
1017 | port_cap->max_port_width = field & 0xf; | ||
1018 | MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET); | ||
1019 | port_cap->max_gids = 1 << (field >> 4); | ||
1020 | port_cap->max_pkeys = 1 << (field & 0xf); | ||
1021 | MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET); | ||
1022 | port_cap->max_vl = field & 0xf; | ||
1023 | MLX4_GET(field, outbox, QUERY_PORT_MAX_MACVLAN_OFFSET); | ||
1024 | port_cap->log_max_macs = field & 0xf; | ||
1025 | port_cap->log_max_vlans = field >> 4; | ||
1026 | MLX4_GET(port_cap->eth_mtu, outbox, QUERY_PORT_ETH_MTU_OFFSET); | ||
1027 | MLX4_GET(port_cap->def_mac, outbox, QUERY_PORT_MAC_OFFSET); | ||
1028 | MLX4_GET(field32, outbox, QUERY_PORT_TRANS_VENDOR_OFFSET); | ||
1029 | port_cap->trans_type = field32 >> 24; | ||
1030 | port_cap->vendor_oui = field32 & 0xffffff; | ||
1031 | MLX4_GET(port_cap->wavelength, outbox, QUERY_PORT_WAVELENGTH_OFFSET); | ||
1032 | MLX4_GET(port_cap->trans_code, outbox, QUERY_PORT_TRANS_CODE_OFFSET); | ||
1033 | } | ||
1034 | |||
1035 | out: | ||
1036 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
1037 | return err; | ||
1038 | } | ||
1039 | |||
1040 | #define DEV_CAP_EXT_2_FLAG_VLAN_CONTROL (1 << 26) | ||
1041 | #define DEV_CAP_EXT_2_FLAG_80_VFS (1 << 21) | ||
1042 | #define DEV_CAP_EXT_2_FLAG_FSM (1 << 20) | ||
1043 | |||
976 | int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, | 1044 | int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, |
977 | struct mlx4_vhcr *vhcr, | 1045 | struct mlx4_vhcr *vhcr, |
978 | struct mlx4_cmd_mailbox *inbox, | 1046 | struct mlx4_cmd_mailbox *inbox, |
@@ -982,7 +1050,7 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
982 | u64 flags; | 1050 | u64 flags; |
983 | int err = 0; | 1051 | int err = 0; |
984 | u8 field; | 1052 | u8 field; |
985 | u32 bmme_flags; | 1053 | u32 bmme_flags, field32; |
986 | int real_port; | 1054 | int real_port; |
987 | int slave_port; | 1055 | int slave_port; |
988 | int first_port; | 1056 | int first_port; |
@@ -1053,6 +1121,12 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
1053 | field &= ~0x80; | 1121 | field &= ~0x80; |
1054 | MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET); | 1122 | MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET); |
1055 | 1123 | ||
1124 | /* turn off host side virt features (VST, FSM, etc) for guests */ | ||
1125 | MLX4_GET(field32, outbox->buf, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); | ||
1126 | field32 &= ~(DEV_CAP_EXT_2_FLAG_VLAN_CONTROL | DEV_CAP_EXT_2_FLAG_80_VFS | | ||
1127 | DEV_CAP_EXT_2_FLAG_FSM); | ||
1128 | MLX4_PUT(outbox->buf, field32, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); | ||
1129 | |||
1056 | return 0; | 1130 | return 0; |
1057 | } | 1131 | } |
1058 | 1132 | ||
@@ -1471,6 +1545,12 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) | |||
1471 | struct mlx4_cmd_mailbox *mailbox; | 1545 | struct mlx4_cmd_mailbox *mailbox; |
1472 | __be32 *inbox; | 1546 | __be32 *inbox; |
1473 | int err; | 1547 | int err; |
1548 | static const u8 a0_dmfs_hw_steering[] = { | ||
1549 | [MLX4_STEERING_DMFS_A0_DEFAULT] = 0, | ||
1550 | [MLX4_STEERING_DMFS_A0_DYNAMIC] = 1, | ||
1551 | [MLX4_STEERING_DMFS_A0_STATIC] = 2, | ||
1552 | [MLX4_STEERING_DMFS_A0_DISABLE] = 3 | ||
1553 | }; | ||
1474 | 1554 | ||
1475 | #define INIT_HCA_IN_SIZE 0x200 | 1555 | #define INIT_HCA_IN_SIZE 0x200 |
1476 | #define INIT_HCA_VERSION_OFFSET 0x000 | 1556 | #define INIT_HCA_VERSION_OFFSET 0x000 |
@@ -1504,6 +1584,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) | |||
1504 | #define INIT_HCA_FS_PARAM_OFFSET 0x1d0 | 1584 | #define INIT_HCA_FS_PARAM_OFFSET 0x1d0 |
1505 | #define INIT_HCA_FS_BASE_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x00) | 1585 | #define INIT_HCA_FS_BASE_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x00) |
1506 | #define INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x12) | 1586 | #define INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x12) |
1587 | #define INIT_HCA_FS_A0_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x18) | ||
1507 | #define INIT_HCA_FS_LOG_TABLE_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x1b) | 1588 | #define INIT_HCA_FS_LOG_TABLE_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x1b) |
1508 | #define INIT_HCA_FS_ETH_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x21) | 1589 | #define INIT_HCA_FS_ETH_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x21) |
1509 | #define INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x22) | 1590 | #define INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x22) |
@@ -1614,8 +1695,11 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) | |||
1614 | /* Enable Ethernet flow steering | 1695 | /* Enable Ethernet flow steering |
1615 | * with udp unicast and tcp unicast | 1696 | * with udp unicast and tcp unicast |
1616 | */ | 1697 | */ |
1617 | MLX4_PUT(inbox, (u8) (MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN), | 1698 | if (dev->caps.dmfs_high_steer_mode != |
1618 | INIT_HCA_FS_ETH_BITS_OFFSET); | 1699 | MLX4_STEERING_DMFS_A0_STATIC) |
1700 | MLX4_PUT(inbox, | ||
1701 | (u8)(MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN), | ||
1702 | INIT_HCA_FS_ETH_BITS_OFFSET); | ||
1619 | MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, | 1703 | MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, |
1620 | INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET); | 1704 | INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET); |
1621 | /* Enable IPoIB flow steering | 1705 | /* Enable IPoIB flow steering |
@@ -1625,6 +1709,13 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) | |||
1625 | INIT_HCA_FS_IB_BITS_OFFSET); | 1709 | INIT_HCA_FS_IB_BITS_OFFSET); |
1626 | MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, | 1710 | MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, |
1627 | INIT_HCA_FS_IB_NUM_ADDRS_OFFSET); | 1711 | INIT_HCA_FS_IB_NUM_ADDRS_OFFSET); |
1712 | |||
1713 | if (dev->caps.dmfs_high_steer_mode != | ||
1714 | MLX4_STEERING_DMFS_A0_NOT_SUPPORTED) | ||
1715 | MLX4_PUT(inbox, | ||
1716 | ((u8)(a0_dmfs_hw_steering[dev->caps.dmfs_high_steer_mode] | ||
1717 | << 6)), | ||
1718 | INIT_HCA_FS_A0_OFFSET); | ||
1628 | } else { | 1719 | } else { |
1629 | MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); | 1720 | MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); |
1630 | MLX4_PUT(inbox, param->log_mc_entry_sz, | 1721 | MLX4_PUT(inbox, param->log_mc_entry_sz, |
@@ -1675,6 +1766,12 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, | |||
1675 | u32 dword_field; | 1766 | u32 dword_field; |
1676 | int err; | 1767 | int err; |
1677 | u8 byte_field; | 1768 | u8 byte_field; |
1769 | static const u8 a0_dmfs_query_hw_steering[] = { | ||
1770 | [0] = MLX4_STEERING_DMFS_A0_DEFAULT, | ||
1771 | [1] = MLX4_STEERING_DMFS_A0_DYNAMIC, | ||
1772 | [2] = MLX4_STEERING_DMFS_A0_STATIC, | ||
1773 | [3] = MLX4_STEERING_DMFS_A0_DISABLE | ||
1774 | }; | ||
1678 | 1775 | ||
1679 | #define QUERY_HCA_GLOBAL_CAPS_OFFSET 0x04 | 1776 | #define QUERY_HCA_GLOBAL_CAPS_OFFSET 0x04 |
1680 | #define QUERY_HCA_CORE_CLOCK_OFFSET 0x0c | 1777 | #define QUERY_HCA_CORE_CLOCK_OFFSET 0x0c |
@@ -1727,6 +1824,10 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, | |||
1727 | INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); | 1824 | INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); |
1728 | MLX4_GET(param->log_mc_table_sz, outbox, | 1825 | MLX4_GET(param->log_mc_table_sz, outbox, |
1729 | INIT_HCA_FS_LOG_TABLE_SZ_OFFSET); | 1826 | INIT_HCA_FS_LOG_TABLE_SZ_OFFSET); |
1827 | MLX4_GET(byte_field, outbox, | ||
1828 | INIT_HCA_FS_A0_OFFSET); | ||
1829 | param->dmfs_high_steer_mode = | ||
1830 | a0_dmfs_query_hw_steering[(byte_field >> 6) & 3]; | ||
1730 | } else { | 1831 | } else { |
1731 | MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET); | 1832 | MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET); |
1732 | MLX4_GET(param->log_mc_entry_sz, outbox, | 1833 | MLX4_GET(param->log_mc_entry_sz, outbox, |
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h index 475215ee370f..794e2826609a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/drivers/net/ethernet/mellanox/mlx4/fw.h | |||
@@ -43,6 +43,26 @@ struct mlx4_mod_stat_cfg { | |||
43 | u8 log_pg_sz_m; | 43 | u8 log_pg_sz_m; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | struct mlx4_port_cap { | ||
47 | u8 supported_port_types; | ||
48 | u8 suggested_type; | ||
49 | u8 default_sense; | ||
50 | u8 log_max_macs; | ||
51 | u8 log_max_vlans; | ||
52 | int ib_mtu; | ||
53 | int max_port_width; | ||
54 | int max_vl; | ||
55 | int max_gids; | ||
56 | int max_pkeys; | ||
57 | u64 def_mac; | ||
58 | u16 eth_mtu; | ||
59 | int trans_type; | ||
60 | int vendor_oui; | ||
61 | u16 wavelength; | ||
62 | u64 trans_code; | ||
63 | u8 dmfs_optimized_state; | ||
64 | }; | ||
65 | |||
46 | struct mlx4_dev_cap { | 66 | struct mlx4_dev_cap { |
47 | int max_srq_sz; | 67 | int max_srq_sz; |
48 | int max_qp_sz; | 68 | int max_qp_sz; |
@@ -67,17 +87,6 @@ struct mlx4_dev_cap { | |||
67 | int local_ca_ack_delay; | 87 | int local_ca_ack_delay; |
68 | int num_ports; | 88 | int num_ports; |
69 | u32 max_msg_sz; | 89 | u32 max_msg_sz; |
70 | int ib_mtu[MLX4_MAX_PORTS + 1]; | ||
71 | int max_port_width[MLX4_MAX_PORTS + 1]; | ||
72 | int max_vl[MLX4_MAX_PORTS + 1]; | ||
73 | int max_gids[MLX4_MAX_PORTS + 1]; | ||
74 | int max_pkeys[MLX4_MAX_PORTS + 1]; | ||
75 | u64 def_mac[MLX4_MAX_PORTS + 1]; | ||
76 | u16 eth_mtu[MLX4_MAX_PORTS + 1]; | ||
77 | int trans_type[MLX4_MAX_PORTS + 1]; | ||
78 | int vendor_oui[MLX4_MAX_PORTS + 1]; | ||
79 | u16 wavelength[MLX4_MAX_PORTS + 1]; | ||
80 | u64 trans_code[MLX4_MAX_PORTS + 1]; | ||
81 | u16 stat_rate_support; | 90 | u16 stat_rate_support; |
82 | int fs_log_max_ucast_qp_range_size; | 91 | int fs_log_max_ucast_qp_range_size; |
83 | int fs_max_num_qp_per_entry; | 92 | int fs_max_num_qp_per_entry; |
@@ -115,12 +124,10 @@ struct mlx4_dev_cap { | |||
115 | u64 max_icm_sz; | 124 | u64 max_icm_sz; |
116 | int max_gso_sz; | 125 | int max_gso_sz; |
117 | int max_rss_tbl_sz; | 126 | int max_rss_tbl_sz; |
118 | u8 supported_port_types[MLX4_MAX_PORTS + 1]; | ||
119 | u8 suggested_type[MLX4_MAX_PORTS + 1]; | ||
120 | u8 default_sense[MLX4_MAX_PORTS + 1]; | ||
121 | u8 log_max_macs[MLX4_MAX_PORTS + 1]; | ||
122 | u8 log_max_vlans[MLX4_MAX_PORTS + 1]; | ||
123 | u32 max_counters; | 127 | u32 max_counters; |
128 | u32 dmfs_high_rate_qpn_base; | ||
129 | u32 dmfs_high_rate_qpn_range; | ||
130 | struct mlx4_port_cap port_cap[MLX4_MAX_PORTS + 1]; | ||
124 | }; | 131 | }; |
125 | 132 | ||
126 | struct mlx4_func_cap { | 133 | struct mlx4_func_cap { |
@@ -144,6 +151,7 @@ struct mlx4_func_cap { | |||
144 | u8 port_flags; | 151 | u8 port_flags; |
145 | u8 flags1; | 152 | u8 flags1; |
146 | u64 phys_port_id; | 153 | u64 phys_port_id; |
154 | u32 extra_flags; | ||
147 | }; | 155 | }; |
148 | 156 | ||
149 | struct mlx4_func { | 157 | struct mlx4_func { |
@@ -189,6 +197,7 @@ struct mlx4_init_hca_param { | |||
189 | u8 mw_enabled; /* Enable memory windows */ | 197 | u8 mw_enabled; /* Enable memory windows */ |
190 | u8 uar_page_sz; /* log pg sz in 4k chunks */ | 198 | u8 uar_page_sz; /* log pg sz in 4k chunks */ |
191 | u8 steering_mode; /* for QUERY_HCA */ | 199 | u8 steering_mode; /* for QUERY_HCA */ |
200 | u8 dmfs_high_steer_mode; /* for QUERY_HCA */ | ||
192 | u64 dev_cap_enabled; | 201 | u64 dev_cap_enabled; |
193 | u16 cqe_size; /* For use only when CQE stride feature enabled */ | 202 | u16 cqe_size; /* For use only when CQE stride feature enabled */ |
194 | u16 eqe_size; /* For use only when EQE stride feature enabled */ | 203 | u16 eqe_size; /* For use only when EQE stride feature enabled */ |
@@ -216,6 +225,7 @@ struct mlx4_set_ib_param { | |||
216 | }; | 225 | }; |
217 | 226 | ||
218 | int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap); | 227 | int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap); |
228 | int mlx4_QUERY_PORT(struct mlx4_dev *dev, int port, struct mlx4_port_cap *port_cap); | ||
219 | int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port, | 229 | int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port, |
220 | struct mlx4_func_cap *func_cap); | 230 | struct mlx4_func_cap *func_cap); |
221 | int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, | 231 | int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, |
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 3044f9e623cb..e25436b24ce7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -105,7 +105,8 @@ MODULE_PARM_DESC(enable_64b_cqe_eqe, | |||
105 | "Enable 64 byte CQEs/EQEs when the FW supports this (default: True)"); | 105 | "Enable 64 byte CQEs/EQEs when the FW supports this (default: True)"); |
106 | 106 | ||
107 | #define PF_CONTEXT_BEHAVIOUR_MASK (MLX4_FUNC_CAP_64B_EQE_CQE | \ | 107 | #define PF_CONTEXT_BEHAVIOUR_MASK (MLX4_FUNC_CAP_64B_EQE_CQE | \ |
108 | MLX4_FUNC_CAP_EQE_CQE_STRIDE) | 108 | MLX4_FUNC_CAP_EQE_CQE_STRIDE | \ |
109 | MLX4_FUNC_CAP_DMFS_A0_STATIC) | ||
109 | 110 | ||
110 | static char mlx4_version[] = | 111 | static char mlx4_version[] = |
111 | DRV_NAME ": Mellanox ConnectX core driver v" | 112 | DRV_NAME ": Mellanox ConnectX core driver v" |
@@ -254,6 +255,46 @@ static void mlx4_enable_cqe_eqe_stride(struct mlx4_dev *dev) | |||
254 | } | 255 | } |
255 | } | 256 | } |
256 | 257 | ||
258 | static int _mlx4_dev_port(struct mlx4_dev *dev, int port, | ||
259 | struct mlx4_port_cap *port_cap) | ||
260 | { | ||
261 | dev->caps.vl_cap[port] = port_cap->max_vl; | ||
262 | dev->caps.ib_mtu_cap[port] = port_cap->ib_mtu; | ||
263 | dev->phys_caps.gid_phys_table_len[port] = port_cap->max_gids; | ||
264 | dev->phys_caps.pkey_phys_table_len[port] = port_cap->max_pkeys; | ||
265 | /* set gid and pkey table operating lengths by default | ||
266 | * to non-sriov values | ||
267 | */ | ||
268 | dev->caps.gid_table_len[port] = port_cap->max_gids; | ||
269 | dev->caps.pkey_table_len[port] = port_cap->max_pkeys; | ||
270 | dev->caps.port_width_cap[port] = port_cap->max_port_width; | ||
271 | dev->caps.eth_mtu_cap[port] = port_cap->eth_mtu; | ||
272 | dev->caps.def_mac[port] = port_cap->def_mac; | ||
273 | dev->caps.supported_type[port] = port_cap->supported_port_types; | ||
274 | dev->caps.suggested_type[port] = port_cap->suggested_type; | ||
275 | dev->caps.default_sense[port] = port_cap->default_sense; | ||
276 | dev->caps.trans_type[port] = port_cap->trans_type; | ||
277 | dev->caps.vendor_oui[port] = port_cap->vendor_oui; | ||
278 | dev->caps.wavelength[port] = port_cap->wavelength; | ||
279 | dev->caps.trans_code[port] = port_cap->trans_code; | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int mlx4_dev_port(struct mlx4_dev *dev, int port, | ||
285 | struct mlx4_port_cap *port_cap) | ||
286 | { | ||
287 | int err = 0; | ||
288 | |||
289 | err = mlx4_QUERY_PORT(dev, port, port_cap); | ||
290 | |||
291 | if (err) | ||
292 | mlx4_err(dev, "QUERY_PORT command failed.\n"); | ||
293 | |||
294 | return err; | ||
295 | } | ||
296 | |||
297 | #define MLX4_A0_STEERING_TABLE_SIZE 256 | ||
257 | static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | 298 | static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) |
258 | { | 299 | { |
259 | int err; | 300 | int err; |
@@ -289,24 +330,11 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
289 | dev->caps.num_sys_eqs : | 330 | dev->caps.num_sys_eqs : |
290 | MLX4_MAX_EQ_NUM; | 331 | MLX4_MAX_EQ_NUM; |
291 | for (i = 1; i <= dev->caps.num_ports; ++i) { | 332 | for (i = 1; i <= dev->caps.num_ports; ++i) { |
292 | dev->caps.vl_cap[i] = dev_cap->max_vl[i]; | 333 | err = _mlx4_dev_port(dev, i, dev_cap->port_cap + i); |
293 | dev->caps.ib_mtu_cap[i] = dev_cap->ib_mtu[i]; | 334 | if (err) { |
294 | dev->phys_caps.gid_phys_table_len[i] = dev_cap->max_gids[i]; | 335 | mlx4_err(dev, "QUERY_PORT command failed, aborting\n"); |
295 | dev->phys_caps.pkey_phys_table_len[i] = dev_cap->max_pkeys[i]; | 336 | return err; |
296 | /* set gid and pkey table operating lengths by default | 337 | } |
297 | * to non-sriov values */ | ||
298 | dev->caps.gid_table_len[i] = dev_cap->max_gids[i]; | ||
299 | dev->caps.pkey_table_len[i] = dev_cap->max_pkeys[i]; | ||
300 | dev->caps.port_width_cap[i] = dev_cap->max_port_width[i]; | ||
301 | dev->caps.eth_mtu_cap[i] = dev_cap->eth_mtu[i]; | ||
302 | dev->caps.def_mac[i] = dev_cap->def_mac[i]; | ||
303 | dev->caps.supported_type[i] = dev_cap->supported_port_types[i]; | ||
304 | dev->caps.suggested_type[i] = dev_cap->suggested_type[i]; | ||
305 | dev->caps.default_sense[i] = dev_cap->default_sense[i]; | ||
306 | dev->caps.trans_type[i] = dev_cap->trans_type[i]; | ||
307 | dev->caps.vendor_oui[i] = dev_cap->vendor_oui[i]; | ||
308 | dev->caps.wavelength[i] = dev_cap->wavelength[i]; | ||
309 | dev->caps.trans_code[i] = dev_cap->trans_code[i]; | ||
310 | } | 338 | } |
311 | 339 | ||
312 | dev->caps.uar_page_size = PAGE_SIZE; | 340 | dev->caps.uar_page_size = PAGE_SIZE; |
@@ -415,13 +443,13 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
415 | dev->caps.possible_type[i] = dev->caps.port_type[i]; | 443 | dev->caps.possible_type[i] = dev->caps.port_type[i]; |
416 | } | 444 | } |
417 | 445 | ||
418 | if (dev->caps.log_num_macs > dev_cap->log_max_macs[i]) { | 446 | if (dev->caps.log_num_macs > dev_cap->port_cap[i].log_max_macs) { |
419 | dev->caps.log_num_macs = dev_cap->log_max_macs[i]; | 447 | dev->caps.log_num_macs = dev_cap->port_cap[i].log_max_macs; |
420 | mlx4_warn(dev, "Requested number of MACs is too much for port %d, reducing to %d\n", | 448 | mlx4_warn(dev, "Requested number of MACs is too much for port %d, reducing to %d\n", |
421 | i, 1 << dev->caps.log_num_macs); | 449 | i, 1 << dev->caps.log_num_macs); |
422 | } | 450 | } |
423 | if (dev->caps.log_num_vlans > dev_cap->log_max_vlans[i]) { | 451 | if (dev->caps.log_num_vlans > dev_cap->port_cap[i].log_max_vlans) { |
424 | dev->caps.log_num_vlans = dev_cap->log_max_vlans[i]; | 452 | dev->caps.log_num_vlans = dev_cap->port_cap[i].log_max_vlans; |
425 | mlx4_warn(dev, "Requested number of VLANs is too much for port %d, reducing to %d\n", | 453 | mlx4_warn(dev, "Requested number of VLANs is too much for port %d, reducing to %d\n", |
426 | i, 1 << dev->caps.log_num_vlans); | 454 | i, 1 << dev->caps.log_num_vlans); |
427 | } | 455 | } |
@@ -437,6 +465,28 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
437 | dev->caps.num_ports; | 465 | dev->caps.num_ports; |
438 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH] = MLX4_NUM_FEXCH; | 466 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH] = MLX4_NUM_FEXCH; |
439 | 467 | ||
468 | if (dev_cap->dmfs_high_rate_qpn_base > 0 && | ||
469 | dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FS_EN) | ||
470 | dev->caps.dmfs_high_rate_qpn_base = dev_cap->dmfs_high_rate_qpn_base; | ||
471 | else | ||
472 | dev->caps.dmfs_high_rate_qpn_base = | ||
473 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW]; | ||
474 | |||
475 | if (dev_cap->dmfs_high_rate_qpn_range > 0 && | ||
476 | dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FS_EN) { | ||
477 | dev->caps.dmfs_high_rate_qpn_range = dev_cap->dmfs_high_rate_qpn_range; | ||
478 | dev->caps.dmfs_high_steer_mode = MLX4_STEERING_DMFS_A0_DEFAULT; | ||
479 | dev->caps.flags2 |= MLX4_DEV_CAP_FLAG2_FS_A0; | ||
480 | } else { | ||
481 | dev->caps.dmfs_high_steer_mode = MLX4_STEERING_DMFS_A0_NOT_SUPPORTED; | ||
482 | dev->caps.dmfs_high_rate_qpn_base = | ||
483 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW]; | ||
484 | dev->caps.dmfs_high_rate_qpn_range = MLX4_A0_STEERING_TABLE_SIZE; | ||
485 | } | ||
486 | |||
487 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_RSS_RAW_ETH] = | ||
488 | dev->caps.dmfs_high_rate_qpn_range; | ||
489 | |||
440 | dev->caps.reserved_qps = dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] + | 490 | dev->caps.reserved_qps = dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] + |
441 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] + | 491 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] + |
442 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] + | 492 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_ADDR] + |
@@ -466,8 +516,14 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
466 | mlx4_is_master(dev)) | 516 | mlx4_is_master(dev)) |
467 | dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE; | 517 | dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE; |
468 | 518 | ||
469 | if (!mlx4_is_slave(dev)) | 519 | if (!mlx4_is_slave(dev)) { |
470 | mlx4_enable_cqe_eqe_stride(dev); | 520 | mlx4_enable_cqe_eqe_stride(dev); |
521 | dev->caps.alloc_res_qp_mask = | ||
522 | (dev->caps.bf_reg_size ? MLX4_RESERVE_ETH_BF_QP : 0) | | ||
523 | MLX4_RESERVE_A0_QP; | ||
524 | } else { | ||
525 | dev->caps.alloc_res_qp_mask = 0; | ||
526 | } | ||
471 | 527 | ||
472 | return 0; | 528 | return 0; |
473 | } | 529 | } |
@@ -718,7 +774,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) | |||
718 | 774 | ||
719 | if ((func_cap.pf_context_behaviour | PF_CONTEXT_BEHAVIOUR_MASK) != | 775 | if ((func_cap.pf_context_behaviour | PF_CONTEXT_BEHAVIOUR_MASK) != |
720 | PF_CONTEXT_BEHAVIOUR_MASK) { | 776 | PF_CONTEXT_BEHAVIOUR_MASK) { |
721 | mlx4_err(dev, "Unknown pf context behaviour\n"); | 777 | mlx4_err(dev, "Unknown pf context behaviour %x known flags %x\n", |
778 | func_cap.pf_context_behaviour, PF_CONTEXT_BEHAVIOUR_MASK); | ||
722 | return -ENOSYS; | 779 | return -ENOSYS; |
723 | } | 780 | } |
724 | 781 | ||
@@ -817,6 +874,13 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) | |||
817 | 874 | ||
818 | slave_adjust_steering_mode(dev, &dev_cap, &hca_param); | 875 | slave_adjust_steering_mode(dev, &dev_cap, &hca_param); |
819 | 876 | ||
877 | if (func_cap.extra_flags & MLX4_QUERY_FUNC_FLAGS_BF_RES_QP && | ||
878 | dev->caps.bf_reg_size) | ||
879 | dev->caps.alloc_res_qp_mask |= MLX4_RESERVE_ETH_BF_QP; | ||
880 | |||
881 | if (func_cap.extra_flags & MLX4_QUERY_FUNC_FLAGS_A0_RES_QP) | ||
882 | dev->caps.alloc_res_qp_mask |= MLX4_RESERVE_A0_QP; | ||
883 | |||
820 | return 0; | 884 | return 0; |
821 | 885 | ||
822 | err_mem: | 886 | err_mem: |
@@ -1598,10 +1662,46 @@ static int choose_log_fs_mgm_entry_size(int qp_per_entry) | |||
1598 | return (i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE) ? i : -1; | 1662 | return (i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE) ? i : -1; |
1599 | } | 1663 | } |
1600 | 1664 | ||
1665 | static const char *dmfs_high_rate_steering_mode_str(int dmfs_high_steer_mode) | ||
1666 | { | ||
1667 | switch (dmfs_high_steer_mode) { | ||
1668 | case MLX4_STEERING_DMFS_A0_DEFAULT: | ||
1669 | return "default performance"; | ||
1670 | |||
1671 | case MLX4_STEERING_DMFS_A0_DYNAMIC: | ||
1672 | return "dynamic hybrid mode"; | ||
1673 | |||
1674 | case MLX4_STEERING_DMFS_A0_STATIC: | ||
1675 | return "performance optimized for limited rule configuration (static)"; | ||
1676 | |||
1677 | case MLX4_STEERING_DMFS_A0_DISABLE: | ||
1678 | return "disabled performance optimized steering"; | ||
1679 | |||
1680 | case MLX4_STEERING_DMFS_A0_NOT_SUPPORTED: | ||
1681 | return "performance optimized steering not supported"; | ||
1682 | |||
1683 | default: | ||
1684 | return "Unrecognized mode"; | ||
1685 | } | ||
1686 | } | ||
1687 | |||
1688 | #define MLX4_DMFS_A0_STEERING (1UL << 2) | ||
1689 | |||
1601 | static void choose_steering_mode(struct mlx4_dev *dev, | 1690 | static void choose_steering_mode(struct mlx4_dev *dev, |
1602 | struct mlx4_dev_cap *dev_cap) | 1691 | struct mlx4_dev_cap *dev_cap) |
1603 | { | 1692 | { |
1604 | if (mlx4_log_num_mgm_entry_size == -1 && | 1693 | if (mlx4_log_num_mgm_entry_size <= 0) { |
1694 | if ((-mlx4_log_num_mgm_entry_size) & MLX4_DMFS_A0_STEERING) { | ||
1695 | if (dev->caps.dmfs_high_steer_mode == | ||
1696 | MLX4_STEERING_DMFS_A0_NOT_SUPPORTED) | ||
1697 | mlx4_err(dev, "DMFS high rate mode not supported\n"); | ||
1698 | else | ||
1699 | dev->caps.dmfs_high_steer_mode = | ||
1700 | MLX4_STEERING_DMFS_A0_STATIC; | ||
1701 | } | ||
1702 | } | ||
1703 | |||
1704 | if (mlx4_log_num_mgm_entry_size <= 0 && | ||
1605 | dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN && | 1705 | dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN && |
1606 | (!mlx4_is_mfunc(dev) || | 1706 | (!mlx4_is_mfunc(dev) || |
1607 | (dev_cap->fs_max_num_qp_per_entry >= (dev->num_vfs + 1))) && | 1707 | (dev_cap->fs_max_num_qp_per_entry >= (dev->num_vfs + 1))) && |
@@ -1614,6 +1714,9 @@ static void choose_steering_mode(struct mlx4_dev *dev, | |||
1614 | dev->caps.fs_log_max_ucast_qp_range_size = | 1714 | dev->caps.fs_log_max_ucast_qp_range_size = |
1615 | dev_cap->fs_log_max_ucast_qp_range_size; | 1715 | dev_cap->fs_log_max_ucast_qp_range_size; |
1616 | } else { | 1716 | } else { |
1717 | if (dev->caps.dmfs_high_steer_mode != | ||
1718 | MLX4_STEERING_DMFS_A0_NOT_SUPPORTED) | ||
1719 | dev->caps.dmfs_high_steer_mode = MLX4_STEERING_DMFS_A0_DISABLE; | ||
1617 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && | 1720 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && |
1618 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) | 1721 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) |
1619 | dev->caps.steering_mode = MLX4_STEERING_MODE_B0; | 1722 | dev->caps.steering_mode = MLX4_STEERING_MODE_B0; |
@@ -1640,7 +1743,8 @@ static void choose_tunnel_offload_mode(struct mlx4_dev *dev, | |||
1640 | struct mlx4_dev_cap *dev_cap) | 1743 | struct mlx4_dev_cap *dev_cap) |
1641 | { | 1744 | { |
1642 | if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED && | 1745 | if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED && |
1643 | dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS) | 1746 | dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS && |
1747 | dev->caps.dmfs_high_steer_mode != MLX4_STEERING_DMFS_A0_STATIC) | ||
1644 | dev->caps.tunnel_offload_mode = MLX4_TUNNEL_OFFLOAD_MODE_VXLAN; | 1748 | dev->caps.tunnel_offload_mode = MLX4_TUNNEL_OFFLOAD_MODE_VXLAN; |
1645 | else | 1749 | else |
1646 | dev->caps.tunnel_offload_mode = MLX4_TUNNEL_OFFLOAD_MODE_NONE; | 1750 | dev->caps.tunnel_offload_mode = MLX4_TUNNEL_OFFLOAD_MODE_NONE; |
@@ -1649,6 +1753,35 @@ static void choose_tunnel_offload_mode(struct mlx4_dev *dev, | |||
1649 | == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) ? "vxlan" : "none"); | 1753 | == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) ? "vxlan" : "none"); |
1650 | } | 1754 | } |
1651 | 1755 | ||
1756 | static int mlx4_validate_optimized_steering(struct mlx4_dev *dev) | ||
1757 | { | ||
1758 | int i; | ||
1759 | struct mlx4_port_cap port_cap; | ||
1760 | |||
1761 | if (dev->caps.dmfs_high_steer_mode == MLX4_STEERING_DMFS_A0_NOT_SUPPORTED) | ||
1762 | return -EINVAL; | ||
1763 | |||
1764 | for (i = 1; i <= dev->caps.num_ports; i++) { | ||
1765 | if (mlx4_dev_port(dev, i, &port_cap)) { | ||
1766 | mlx4_err(dev, | ||
1767 | "QUERY_DEV_CAP command failed, can't veify DMFS high rate steering.\n"); | ||
1768 | } else if ((dev->caps.dmfs_high_steer_mode != | ||
1769 | MLX4_STEERING_DMFS_A0_DEFAULT) && | ||
1770 | (port_cap.dmfs_optimized_state == | ||
1771 | !!(dev->caps.dmfs_high_steer_mode == | ||
1772 | MLX4_STEERING_DMFS_A0_DISABLE))) { | ||
1773 | mlx4_err(dev, | ||
1774 | "DMFS high rate steer mode differ, driver requested %s but %s in FW.\n", | ||
1775 | dmfs_high_rate_steering_mode_str( | ||
1776 | dev->caps.dmfs_high_steer_mode), | ||
1777 | (port_cap.dmfs_optimized_state ? | ||
1778 | "enabled" : "disabled")); | ||
1779 | } | ||
1780 | } | ||
1781 | |||
1782 | return 0; | ||
1783 | } | ||
1784 | |||
1652 | static int mlx4_init_fw(struct mlx4_dev *dev) | 1785 | static int mlx4_init_fw(struct mlx4_dev *dev) |
1653 | { | 1786 | { |
1654 | struct mlx4_mod_stat_cfg mlx4_cfg; | 1787 | struct mlx4_mod_stat_cfg mlx4_cfg; |
@@ -1701,6 +1834,10 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
1701 | choose_steering_mode(dev, &dev_cap); | 1834 | choose_steering_mode(dev, &dev_cap); |
1702 | choose_tunnel_offload_mode(dev, &dev_cap); | 1835 | choose_tunnel_offload_mode(dev, &dev_cap); |
1703 | 1836 | ||
1837 | if (dev->caps.dmfs_high_steer_mode == MLX4_STEERING_DMFS_A0_STATIC && | ||
1838 | mlx4_is_master(dev)) | ||
1839 | dev->caps.function_caps |= MLX4_FUNC_CAP_DMFS_A0_STATIC; | ||
1840 | |||
1704 | err = mlx4_get_phys_port_id(dev); | 1841 | err = mlx4_get_phys_port_id(dev); |
1705 | if (err) | 1842 | if (err) |
1706 | mlx4_err(dev, "Fail to get physical port id\n"); | 1843 | mlx4_err(dev, "Fail to get physical port id\n"); |
@@ -1787,6 +1924,24 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
1787 | mlx4_err(dev, "Failed to map internal clock. Timestamping is not supported\n"); | 1924 | mlx4_err(dev, "Failed to map internal clock. Timestamping is not supported\n"); |
1788 | } | 1925 | } |
1789 | } | 1926 | } |
1927 | |||
1928 | if (dev->caps.dmfs_high_steer_mode != | ||
1929 | MLX4_STEERING_DMFS_A0_NOT_SUPPORTED) { | ||
1930 | if (mlx4_validate_optimized_steering(dev)) | ||
1931 | mlx4_warn(dev, "Optimized steering validation failed\n"); | ||
1932 | |||
1933 | if (dev->caps.dmfs_high_steer_mode == | ||
1934 | MLX4_STEERING_DMFS_A0_DISABLE) { | ||
1935 | dev->caps.dmfs_high_rate_qpn_base = | ||
1936 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW]; | ||
1937 | dev->caps.dmfs_high_rate_qpn_range = | ||
1938 | MLX4_A0_STEERING_TABLE_SIZE; | ||
1939 | } | ||
1940 | |||
1941 | mlx4_dbg(dev, "DMFS high rate steer mode is: %s\n", | ||
1942 | dmfs_high_rate_steering_mode_str( | ||
1943 | dev->caps.dmfs_high_steer_mode)); | ||
1944 | } | ||
1790 | } else { | 1945 | } else { |
1791 | err = mlx4_init_slave(dev); | 1946 | err = mlx4_init_slave(dev); |
1792 | if (err) { | 1947 | if (err) { |
@@ -3159,10 +3314,11 @@ static int __init mlx4_verify_params(void) | |||
3159 | port_type_array[0] = true; | 3314 | port_type_array[0] = true; |
3160 | } | 3315 | } |
3161 | 3316 | ||
3162 | if (mlx4_log_num_mgm_entry_size != -1 && | 3317 | if (mlx4_log_num_mgm_entry_size < -7 || |
3163 | (mlx4_log_num_mgm_entry_size < MLX4_MIN_MGM_LOG_ENTRY_SIZE || | 3318 | (mlx4_log_num_mgm_entry_size > 0 && |
3164 | mlx4_log_num_mgm_entry_size > MLX4_MAX_MGM_LOG_ENTRY_SIZE)) { | 3319 | (mlx4_log_num_mgm_entry_size < MLX4_MIN_MGM_LOG_ENTRY_SIZE || |
3165 | pr_warn("mlx4_core: mlx4_log_num_mgm_entry_size (%d) not in legal range (-1 or %d..%d)\n", | 3320 | mlx4_log_num_mgm_entry_size > MLX4_MAX_MGM_LOG_ENTRY_SIZE))) { |
3321 | pr_warn("mlx4_core: mlx4_log_num_mgm_entry_size (%d) not in legal range (-7..0 or %d..%d)\n", | ||
3166 | mlx4_log_num_mgm_entry_size, | 3322 | mlx4_log_num_mgm_entry_size, |
3167 | MLX4_MIN_MGM_LOG_ENTRY_SIZE, | 3323 | MLX4_MIN_MGM_LOG_ENTRY_SIZE, |
3168 | MLX4_MAX_MGM_LOG_ENTRY_SIZE); | 3324 | MLX4_MAX_MGM_LOG_ENTRY_SIZE); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index 872843179f44..a3867e7ef885 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c | |||
@@ -999,12 +999,27 @@ int mlx4_flow_attach(struct mlx4_dev *dev, | |||
999 | } | 999 | } |
1000 | 1000 | ||
1001 | ret = mlx4_QP_FLOW_STEERING_ATTACH(dev, mailbox, size >> 2, reg_id); | 1001 | ret = mlx4_QP_FLOW_STEERING_ATTACH(dev, mailbox, size >> 2, reg_id); |
1002 | if (ret == -ENOMEM) | 1002 | if (ret == -ENOMEM) { |
1003 | mlx4_err_rule(dev, | 1003 | mlx4_err_rule(dev, |
1004 | "mcg table is full. Fail to register network rule\n", | 1004 | "mcg table is full. Fail to register network rule\n", |
1005 | rule); | 1005 | rule); |
1006 | else if (ret) | 1006 | } else if (ret) { |
1007 | mlx4_err_rule(dev, "Fail to register network rule\n", rule); | 1007 | if (ret == -ENXIO) { |
1008 | if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) | ||
1009 | mlx4_err_rule(dev, | ||
1010 | "DMFS is not enabled, " | ||
1011 | "failed to register network rule.\n", | ||
1012 | rule); | ||
1013 | else | ||
1014 | mlx4_err_rule(dev, | ||
1015 | "Rule exceeds the dmfs_high_rate_mode limitations, " | ||
1016 | "failed to register network rule.\n", | ||
1017 | rule); | ||
1018 | |||
1019 | } else { | ||
1020 | mlx4_err_rule(dev, "Fail to register network rule.\n", rule); | ||
1021 | } | ||
1022 | } | ||
1008 | 1023 | ||
1009 | mlx4_free_cmd_mailbox(dev, mailbox); | 1024 | mlx4_free_cmd_mailbox(dev, mailbox); |
1010 | 1025 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index f48e7c3eecf8..bdd4eea2247c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -43,6 +43,8 @@ | |||
43 | #include <linux/timer.h> | 43 | #include <linux/timer.h> |
44 | #include <linux/semaphore.h> | 44 | #include <linux/semaphore.h> |
45 | #include <linux/workqueue.h> | 45 | #include <linux/workqueue.h> |
46 | #include <linux/interrupt.h> | ||
47 | #include <linux/spinlock.h> | ||
46 | 48 | ||
47 | #include <linux/mlx4/device.h> | 49 | #include <linux/mlx4/device.h> |
48 | #include <linux/mlx4/driver.h> | 50 | #include <linux/mlx4/driver.h> |
@@ -243,6 +245,7 @@ struct mlx4_bitmap { | |||
243 | u32 reserved_top; | 245 | u32 reserved_top; |
244 | u32 mask; | 246 | u32 mask; |
245 | u32 avail; | 247 | u32 avail; |
248 | u32 effective_len; | ||
246 | spinlock_t lock; | 249 | spinlock_t lock; |
247 | unsigned long *table; | 250 | unsigned long *table; |
248 | }; | 251 | }; |
@@ -373,6 +376,14 @@ struct mlx4_srq_context { | |||
373 | __be64 db_rec_addr; | 376 | __be64 db_rec_addr; |
374 | }; | 377 | }; |
375 | 378 | ||
379 | struct mlx4_eq_tasklet { | ||
380 | struct list_head list; | ||
381 | struct list_head process_list; | ||
382 | struct tasklet_struct task; | ||
383 | /* lock on completion tasklet list */ | ||
384 | spinlock_t lock; | ||
385 | }; | ||
386 | |||
376 | struct mlx4_eq { | 387 | struct mlx4_eq { |
377 | struct mlx4_dev *dev; | 388 | struct mlx4_dev *dev; |
378 | void __iomem *doorbell; | 389 | void __iomem *doorbell; |
@@ -383,6 +394,7 @@ struct mlx4_eq { | |||
383 | int nent; | 394 | int nent; |
384 | struct mlx4_buf_list *page_list; | 395 | struct mlx4_buf_list *page_list; |
385 | struct mlx4_mtt mtt; | 396 | struct mlx4_mtt mtt; |
397 | struct mlx4_eq_tasklet tasklet_ctx; | ||
386 | }; | 398 | }; |
387 | 399 | ||
388 | struct mlx4_slave_eqe { | 400 | struct mlx4_slave_eqe { |
@@ -670,8 +682,17 @@ struct mlx4_srq_table { | |||
670 | struct mlx4_icm_table cmpt_table; | 682 | struct mlx4_icm_table cmpt_table; |
671 | }; | 683 | }; |
672 | 684 | ||
685 | enum mlx4_qp_table_zones { | ||
686 | MLX4_QP_TABLE_ZONE_GENERAL, | ||
687 | MLX4_QP_TABLE_ZONE_RSS, | ||
688 | MLX4_QP_TABLE_ZONE_RAW_ETH, | ||
689 | MLX4_QP_TABLE_ZONE_NUM | ||
690 | }; | ||
691 | |||
673 | struct mlx4_qp_table { | 692 | struct mlx4_qp_table { |
674 | struct mlx4_bitmap bitmap; | 693 | struct mlx4_bitmap *bitmap_gen; |
694 | struct mlx4_zone_allocator *zones; | ||
695 | u32 zones_uids[MLX4_QP_TABLE_ZONE_NUM]; | ||
675 | u32 rdmarc_base; | 696 | u32 rdmarc_base; |
676 | int rdmarc_shift; | 697 | int rdmarc_shift; |
677 | spinlock_t lock; | 698 | spinlock_t lock; |
@@ -873,7 +894,8 @@ extern struct workqueue_struct *mlx4_wq; | |||
873 | 894 | ||
874 | u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap); | 895 | u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap); |
875 | void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr); | 896 | void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr); |
876 | u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align); | 897 | u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, |
898 | int align, u32 skip_mask); | ||
877 | void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt, | 899 | void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt, |
878 | int use_rr); | 900 | int use_rr); |
879 | u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap); | 901 | u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap); |
@@ -959,7 +981,7 @@ int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, | |||
959 | struct mlx4_cmd_mailbox *outbox, | 981 | struct mlx4_cmd_mailbox *outbox, |
960 | struct mlx4_cmd_info *cmd); | 982 | struct mlx4_cmd_info *cmd); |
961 | int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, | 983 | int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, |
962 | int *base); | 984 | int *base, u8 flags); |
963 | void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt); | 985 | void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt); |
964 | int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac); | 986 | int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac); |
965 | void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac); | 987 | void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac); |
@@ -1146,6 +1168,7 @@ void mlx4_cmd_use_polling(struct mlx4_dev *dev); | |||
1146 | int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param, | 1168 | int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param, |
1147 | unsigned long timeout); | 1169 | unsigned long timeout); |
1148 | 1170 | ||
1171 | void mlx4_cq_tasklet_cb(unsigned long data); | ||
1149 | void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn); | 1172 | void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn); |
1150 | void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type); | 1173 | void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type); |
1151 | 1174 | ||
@@ -1332,4 +1355,72 @@ int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave, int port); | |||
1332 | int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave); | 1355 | int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave); |
1333 | int mlx4_config_mad_demux(struct mlx4_dev *dev); | 1356 | int mlx4_config_mad_demux(struct mlx4_dev *dev); |
1334 | 1357 | ||
1358 | enum mlx4_zone_flags { | ||
1359 | MLX4_ZONE_ALLOW_ALLOC_FROM_LOWER_PRIO = 1UL << 0, | ||
1360 | MLX4_ZONE_ALLOW_ALLOC_FROM_EQ_PRIO = 1UL << 1, | ||
1361 | MLX4_ZONE_FALLBACK_TO_HIGHER_PRIO = 1UL << 2, | ||
1362 | MLX4_ZONE_USE_RR = 1UL << 3, | ||
1363 | }; | ||
1364 | |||
1365 | enum mlx4_zone_alloc_flags { | ||
1366 | /* No two objects could overlap between zones. UID | ||
1367 | * could be left unused. If this flag is given and | ||
1368 | * two overlapped zones are used, an object will be free'd | ||
1369 | * from the smallest possible matching zone. | ||
1370 | */ | ||
1371 | MLX4_ZONE_ALLOC_FLAGS_NO_OVERLAP = 1UL << 0, | ||
1372 | }; | ||
1373 | |||
1374 | struct mlx4_zone_allocator; | ||
1375 | |||
1376 | /* Create a new zone allocator */ | ||
1377 | struct mlx4_zone_allocator *mlx4_zone_allocator_create(enum mlx4_zone_alloc_flags flags); | ||
1378 | |||
1379 | /* Attach a mlx4_bitmap <bitmap> of priority <priority> to the zone allocator | ||
1380 | * <zone_alloc>. Allocating an object from this zone adds an offset <offset>. | ||
1381 | * Similarly, when searching for an object to free, this offset it taken into | ||
1382 | * account. The use_rr mlx4_ib parameter for allocating objects from this <bitmap> | ||
1383 | * is given through the MLX4_ZONE_USE_RR flag in <flags>. | ||
1384 | * When an allocation fails, <zone_alloc> tries to allocate from other zones | ||
1385 | * according to the policy set by <flags>. <puid> is the unique identifier | ||
1386 | * received to this zone. | ||
1387 | */ | ||
1388 | int mlx4_zone_add_one(struct mlx4_zone_allocator *zone_alloc, | ||
1389 | struct mlx4_bitmap *bitmap, | ||
1390 | u32 flags, | ||
1391 | int priority, | ||
1392 | int offset, | ||
1393 | u32 *puid); | ||
1394 | |||
1395 | /* Remove bitmap indicated by <uid> from <zone_alloc> */ | ||
1396 | int mlx4_zone_remove_one(struct mlx4_zone_allocator *zone_alloc, u32 uid); | ||
1397 | |||
1398 | /* Delete the zone allocator <zone_alloc. This function doesn't destroy | ||
1399 | * the attached bitmaps. | ||
1400 | */ | ||
1401 | void mlx4_zone_allocator_destroy(struct mlx4_zone_allocator *zone_alloc); | ||
1402 | |||
1403 | /* Allocate <count> objects with align <align> and skip_mask <skip_mask> | ||
1404 | * from the mlx4_bitmap whose uid is <uid>. The bitmap which we actually | ||
1405 | * allocated from is returned in <puid>. If the allocation fails, a negative | ||
1406 | * number is returned. Otherwise, the offset of the first object is returned. | ||
1407 | */ | ||
1408 | u32 mlx4_zone_alloc_entries(struct mlx4_zone_allocator *zones, u32 uid, int count, | ||
1409 | int align, u32 skip_mask, u32 *puid); | ||
1410 | |||
1411 | /* Free <count> objects, start from <obj> of the uid <uid> from zone_allocator | ||
1412 | * <zones>. | ||
1413 | */ | ||
1414 | u32 mlx4_zone_free_entries(struct mlx4_zone_allocator *zones, | ||
1415 | u32 uid, u32 obj, u32 count); | ||
1416 | |||
1417 | /* If <zones> was allocated with MLX4_ZONE_ALLOC_FLAGS_NO_OVERLAP, instead of | ||
1418 | * specifying the uid when freeing an object, zone allocator could figure it by | ||
1419 | * itself. Other parameters are similar to mlx4_zone_free. | ||
1420 | */ | ||
1421 | u32 mlx4_zone_free_entries_unique(struct mlx4_zone_allocator *zones, u32 obj, u32 count); | ||
1422 | |||
1423 | /* Returns a pointer to mlx4_bitmap that was attached to <zones> with <uid> */ | ||
1424 | struct mlx4_bitmap *mlx4_zone_get_bitmap(struct mlx4_zone_allocator *zones, u32 uid); | ||
1425 | |||
1335 | #endif /* MLX4_H */ | 1426 | #endif /* MLX4_H */ |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index ac48a8d91501..944a112dff37 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | |||
@@ -778,7 +778,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev); | |||
778 | 778 | ||
779 | int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, | 779 | int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, |
780 | struct mlx4_en_tx_ring **pring, | 780 | struct mlx4_en_tx_ring **pring, |
781 | int qpn, u32 size, u16 stride, | 781 | u32 size, u16 stride, |
782 | int node, int queue_index); | 782 | int node, int queue_index); |
783 | void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, | 783 | void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, |
784 | struct mlx4_en_tx_ring **pring); | 784 | struct mlx4_en_tx_ring **pring); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 2301365c79c7..1586ecce13c7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c | |||
@@ -42,6 +42,10 @@ | |||
42 | #include "mlx4.h" | 42 | #include "mlx4.h" |
43 | #include "icm.h" | 43 | #include "icm.h" |
44 | 44 | ||
45 | /* QP to support BF should have bits 6,7 cleared */ | ||
46 | #define MLX4_BF_QP_SKIP_MASK 0xc0 | ||
47 | #define MLX4_MAX_BF_QP_RANGE 0x40 | ||
48 | |||
45 | void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type) | 49 | void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type) |
46 | { | 50 | { |
47 | struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; | 51 | struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; |
@@ -207,26 +211,45 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, | |||
207 | EXPORT_SYMBOL_GPL(mlx4_qp_modify); | 211 | EXPORT_SYMBOL_GPL(mlx4_qp_modify); |
208 | 212 | ||
209 | int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, | 213 | int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, |
210 | int *base) | 214 | int *base, u8 flags) |
211 | { | 215 | { |
216 | u32 uid; | ||
217 | int bf_qp = !!(flags & (u8)MLX4_RESERVE_ETH_BF_QP); | ||
218 | |||
212 | struct mlx4_priv *priv = mlx4_priv(dev); | 219 | struct mlx4_priv *priv = mlx4_priv(dev); |
213 | struct mlx4_qp_table *qp_table = &priv->qp_table; | 220 | struct mlx4_qp_table *qp_table = &priv->qp_table; |
214 | 221 | ||
215 | *base = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align); | 222 | if (cnt > MLX4_MAX_BF_QP_RANGE && bf_qp) |
223 | return -ENOMEM; | ||
224 | |||
225 | uid = MLX4_QP_TABLE_ZONE_GENERAL; | ||
226 | if (flags & (u8)MLX4_RESERVE_A0_QP) { | ||
227 | if (bf_qp) | ||
228 | uid = MLX4_QP_TABLE_ZONE_RAW_ETH; | ||
229 | else | ||
230 | uid = MLX4_QP_TABLE_ZONE_RSS; | ||
231 | } | ||
232 | |||
233 | *base = mlx4_zone_alloc_entries(qp_table->zones, uid, cnt, align, | ||
234 | bf_qp ? MLX4_BF_QP_SKIP_MASK : 0, NULL); | ||
216 | if (*base == -1) | 235 | if (*base == -1) |
217 | return -ENOMEM; | 236 | return -ENOMEM; |
218 | 237 | ||
219 | return 0; | 238 | return 0; |
220 | } | 239 | } |
221 | 240 | ||
222 | int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base) | 241 | int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, |
242 | int *base, u8 flags) | ||
223 | { | 243 | { |
224 | u64 in_param = 0; | 244 | u64 in_param = 0; |
225 | u64 out_param; | 245 | u64 out_param; |
226 | int err; | 246 | int err; |
227 | 247 | ||
248 | /* Turn off all unsupported QP allocation flags */ | ||
249 | flags &= dev->caps.alloc_res_qp_mask; | ||
250 | |||
228 | if (mlx4_is_mfunc(dev)) { | 251 | if (mlx4_is_mfunc(dev)) { |
229 | set_param_l(&in_param, cnt); | 252 | set_param_l(&in_param, (((u32)flags) << 24) | (u32)cnt); |
230 | set_param_h(&in_param, align); | 253 | set_param_h(&in_param, align); |
231 | err = mlx4_cmd_imm(dev, in_param, &out_param, | 254 | err = mlx4_cmd_imm(dev, in_param, &out_param, |
232 | RES_QP, RES_OP_RESERVE, | 255 | RES_QP, RES_OP_RESERVE, |
@@ -238,7 +261,7 @@ int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base) | |||
238 | *base = get_param_l(&out_param); | 261 | *base = get_param_l(&out_param); |
239 | return 0; | 262 | return 0; |
240 | } | 263 | } |
241 | return __mlx4_qp_reserve_range(dev, cnt, align, base); | 264 | return __mlx4_qp_reserve_range(dev, cnt, align, base, flags); |
242 | } | 265 | } |
243 | EXPORT_SYMBOL_GPL(mlx4_qp_reserve_range); | 266 | EXPORT_SYMBOL_GPL(mlx4_qp_reserve_range); |
244 | 267 | ||
@@ -249,7 +272,7 @@ void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) | |||
249 | 272 | ||
250 | if (mlx4_is_qp_reserved(dev, (u32) base_qpn)) | 273 | if (mlx4_is_qp_reserved(dev, (u32) base_qpn)) |
251 | return; | 274 | return; |
252 | mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt, MLX4_USE_RR); | 275 | mlx4_zone_free_entries_unique(qp_table->zones, base_qpn, cnt); |
253 | } | 276 | } |
254 | 277 | ||
255 | void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) | 278 | void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) |
@@ -459,28 +482,261 @@ static int mlx4_CONF_SPECIAL_QP(struct mlx4_dev *dev, u32 base_qpn) | |||
459 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); | 482 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); |
460 | } | 483 | } |
461 | 484 | ||
485 | #define MLX4_QP_TABLE_RSS_ETH_PRIORITY 2 | ||
486 | #define MLX4_QP_TABLE_RAW_ETH_PRIORITY 1 | ||
487 | #define MLX4_QP_TABLE_RAW_ETH_SIZE 256 | ||
488 | |||
489 | static int mlx4_create_zones(struct mlx4_dev *dev, | ||
490 | u32 reserved_bottom_general, | ||
491 | u32 reserved_top_general, | ||
492 | u32 reserved_bottom_rss, | ||
493 | u32 start_offset_rss, | ||
494 | u32 max_table_offset) | ||
495 | { | ||
496 | struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; | ||
497 | struct mlx4_bitmap (*bitmap)[MLX4_QP_TABLE_ZONE_NUM] = NULL; | ||
498 | int bitmap_initialized = 0; | ||
499 | u32 last_offset; | ||
500 | int k; | ||
501 | int err; | ||
502 | |||
503 | qp_table->zones = mlx4_zone_allocator_create(MLX4_ZONE_ALLOC_FLAGS_NO_OVERLAP); | ||
504 | |||
505 | if (NULL == qp_table->zones) | ||
506 | return -ENOMEM; | ||
507 | |||
508 | bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL); | ||
509 | |||
510 | if (NULL == bitmap) { | ||
511 | err = -ENOMEM; | ||
512 | goto free_zone; | ||
513 | } | ||
514 | |||
515 | err = mlx4_bitmap_init(*bitmap + MLX4_QP_TABLE_ZONE_GENERAL, dev->caps.num_qps, | ||
516 | (1 << 23) - 1, reserved_bottom_general, | ||
517 | reserved_top_general); | ||
518 | |||
519 | if (err) | ||
520 | goto free_bitmap; | ||
521 | |||
522 | ++bitmap_initialized; | ||
523 | |||
524 | err = mlx4_zone_add_one(qp_table->zones, *bitmap + MLX4_QP_TABLE_ZONE_GENERAL, | ||
525 | MLX4_ZONE_FALLBACK_TO_HIGHER_PRIO | | ||
526 | MLX4_ZONE_USE_RR, 0, | ||
527 | 0, qp_table->zones_uids + MLX4_QP_TABLE_ZONE_GENERAL); | ||
528 | |||
529 | if (err) | ||
530 | goto free_bitmap; | ||
531 | |||
532 | err = mlx4_bitmap_init(*bitmap + MLX4_QP_TABLE_ZONE_RSS, | ||
533 | reserved_bottom_rss, | ||
534 | reserved_bottom_rss - 1, | ||
535 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], | ||
536 | reserved_bottom_rss - start_offset_rss); | ||
537 | |||
538 | if (err) | ||
539 | goto free_bitmap; | ||
540 | |||
541 | ++bitmap_initialized; | ||
542 | |||
543 | err = mlx4_zone_add_one(qp_table->zones, *bitmap + MLX4_QP_TABLE_ZONE_RSS, | ||
544 | MLX4_ZONE_ALLOW_ALLOC_FROM_LOWER_PRIO | | ||
545 | MLX4_ZONE_ALLOW_ALLOC_FROM_EQ_PRIO | | ||
546 | MLX4_ZONE_USE_RR, MLX4_QP_TABLE_RSS_ETH_PRIORITY, | ||
547 | 0, qp_table->zones_uids + MLX4_QP_TABLE_ZONE_RSS); | ||
548 | |||
549 | if (err) | ||
550 | goto free_bitmap; | ||
551 | |||
552 | last_offset = dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW]; | ||
553 | /* We have a single zone for the A0 steering QPs area of the FW. This area | ||
554 | * needs to be split into subareas. One set of subareas is for RSS QPs | ||
555 | * (in which qp number bits 6 and/or 7 are set); the other set of subareas | ||
556 | * is for RAW_ETH QPs, which require that both bits 6 and 7 are zero. | ||
557 | * Currently, the values returned by the FW (A0 steering area starting qp number | ||
558 | * and A0 steering area size) are such that there are only two subareas -- one | ||
559 | * for RSS and one for RAW_ETH. | ||
560 | */ | ||
561 | for (k = MLX4_QP_TABLE_ZONE_RSS + 1; k < sizeof(*bitmap)/sizeof((*bitmap)[0]); | ||
562 | k++) { | ||
563 | int size; | ||
564 | u32 offset = start_offset_rss; | ||
565 | u32 bf_mask; | ||
566 | u32 requested_size; | ||
567 | |||
568 | /* Assuming MLX4_BF_QP_SKIP_MASK is consecutive ones, this calculates | ||
569 | * a mask of all LSB bits set until (and not including) the first | ||
570 | * set bit of MLX4_BF_QP_SKIP_MASK. For example, if MLX4_BF_QP_SKIP_MASK | ||
571 | * is 0xc0, bf_mask will be 0x3f. | ||
572 | */ | ||
573 | bf_mask = (MLX4_BF_QP_SKIP_MASK & ~(MLX4_BF_QP_SKIP_MASK - 1)) - 1; | ||
574 | requested_size = min((u32)MLX4_QP_TABLE_RAW_ETH_SIZE, bf_mask + 1); | ||
575 | |||
576 | if (((last_offset & MLX4_BF_QP_SKIP_MASK) && | ||
577 | ((int)(max_table_offset - last_offset)) >= | ||
578 | roundup_pow_of_two(MLX4_BF_QP_SKIP_MASK)) || | ||
579 | (!(last_offset & MLX4_BF_QP_SKIP_MASK) && | ||
580 | !((last_offset + requested_size - 1) & | ||
581 | MLX4_BF_QP_SKIP_MASK))) | ||
582 | size = requested_size; | ||
583 | else { | ||
584 | u32 candidate_offset = | ||
585 | (last_offset | MLX4_BF_QP_SKIP_MASK | bf_mask) + 1; | ||
586 | |||
587 | if (last_offset & MLX4_BF_QP_SKIP_MASK) | ||
588 | last_offset = candidate_offset; | ||
589 | |||
590 | /* From this point, the BF bits are 0 */ | ||
591 | |||
592 | if (last_offset > max_table_offset) { | ||
593 | /* need to skip */ | ||
594 | size = -1; | ||
595 | } else { | ||
596 | size = min3(max_table_offset - last_offset, | ||
597 | bf_mask - (last_offset & bf_mask), | ||
598 | requested_size); | ||
599 | if (size < requested_size) { | ||
600 | int candidate_size; | ||
601 | |||
602 | candidate_size = min3( | ||
603 | max_table_offset - candidate_offset, | ||
604 | bf_mask - (last_offset & bf_mask), | ||
605 | requested_size); | ||
606 | |||
607 | /* We will not take this path if last_offset was | ||
608 | * already set above to candidate_offset | ||
609 | */ | ||
610 | if (candidate_size > size) { | ||
611 | last_offset = candidate_offset; | ||
612 | size = candidate_size; | ||
613 | } | ||
614 | } | ||
615 | } | ||
616 | } | ||
617 | |||
618 | if (size > 0) { | ||
619 | /* mlx4_bitmap_alloc_range will find a contiguous range of "size" | ||
620 | * QPs in which both bits 6 and 7 are zero, because we pass it the | ||
621 | * MLX4_BF_SKIP_MASK). | ||
622 | */ | ||
623 | offset = mlx4_bitmap_alloc_range( | ||
624 | *bitmap + MLX4_QP_TABLE_ZONE_RSS, | ||
625 | size, 1, | ||
626 | MLX4_BF_QP_SKIP_MASK); | ||
627 | |||
628 | if (offset == (u32)-1) { | ||
629 | err = -ENOMEM; | ||
630 | break; | ||
631 | } | ||
632 | |||
633 | last_offset = offset + size; | ||
634 | |||
635 | err = mlx4_bitmap_init(*bitmap + k, roundup_pow_of_two(size), | ||
636 | roundup_pow_of_two(size) - 1, 0, | ||
637 | roundup_pow_of_two(size) - size); | ||
638 | } else { | ||
639 | /* Add an empty bitmap, we'll allocate from different zones (since | ||
640 | * at least one is reserved) | ||
641 | */ | ||
642 | err = mlx4_bitmap_init(*bitmap + k, 1, | ||
643 | MLX4_QP_TABLE_RAW_ETH_SIZE - 1, 0, | ||
644 | 0); | ||
645 | mlx4_bitmap_alloc_range(*bitmap + k, 1, 1, 0); | ||
646 | } | ||
647 | |||
648 | if (err) | ||
649 | break; | ||
650 | |||
651 | ++bitmap_initialized; | ||
652 | |||
653 | err = mlx4_zone_add_one(qp_table->zones, *bitmap + k, | ||
654 | MLX4_ZONE_ALLOW_ALLOC_FROM_LOWER_PRIO | | ||
655 | MLX4_ZONE_ALLOW_ALLOC_FROM_EQ_PRIO | | ||
656 | MLX4_ZONE_USE_RR, MLX4_QP_TABLE_RAW_ETH_PRIORITY, | ||
657 | offset, qp_table->zones_uids + k); | ||
658 | |||
659 | if (err) | ||
660 | break; | ||
661 | } | ||
662 | |||
663 | if (err) | ||
664 | goto free_bitmap; | ||
665 | |||
666 | qp_table->bitmap_gen = *bitmap; | ||
667 | |||
668 | return err; | ||
669 | |||
670 | free_bitmap: | ||
671 | for (k = 0; k < bitmap_initialized; k++) | ||
672 | mlx4_bitmap_cleanup(*bitmap + k); | ||
673 | kfree(bitmap); | ||
674 | free_zone: | ||
675 | mlx4_zone_allocator_destroy(qp_table->zones); | ||
676 | return err; | ||
677 | } | ||
678 | |||
679 | static void mlx4_cleanup_qp_zones(struct mlx4_dev *dev) | ||
680 | { | ||
681 | struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; | ||
682 | |||
683 | if (qp_table->zones) { | ||
684 | int i; | ||
685 | |||
686 | for (i = 0; | ||
687 | i < sizeof(qp_table->zones_uids)/sizeof(qp_table->zones_uids[0]); | ||
688 | i++) { | ||
689 | struct mlx4_bitmap *bitmap = | ||
690 | mlx4_zone_get_bitmap(qp_table->zones, | ||
691 | qp_table->zones_uids[i]); | ||
692 | |||
693 | mlx4_zone_remove_one(qp_table->zones, qp_table->zones_uids[i]); | ||
694 | if (NULL == bitmap) | ||
695 | continue; | ||
696 | |||
697 | mlx4_bitmap_cleanup(bitmap); | ||
698 | } | ||
699 | mlx4_zone_allocator_destroy(qp_table->zones); | ||
700 | kfree(qp_table->bitmap_gen); | ||
701 | qp_table->bitmap_gen = NULL; | ||
702 | qp_table->zones = NULL; | ||
703 | } | ||
704 | } | ||
705 | |||
462 | int mlx4_init_qp_table(struct mlx4_dev *dev) | 706 | int mlx4_init_qp_table(struct mlx4_dev *dev) |
463 | { | 707 | { |
464 | struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; | 708 | struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; |
465 | int err; | 709 | int err; |
466 | int reserved_from_top = 0; | 710 | int reserved_from_top = 0; |
711 | int reserved_from_bot; | ||
467 | int k; | 712 | int k; |
713 | int fixed_reserved_from_bot_rv = 0; | ||
714 | int bottom_reserved_for_rss_bitmap; | ||
715 | u32 max_table_offset = dev->caps.dmfs_high_rate_qpn_base + | ||
716 | dev->caps.dmfs_high_rate_qpn_range; | ||
468 | 717 | ||
469 | spin_lock_init(&qp_table->lock); | 718 | spin_lock_init(&qp_table->lock); |
470 | INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC); | 719 | INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC); |
471 | if (mlx4_is_slave(dev)) | 720 | if (mlx4_is_slave(dev)) |
472 | return 0; | 721 | return 0; |
473 | 722 | ||
474 | /* | 723 | /* We reserve 2 extra QPs per port for the special QPs. The |
475 | * We reserve 2 extra QPs per port for the special QPs. The | ||
476 | * block of special QPs must be aligned to a multiple of 8, so | 724 | * block of special QPs must be aligned to a multiple of 8, so |
477 | * round up. | 725 | * round up. |
478 | * | 726 | * |
479 | * We also reserve the MSB of the 24-bit QP number to indicate | 727 | * We also reserve the MSB of the 24-bit QP number to indicate |
480 | * that a QP is an XRC QP. | 728 | * that a QP is an XRC QP. |
481 | */ | 729 | */ |
482 | dev->phys_caps.base_sqpn = | 730 | for (k = 0; k <= MLX4_QP_REGION_BOTTOM; k++) |
483 | ALIGN(dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], 8); | 731 | fixed_reserved_from_bot_rv += dev->caps.reserved_qps_cnt[k]; |
732 | |||
733 | if (fixed_reserved_from_bot_rv < max_table_offset) | ||
734 | fixed_reserved_from_bot_rv = max_table_offset; | ||
735 | |||
736 | /* We reserve at least 1 extra for bitmaps that we don't have enough space for*/ | ||
737 | bottom_reserved_for_rss_bitmap = | ||
738 | roundup_pow_of_two(fixed_reserved_from_bot_rv + 1); | ||
739 | dev->phys_caps.base_sqpn = ALIGN(bottom_reserved_for_rss_bitmap, 8); | ||
484 | 740 | ||
485 | { | 741 | { |
486 | int sort[MLX4_NUM_QP_REGION]; | 742 | int sort[MLX4_NUM_QP_REGION]; |
@@ -490,8 +746,8 @@ int mlx4_init_qp_table(struct mlx4_dev *dev) | |||
490 | for (i = 1; i < MLX4_NUM_QP_REGION; ++i) | 746 | for (i = 1; i < MLX4_NUM_QP_REGION; ++i) |
491 | sort[i] = i; | 747 | sort[i] = i; |
492 | 748 | ||
493 | for (i = MLX4_NUM_QP_REGION; i > 0; --i) { | 749 | for (i = MLX4_NUM_QP_REGION; i > MLX4_QP_REGION_BOTTOM; --i) { |
494 | for (j = 2; j < i; ++j) { | 750 | for (j = MLX4_QP_REGION_BOTTOM + 2; j < i; ++j) { |
495 | if (dev->caps.reserved_qps_cnt[sort[j]] > | 751 | if (dev->caps.reserved_qps_cnt[sort[j]] > |
496 | dev->caps.reserved_qps_cnt[sort[j - 1]]) { | 752 | dev->caps.reserved_qps_cnt[sort[j - 1]]) { |
497 | tmp = sort[j]; | 753 | tmp = sort[j]; |
@@ -501,13 +757,12 @@ int mlx4_init_qp_table(struct mlx4_dev *dev) | |||
501 | } | 757 | } |
502 | } | 758 | } |
503 | 759 | ||
504 | for (i = 1; i < MLX4_NUM_QP_REGION; ++i) { | 760 | for (i = MLX4_QP_REGION_BOTTOM + 1; i < MLX4_NUM_QP_REGION; ++i) { |
505 | last_base -= dev->caps.reserved_qps_cnt[sort[i]]; | 761 | last_base -= dev->caps.reserved_qps_cnt[sort[i]]; |
506 | dev->caps.reserved_qps_base[sort[i]] = last_base; | 762 | dev->caps.reserved_qps_base[sort[i]] = last_base; |
507 | reserved_from_top += | 763 | reserved_from_top += |
508 | dev->caps.reserved_qps_cnt[sort[i]]; | 764 | dev->caps.reserved_qps_cnt[sort[i]]; |
509 | } | 765 | } |
510 | |||
511 | } | 766 | } |
512 | 767 | ||
513 | /* Reserve 8 real SQPs in both native and SRIOV modes. | 768 | /* Reserve 8 real SQPs in both native and SRIOV modes. |
@@ -520,10 +775,17 @@ int mlx4_init_qp_table(struct mlx4_dev *dev) | |||
520 | * b. All the proxy SQPs (8 per function) | 775 | * b. All the proxy SQPs (8 per function) |
521 | * c. All the tunnel QPs (8 per function) | 776 | * c. All the tunnel QPs (8 per function) |
522 | */ | 777 | */ |
778 | reserved_from_bot = mlx4_num_reserved_sqps(dev); | ||
779 | if (reserved_from_bot + reserved_from_top > dev->caps.num_qps) { | ||
780 | mlx4_err(dev, "Number of reserved QPs is higher than number of QPs\n"); | ||
781 | return -EINVAL; | ||
782 | } | ||
783 | |||
784 | err = mlx4_create_zones(dev, reserved_from_bot, reserved_from_bot, | ||
785 | bottom_reserved_for_rss_bitmap, | ||
786 | fixed_reserved_from_bot_rv, | ||
787 | max_table_offset); | ||
523 | 788 | ||
524 | err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps, | ||
525 | (1 << 23) - 1, mlx4_num_reserved_sqps(dev), | ||
526 | reserved_from_top); | ||
527 | if (err) | 789 | if (err) |
528 | return err; | 790 | return err; |
529 | 791 | ||
@@ -559,7 +821,8 @@ int mlx4_init_qp_table(struct mlx4_dev *dev) | |||
559 | err = mlx4_CONF_SPECIAL_QP(dev, dev->phys_caps.base_sqpn); | 821 | err = mlx4_CONF_SPECIAL_QP(dev, dev->phys_caps.base_sqpn); |
560 | if (err) | 822 | if (err) |
561 | goto err_mem; | 823 | goto err_mem; |
562 | return 0; | 824 | |
825 | return err; | ||
563 | 826 | ||
564 | err_mem: | 827 | err_mem: |
565 | kfree(dev->caps.qp0_tunnel); | 828 | kfree(dev->caps.qp0_tunnel); |
@@ -568,6 +831,7 @@ err_mem: | |||
568 | kfree(dev->caps.qp1_proxy); | 831 | kfree(dev->caps.qp1_proxy); |
569 | dev->caps.qp0_tunnel = dev->caps.qp0_proxy = | 832 | dev->caps.qp0_tunnel = dev->caps.qp0_proxy = |
570 | dev->caps.qp1_tunnel = dev->caps.qp1_proxy = NULL; | 833 | dev->caps.qp1_tunnel = dev->caps.qp1_proxy = NULL; |
834 | mlx4_cleanup_qp_zones(dev); | ||
571 | return err; | 835 | return err; |
572 | } | 836 | } |
573 | 837 | ||
@@ -577,7 +841,8 @@ void mlx4_cleanup_qp_table(struct mlx4_dev *dev) | |||
577 | return; | 841 | return; |
578 | 842 | ||
579 | mlx4_CONF_SPECIAL_QP(dev, 0); | 843 | mlx4_CONF_SPECIAL_QP(dev, 0); |
580 | mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap); | 844 | |
845 | mlx4_cleanup_qp_zones(dev); | ||
581 | } | 846 | } |
582 | 847 | ||
583 | int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp, | 848 | int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp, |
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 16f617b5749e..4efbd1eca611 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
@@ -1543,16 +1543,21 @@ static int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, | |||
1543 | int align; | 1543 | int align; |
1544 | int base; | 1544 | int base; |
1545 | int qpn; | 1545 | int qpn; |
1546 | u8 flags; | ||
1546 | 1547 | ||
1547 | switch (op) { | 1548 | switch (op) { |
1548 | case RES_OP_RESERVE: | 1549 | case RES_OP_RESERVE: |
1549 | count = get_param_l(&in_param) & 0xffffff; | 1550 | count = get_param_l(&in_param) & 0xffffff; |
1551 | /* Turn off all unsupported QP allocation flags that the | ||
1552 | * slave tries to set. | ||
1553 | */ | ||
1554 | flags = (get_param_l(&in_param) >> 24) & dev->caps.alloc_res_qp_mask; | ||
1550 | align = get_param_h(&in_param); | 1555 | align = get_param_h(&in_param); |
1551 | err = mlx4_grant_resource(dev, slave, RES_QP, count, 0); | 1556 | err = mlx4_grant_resource(dev, slave, RES_QP, count, 0); |
1552 | if (err) | 1557 | if (err) |
1553 | return err; | 1558 | return err; |
1554 | 1559 | ||
1555 | err = __mlx4_qp_reserve_range(dev, count, align, &base); | 1560 | err = __mlx4_qp_reserve_range(dev, count, align, &base, flags); |
1556 | if (err) { | 1561 | if (err) { |
1557 | mlx4_release_resource(dev, slave, RES_QP, count, 0); | 1562 | mlx4_release_resource(dev, slave, RES_QP, count, 0); |
1558 | return err; | 1563 | return err; |
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index cf09e65c2901..25c791e295fd 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h | |||
@@ -117,6 +117,14 @@ enum { | |||
117 | MLX4_STEERING_MODE_DEVICE_MANAGED | 117 | MLX4_STEERING_MODE_DEVICE_MANAGED |
118 | }; | 118 | }; |
119 | 119 | ||
120 | enum { | ||
121 | MLX4_STEERING_DMFS_A0_DEFAULT, | ||
122 | MLX4_STEERING_DMFS_A0_DYNAMIC, | ||
123 | MLX4_STEERING_DMFS_A0_STATIC, | ||
124 | MLX4_STEERING_DMFS_A0_DISABLE, | ||
125 | MLX4_STEERING_DMFS_A0_NOT_SUPPORTED | ||
126 | }; | ||
127 | |||
120 | static inline const char *mlx4_steering_mode_str(int steering_mode) | 128 | static inline const char *mlx4_steering_mode_str(int steering_mode) |
121 | { | 129 | { |
122 | switch (steering_mode) { | 130 | switch (steering_mode) { |
@@ -191,7 +199,26 @@ enum { | |||
191 | MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP = 1LL << 15, | 199 | MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP = 1LL << 15, |
192 | MLX4_DEV_CAP_FLAG2_CONFIG_DEV = 1LL << 16, | 200 | MLX4_DEV_CAP_FLAG2_CONFIG_DEV = 1LL << 16, |
193 | MLX4_DEV_CAP_FLAG2_SYS_EQS = 1LL << 17, | 201 | MLX4_DEV_CAP_FLAG2_SYS_EQS = 1LL << 17, |
194 | MLX4_DEV_CAP_FLAG2_80_VFS = 1LL << 18 | 202 | MLX4_DEV_CAP_FLAG2_80_VFS = 1LL << 18, |
203 | MLX4_DEV_CAP_FLAG2_FS_A0 = 1LL << 19 | ||
204 | }; | ||
205 | |||
206 | enum { | ||
207 | MLX4_QUERY_FUNC_FLAGS_BF_RES_QP = 1LL << 0, | ||
208 | MLX4_QUERY_FUNC_FLAGS_A0_RES_QP = 1LL << 1 | ||
209 | }; | ||
210 | |||
211 | /* bit enums for an 8-bit flags field indicating special use | ||
212 | * QPs which require special handling in qp_reserve_range. | ||
213 | * Currently, this only includes QPs used by the ETH interface, | ||
214 | * where we expect to use blueflame. These QPs must not have | ||
215 | * bits 6 and 7 set in their qp number. | ||
216 | * | ||
217 | * This enum may use only bits 0..7. | ||
218 | */ | ||
219 | enum { | ||
220 | MLX4_RESERVE_A0_QP = 1 << 6, | ||
221 | MLX4_RESERVE_ETH_BF_QP = 1 << 7, | ||
195 | }; | 222 | }; |
196 | 223 | ||
197 | enum { | 224 | enum { |
@@ -207,7 +234,8 @@ enum { | |||
207 | 234 | ||
208 | enum { | 235 | enum { |
209 | MLX4_FUNC_CAP_64B_EQE_CQE = 1L << 0, | 236 | MLX4_FUNC_CAP_64B_EQE_CQE = 1L << 0, |
210 | MLX4_FUNC_CAP_EQE_CQE_STRIDE = 1L << 1 | 237 | MLX4_FUNC_CAP_EQE_CQE_STRIDE = 1L << 1, |
238 | MLX4_FUNC_CAP_DMFS_A0_STATIC = 1L << 2 | ||
211 | }; | 239 | }; |
212 | 240 | ||
213 | 241 | ||
@@ -333,6 +361,8 @@ enum { | |||
333 | 361 | ||
334 | enum mlx4_qp_region { | 362 | enum mlx4_qp_region { |
335 | MLX4_QP_REGION_FW = 0, | 363 | MLX4_QP_REGION_FW = 0, |
364 | MLX4_QP_REGION_RSS_RAW_ETH, | ||
365 | MLX4_QP_REGION_BOTTOM = MLX4_QP_REGION_RSS_RAW_ETH, | ||
336 | MLX4_QP_REGION_ETH_ADDR, | 366 | MLX4_QP_REGION_ETH_ADDR, |
337 | MLX4_QP_REGION_FC_ADDR, | 367 | MLX4_QP_REGION_FC_ADDR, |
338 | MLX4_QP_REGION_FC_EXCH, | 368 | MLX4_QP_REGION_FC_EXCH, |
@@ -462,6 +492,7 @@ struct mlx4_caps { | |||
462 | int reserved_mcgs; | 492 | int reserved_mcgs; |
463 | int num_qp_per_mgm; | 493 | int num_qp_per_mgm; |
464 | int steering_mode; | 494 | int steering_mode; |
495 | int dmfs_high_steer_mode; | ||
465 | int fs_log_max_ucast_qp_range_size; | 496 | int fs_log_max_ucast_qp_range_size; |
466 | int num_pds; | 497 | int num_pds; |
467 | int reserved_pds; | 498 | int reserved_pds; |
@@ -501,6 +532,9 @@ struct mlx4_caps { | |||
501 | u64 phys_port_id[MLX4_MAX_PORTS + 1]; | 532 | u64 phys_port_id[MLX4_MAX_PORTS + 1]; |
502 | int tunnel_offload_mode; | 533 | int tunnel_offload_mode; |
503 | u8 rx_checksum_flags_port[MLX4_MAX_PORTS + 1]; | 534 | u8 rx_checksum_flags_port[MLX4_MAX_PORTS + 1]; |
535 | u8 alloc_res_qp_mask; | ||
536 | u32 dmfs_high_rate_qpn_base; | ||
537 | u32 dmfs_high_rate_qpn_range; | ||
504 | }; | 538 | }; |
505 | 539 | ||
506 | struct mlx4_buf_list { | 540 | struct mlx4_buf_list { |
@@ -621,6 +655,11 @@ struct mlx4_cq { | |||
621 | 655 | ||
622 | atomic_t refcount; | 656 | atomic_t refcount; |
623 | struct completion free; | 657 | struct completion free; |
658 | struct { | ||
659 | struct list_head list; | ||
660 | void (*comp)(struct mlx4_cq *); | ||
661 | void *priv; | ||
662 | } tasklet_ctx; | ||
624 | }; | 663 | }; |
625 | 664 | ||
626 | struct mlx4_qp { | 665 | struct mlx4_qp { |
@@ -869,7 +908,9 @@ static inline int mlx4_num_reserved_sqps(struct mlx4_dev *dev) | |||
869 | static inline int mlx4_is_qp_reserved(struct mlx4_dev *dev, u32 qpn) | 908 | static inline int mlx4_is_qp_reserved(struct mlx4_dev *dev, u32 qpn) |
870 | { | 909 | { |
871 | return (qpn < dev->phys_caps.base_sqpn + 8 + | 910 | return (qpn < dev->phys_caps.base_sqpn + 8 + |
872 | 16 * MLX4_MFUNC_MAX * !!mlx4_is_master(dev)); | 911 | 16 * MLX4_MFUNC_MAX * !!mlx4_is_master(dev) && |
912 | qpn >= dev->phys_caps.base_sqpn) || | ||
913 | (qpn < dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW]); | ||
873 | } | 914 | } |
874 | 915 | ||
875 | static inline int mlx4_is_guest_proxy(struct mlx4_dev *dev, int slave, u32 qpn) | 916 | static inline int mlx4_is_guest_proxy(struct mlx4_dev *dev, int slave, u32 qpn) |
@@ -945,8 +986,8 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt, | |||
945 | struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq, | 986 | struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq, |
946 | unsigned vector, int collapsed, int timestamp_en); | 987 | unsigned vector, int collapsed, int timestamp_en); |
947 | void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq); | 988 | void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq); |
948 | 989 | int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, | |
949 | int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base); | 990 | int *base, u8 flags); |
950 | void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt); | 991 | void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt); |
951 | 992 | ||
952 | int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp, | 993 | int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp, |