aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/core/cache.c')
-rw-r--r--drivers/infiniband/core/cache.c112
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
412int ib_cache_gid_find_by_port(struct ib_device *ib_dev, 412int 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}
441EXPORT_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 */
463static 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
503next:
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
442static struct ib_gid_table *alloc_gid_table(int sz) 518static 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)
649int ib_get_cached_gid(struct ib_device *device, 725int 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}
659EXPORT_SYMBOL(ib_get_cached_gid); 736EXPORT_SYMBOL(ib_get_cached_gid);
660 737
661int ib_find_cached_gid(struct ib_device *device, 738int 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}
668EXPORT_SYMBOL(ib_find_cached_gid); 746EXPORT_SYMBOL(ib_find_cached_gid);
669 747
748int 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}
764EXPORT_SYMBOL(ib_find_gid_by_filter);
765
670int ib_get_cached_pkey(struct ib_device *device, 766int 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);