diff options
Diffstat (limited to 'drivers/infiniband/core/cache.c')
-rw-r--r-- | drivers/infiniband/core/cache.c | 112 |
1 files changed, 104 insertions, 8 deletions
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 87471ef37198..89bebeada38b 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c | |||
@@ -409,10 +409,10 @@ static int ib_cache_gid_find(struct ib_device *ib_dev, | |||
409 | mask, port, index); | 409 | mask, port, index); |
410 | } | 410 | } |
411 | 411 | ||
412 | int ib_cache_gid_find_by_port(struct ib_device *ib_dev, | 412 | int ib_find_cached_gid_by_port(struct ib_device *ib_dev, |
413 | const union ib_gid *gid, | 413 | const union ib_gid *gid, |
414 | u8 port, struct net_device *ndev, | 414 | u8 port, struct net_device *ndev, |
415 | u16 *index) | 415 | u16 *index) |
416 | { | 416 | { |
417 | int local_index; | 417 | int local_index; |
418 | struct ib_gid_table **ports_table = ib_dev->cache.gid_cache; | 418 | struct ib_gid_table **ports_table = ib_dev->cache.gid_cache; |
@@ -438,6 +438,82 @@ int ib_cache_gid_find_by_port(struct ib_device *ib_dev, | |||
438 | 438 | ||
439 | return -ENOENT; | 439 | return -ENOENT; |
440 | } | 440 | } |
441 | EXPORT_SYMBOL(ib_find_cached_gid_by_port); | ||
442 | |||
443 | /** | ||
444 | * ib_find_gid_by_filter - Returns the GID table index where a specified | ||
445 | * GID value occurs | ||
446 | * @device: The device to query. | ||
447 | * @gid: The GID value to search for. | ||
448 | * @port_num: The port number of the device where the GID value could be | ||
449 | * searched. | ||
450 | * @filter: The filter function is executed on any matching GID in the table. | ||
451 | * If the filter function returns true, the corresponding index is returned, | ||
452 | * otherwise, we continue searching the GID table. It's guaranteed that | ||
453 | * while filter is executed, ndev field is valid and the structure won't | ||
454 | * change. filter is executed in an atomic context. filter must not be NULL. | ||
455 | * @index: The index into the cached GID table where the GID was found. This | ||
456 | * parameter may be NULL. | ||
457 | * | ||
458 | * ib_cache_gid_find_by_filter() searches for the specified GID value | ||
459 | * of which the filter function returns true in the port's GID table. | ||
460 | * This function is only supported on RoCE ports. | ||
461 | * | ||
462 | */ | ||
463 | static int ib_cache_gid_find_by_filter(struct ib_device *ib_dev, | ||
464 | const union ib_gid *gid, | ||
465 | u8 port, | ||
466 | bool (*filter)(const union ib_gid *, | ||
467 | const struct ib_gid_attr *, | ||
468 | void *), | ||
469 | void *context, | ||
470 | u16 *index) | ||
471 | { | ||
472 | struct ib_gid_table **ports_table = ib_dev->cache.gid_cache; | ||
473 | struct ib_gid_table *table; | ||
474 | unsigned int i; | ||
475 | bool found = false; | ||
476 | |||
477 | if (!ports_table) | ||
478 | return -EOPNOTSUPP; | ||
479 | |||
480 | if (port < rdma_start_port(ib_dev) || | ||
481 | port > rdma_end_port(ib_dev) || | ||
482 | !rdma_protocol_roce(ib_dev, port)) | ||
483 | return -EPROTONOSUPPORT; | ||
484 | |||
485 | table = ports_table[port - rdma_start_port(ib_dev)]; | ||
486 | |||
487 | for (i = 0; i < table->sz; i++) { | ||
488 | struct ib_gid_attr attr; | ||
489 | unsigned long flags; | ||
490 | |||
491 | read_lock_irqsave(&table->data_vec[i].lock, flags); | ||
492 | if (table->data_vec[i].props & GID_TABLE_ENTRY_INVALID) | ||
493 | goto next; | ||
494 | |||
495 | if (memcmp(gid, &table->data_vec[i].gid, sizeof(*gid))) | ||
496 | goto next; | ||
497 | |||
498 | memcpy(&attr, &table->data_vec[i].attr, sizeof(attr)); | ||
499 | |||
500 | if (filter(gid, &attr, context)) | ||
501 | found = true; | ||
502 | |||
503 | next: | ||
504 | read_unlock_irqrestore(&table->data_vec[i].lock, flags); | ||
505 | |||
506 | if (found) | ||
507 | break; | ||
508 | } | ||
509 | |||
510 | if (!found) | ||
511 | return -ENOENT; | ||
512 | |||
513 | if (index) | ||
514 | *index = i; | ||
515 | return 0; | ||
516 | } | ||
441 | 517 | ||
442 | static struct ib_gid_table *alloc_gid_table(int sz) | 518 | static struct ib_gid_table *alloc_gid_table(int sz) |
443 | { | 519 | { |
@@ -649,24 +725,44 @@ static int gid_table_setup_one(struct ib_device *ib_dev) | |||
649 | int ib_get_cached_gid(struct ib_device *device, | 725 | int ib_get_cached_gid(struct ib_device *device, |
650 | u8 port_num, | 726 | u8 port_num, |
651 | int index, | 727 | int index, |
652 | union ib_gid *gid) | 728 | union ib_gid *gid, |
729 | struct ib_gid_attr *gid_attr) | ||
653 | { | 730 | { |
654 | if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device)) | 731 | if (port_num < rdma_start_port(device) || port_num > rdma_end_port(device)) |
655 | return -EINVAL; | 732 | return -EINVAL; |
656 | 733 | ||
657 | return __ib_cache_gid_get(device, port_num, index, gid, NULL); | 734 | return __ib_cache_gid_get(device, port_num, index, gid, gid_attr); |
658 | } | 735 | } |
659 | EXPORT_SYMBOL(ib_get_cached_gid); | 736 | EXPORT_SYMBOL(ib_get_cached_gid); |
660 | 737 | ||
661 | int ib_find_cached_gid(struct ib_device *device, | 738 | int ib_find_cached_gid(struct ib_device *device, |
662 | const union ib_gid *gid, | 739 | const union ib_gid *gid, |
740 | struct net_device *ndev, | ||
663 | u8 *port_num, | 741 | u8 *port_num, |
664 | u16 *index) | 742 | u16 *index) |
665 | { | 743 | { |
666 | return ib_cache_gid_find(device, gid, NULL, port_num, index); | 744 | return ib_cache_gid_find(device, gid, ndev, port_num, index); |
667 | } | 745 | } |
668 | EXPORT_SYMBOL(ib_find_cached_gid); | 746 | EXPORT_SYMBOL(ib_find_cached_gid); |
669 | 747 | ||
748 | int ib_find_gid_by_filter(struct ib_device *device, | ||
749 | const union ib_gid *gid, | ||
750 | u8 port_num, | ||
751 | bool (*filter)(const union ib_gid *gid, | ||
752 | const struct ib_gid_attr *, | ||
753 | void *), | ||
754 | void *context, u16 *index) | ||
755 | { | ||
756 | /* Only RoCE GID table supports filter function */ | ||
757 | if (!rdma_cap_roce_gid_table(device, port_num) && filter) | ||
758 | return -EPROTONOSUPPORT; | ||
759 | |||
760 | return ib_cache_gid_find_by_filter(device, gid, | ||
761 | port_num, filter, | ||
762 | context, index); | ||
763 | } | ||
764 | EXPORT_SYMBOL(ib_find_gid_by_filter); | ||
765 | |||
670 | int ib_get_cached_pkey(struct ib_device *device, | 766 | int ib_get_cached_pkey(struct ib_device *device, |
671 | u8 port_num, | 767 | u8 port_num, |
672 | int index, | 768 | int index, |
@@ -845,7 +941,7 @@ static void ib_cache_update(struct ib_device *device, | |||
845 | if (!use_roce_gid_table) { | 941 | if (!use_roce_gid_table) { |
846 | for (i = 0; i < gid_cache->table_len; ++i) { | 942 | for (i = 0; i < gid_cache->table_len; ++i) { |
847 | ret = ib_query_gid(device, port, i, | 943 | ret = ib_query_gid(device, port, i, |
848 | gid_cache->table + i); | 944 | gid_cache->table + i, NULL); |
849 | if (ret) { | 945 | if (ret) { |
850 | printk(KERN_WARNING "ib_query_gid failed (%d) for %s (index %d)\n", | 946 | printk(KERN_WARNING "ib_query_gid failed (%d) for %s (index %d)\n", |
851 | ret, device->name, i); | 947 | ret, device->name, i); |