When a port uses roce_gid_table, the following function
(a) ib_find_cached_gid
(b) ib_get_cached_gid

should query the gid table accordingly.

In order to query it, roce_gid_table is initialized
when needed.

Signed-off-by: Matan Barak <[email protected]>
---
 drivers/infiniband/core/cache.c  | 210 +++++++++++++++++++++++++++++----------
 drivers/infiniband/core/device.c |  17 +++-
 include/rdma/ib_verbs.h          |  21 +++-
 3 files changed, 193 insertions(+), 55 deletions(-)

diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 871da83..217e639 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -58,64 +58,133 @@ struct ib_update_work {
        u8                 port_num;
 };
 
-int ib_get_cached_gid(struct ib_device *device,
-                     u8                port_num,
-                     int               index,
-                     union ib_gid     *gid)
+static int __ib_get_cached_gid(struct ib_device *device,
+                              u8                port_num,
+                              int               index,
+                              union ib_gid     *gid)
 {
        struct ib_gid_cache *cache;
        unsigned long flags;
-       int ret = 0;
+       int ret = -ENOENT;
 
        if (port_num < rdma_start_port(device) || port_num > 
rdma_end_port(device))
                return -EINVAL;
+       if (!device->cache.gid_cache)
+               return -ENOENT;
 
        read_lock_irqsave(&device->cache.lock, flags);
 
        cache = device->cache.gid_cache[port_num - rdma_start_port(device)];
-
-       if (index < 0 || index >= cache->table_len)
-               ret = -EINVAL;
-       else
+       if (cache && index >= 0 && index < cache->table_len) {
                *gid = cache->table[index];
+               ret = 0;
+       }
 
        read_unlock_irqrestore(&device->cache.lock, flags);
-
        return ret;
 }
+
+int ib_get_cached_gid(struct ib_device *device,
+                     u8                port_num,
+                     int               index,
+                     union ib_gid     *gid)
+{
+       if (port_num < rdma_start_port(device) || port_num > 
rdma_end_port(device))
+               return -EINVAL;
+
+       if (rdma_cap_roce_gid_table(device, port_num))
+               return roce_gid_table_get_gid(device, port_num, index, gid,
+                                             NULL);
+
+       if (rdma_protocol_roce(device, port_num))
+               return -EAGAIN;
+
+       return __ib_get_cached_gid(device, port_num, index, gid);
+}
 EXPORT_SYMBOL(ib_get_cached_gid);
 
-int ib_find_cached_gid(struct ib_device   *device,
-                      const union ib_gid *gid,
-                      u8                 *port_num,
-                      u16                *index)
+static int ___ib_find_cached_gid_by_port(struct ib_device *device,
+                                        u8               port_num,
+                                        const union ib_gid *gid,
+                                        u16              *index)
 {
        struct ib_gid_cache *cache;
+       u8 p = port_num - rdma_start_port(device);
+       int i;
+
+       if (port_num < rdma_start_port(device) || port_num > 
rdma_end_port(device))
+               return -EINVAL;
+       if (rdma_cap_roce_gid_table(device, port_num))
+               return -EPROTONOSUPPORT;
+       if (!device->cache.gid_cache)
+               return -ENOENT;
+
+       cache = device->cache.gid_cache[p];
+       if (!cache)
+               return -ENOENT;
+
+       for (i = 0; i < cache->table_len; ++i) {
+               if (!memcmp(gid, &cache->table[i], sizeof(*gid))) {
+                       if (index)
+                               *index = i;
+                       return 0;
+               }
+       }
+
+       return -ENOENT;
+}
+
+static int __ib_find_cached_gid(struct ib_device *device,
+                               const union ib_gid *gid,
+                               u8               *port_num,
+                               u16              *index)
+{
        unsigned long flags;
-       int p, i;
+       u16 found_index;
+       int p;
        int ret = -ENOENT;
 
-       *port_num = -1;
+       if (port_num)
+               *port_num = -1;
        if (index)
                *index = -1;
 
        read_lock_irqsave(&device->cache.lock, flags);
 
-       for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p) {
-               cache = device->cache.gid_cache[p];
-               for (i = 0; i < cache->table_len; ++i) {
-                       if (!memcmp(gid, &cache->table[i], sizeof *gid)) {
-                               *port_num = p + rdma_start_port(device);
-                               if (index)
-                                       *index = i;
-                               ret = 0;
-                               goto found;
-                       }
+       for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) {
+               if (!___ib_find_cached_gid_by_port(device, p, gid,
+                                                  &found_index)) {
+                       if (port_num)
+                               *port_num = p;
+                       ret = 0;
+                       break;
                }
        }
-found:
+
        read_unlock_irqrestore(&device->cache.lock, flags);
 
+       if (!ret && index)
+               *index = found_index;
+
+       return ret;
+}
+
+int ib_find_cached_gid(struct ib_device *device,
+                      const union ib_gid *gid,
+                      u8               *port_num,
+                      u16              *index)
+{
+       int ret = -ENOENT;
+
+       /* Look for a RoCE device with the specified GID. */
+       if (device->cache.roce_gid_table)
+               ret = roce_gid_table_find_gid(device, gid, NULL,
+                                             port_num, index);
+
+       /* If no RoCE devices with the specified GID, look for IB device. */
+       if (ret)
+               ret =  __ib_find_cached_gid(device, gid, port_num, index);
+
        return ret;
 }
 EXPORT_SYMBOL(ib_find_cached_gid);
@@ -127,22 +196,23 @@ int ib_get_cached_pkey(struct ib_device *device,
 {
        struct ib_pkey_cache *cache;
        unsigned long flags;
-       int ret = 0;
+       int ret = -ENOENT;
 
        if (port_num < rdma_start_port(device) || port_num > 
rdma_end_port(device))
                return -EINVAL;
 
+       if (!device->cache.pkey_cache)
+               return -ENOENT;
+
        read_lock_irqsave(&device->cache.lock, flags);
 
        cache = device->cache.pkey_cache[port_num - rdma_start_port(device)];
-
-       if (index < 0 || index >= cache->table_len)
-               ret = -EINVAL;
-       else
+       if (cache && index >= 0 && index < cache->table_len) {
                *pkey = cache->table[index];
+               ret = 0;
+       }
 
        read_unlock_irqrestore(&device->cache.lock, flags);
-
        return ret;
 }
 EXPORT_SYMBOL(ib_get_cached_pkey);
@@ -161,9 +231,14 @@ int ib_find_cached_pkey(struct ib_device *device,
        if (port_num < rdma_start_port(device) || port_num > 
rdma_end_port(device))
                return -EINVAL;
 
+       if (!device->cache.pkey_cache)
+               return -ENOENT;
+
        read_lock_irqsave(&device->cache.lock, flags);
 
        cache = device->cache.pkey_cache[port_num - rdma_start_port(device)];
+       if (!cache)
+               goto out;
 
        *index = -1;
 
@@ -182,8 +257,8 @@ int ib_find_cached_pkey(struct ib_device *device,
                ret = 0;
        }
 
+out:
        read_unlock_irqrestore(&device->cache.lock, flags);
-
        return ret;
 }
 EXPORT_SYMBOL(ib_find_cached_pkey);
@@ -201,9 +276,14 @@ int ib_find_exact_cached_pkey(struct ib_device *device,
        if (port_num < rdma_start_port(device) || port_num > 
rdma_end_port(device))
                return -EINVAL;
 
+       if (!device->cache.pkey_cache)
+               return -ENOENT;
+
        read_lock_irqsave(&device->cache.lock, flags);
 
        cache = device->cache.pkey_cache[port_num - rdma_start_port(device)];
+       if (!cache)
+               goto out;
 
        *index = -1;
 
@@ -213,9 +293,8 @@ int ib_find_exact_cached_pkey(struct ib_device *device,
                        ret = 0;
                        break;
                }
-
+out:
        read_unlock_irqrestore(&device->cache.lock, flags);
-
        return ret;
 }
 EXPORT_SYMBOL(ib_find_exact_cached_pkey);
@@ -225,13 +304,16 @@ int ib_get_cached_lmc(struct ib_device *device,
                      u8                *lmc)
 {
        unsigned long flags;
-       int ret = 0;
+       int ret = -ENOENT;
 
        if (port_num < rdma_start_port(device) || port_num > 
rdma_end_port(device))
                return -EINVAL;
 
        read_lock_irqsave(&device->cache.lock, flags);
-       *lmc = device->cache.lmc_cache[port_num - rdma_start_port(device)];
+       if (device->cache.lmc_cache) {
+               *lmc = device->cache.lmc_cache[port_num - 
rdma_start_port(device)];
+               ret = 0;
+       }
        read_unlock_irqrestore(&device->cache.lock, flags);
 
        return ret;
@@ -243,9 +325,18 @@ static void ib_cache_update(struct ib_device *device,
 {
        struct ib_port_attr       *tprops = NULL;
        struct ib_pkey_cache      *pkey_cache = NULL, *old_pkey_cache;
-       struct ib_gid_cache       *gid_cache = NULL, *old_gid_cache;
+       struct ib_gid_cache       *gid_cache = NULL, *old_gid_cache = NULL;
        int                        i;
        int                        ret;
+       bool                       use_roce_gid_table =
+                                       rdma_cap_roce_gid_table(device, port);
+
+       if (port < rdma_start_port(device) || port > rdma_end_port(device))
+               return;
+
+       if (!(device->cache.pkey_cache && device->cache.gid_cache &&
+             device->cache.lmc_cache))
+               return;
 
        tprops = kmalloc(sizeof *tprops, GFP_KERNEL);
        if (!tprops)
@@ -265,12 +356,14 @@ static void ib_cache_update(struct ib_device *device,
 
        pkey_cache->table_len = tprops->pkey_tbl_len;
 
-       gid_cache = kmalloc(sizeof *gid_cache + tprops->gid_tbl_len *
-                           sizeof *gid_cache->table, GFP_KERNEL);
-       if (!gid_cache)
-               goto err;
+       if (!use_roce_gid_table) {
+               gid_cache = kmalloc(sizeof(*gid_cache) + tprops->gid_tbl_len *
+                           sizeof(*gid_cache->table), GFP_KERNEL);
+               if (!gid_cache)
+                       goto err;
 
-       gid_cache->table_len = tprops->gid_tbl_len;
+               gid_cache->table_len = tprops->gid_tbl_len;
+       }
 
        for (i = 0; i < pkey_cache->table_len; ++i) {
                ret = ib_query_pkey(device, port, i, pkey_cache->table + i);
@@ -281,22 +374,28 @@ static void ib_cache_update(struct ib_device *device,
                }
        }
 
-       for (i = 0; i < gid_cache->table_len; ++i) {
-               ret = ib_query_gid(device, port, i, gid_cache->table + i);
-               if (ret) {
-                       printk(KERN_WARNING "ib_query_gid failed (%d) for %s 
(index %d)\n",
-                              ret, device->name, i);
-                       goto err;
+       if (!use_roce_gid_table) {
+               for (i = 0;  i < gid_cache->table_len; ++i) {
+                       ret = ib_query_gid(device, port, i,
+                                          gid_cache->table + i);
+                       if (ret) {
+                               printk(KERN_WARNING "ib_query_gid failed (%d) 
for %s (index %d)\n",
+                                      ret, device->name, i);
+                               goto err;
+                       }
                }
        }
 
        write_lock_irq(&device->cache.lock);
 
        old_pkey_cache = device->cache.pkey_cache[port - 
rdma_start_port(device)];
-       old_gid_cache  = device->cache.gid_cache [port - 
rdma_start_port(device)];
+       if (!use_roce_gid_table)
+               old_gid_cache  =
+                       device->cache.gid_cache[port - rdma_start_port(device)];
 
        device->cache.pkey_cache[port - rdma_start_port(device)] = pkey_cache;
-       device->cache.gid_cache [port - rdma_start_port(device)] = gid_cache;
+       if (!use_roce_gid_table)
+               device->cache.gid_cache[port - rdma_start_port(device)] = 
gid_cache;
 
        device->cache.lmc_cache[port - rdma_start_port(device)] = tprops->lmc;
 
@@ -392,12 +491,19 @@ err:
        kfree(device->cache.pkey_cache);
        kfree(device->cache.gid_cache);
        kfree(device->cache.lmc_cache);
+       device->cache.pkey_cache = NULL;
+       device->cache.gid_cache = NULL;
+       device->cache.lmc_cache = NULL;
 }
 
 static void ib_cache_cleanup_one(struct ib_device *device)
 {
        int p;
 
+       if (!(device->cache.pkey_cache && device->cache.gid_cache &&
+             device->cache.lmc_cache))
+               return;
+
        ib_unregister_event_handler(&device->cache.event_handler);
        flush_workqueue(ib_wq);
 
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 84edb9a..f9c6935 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -40,6 +40,7 @@
 #include <linux/mutex.h>
 #include <rdma/rdma_netlink.h>
 #include <rdma/ib_addr.h>
+#include <rdma/ib_cache.h>
 
 #include "core_priv.h"
 
@@ -593,6 +594,10 @@ EXPORT_SYMBOL(ib_query_port);
 int ib_query_gid(struct ib_device *device,
                 u8 port_num, int index, union ib_gid *gid)
 {
+       if (rdma_cap_roce_gid_table(device, port_num))
+               return roce_gid_table_get_gid(device, port_num, index, gid,
+                                             NULL);
+
        return device->query_gid(device, port_num, index, gid);
 }
 EXPORT_SYMBOL(ib_query_gid);
@@ -738,18 +743,26 @@ EXPORT_SYMBOL(ib_modify_port);
  *   a specified GID value occurs.
  * @device: The device to query.
  * @gid: The GID value to search for.
+ * @ndev: In RoCE, the net device of the device. Null means ignore.
  * @port_num: The port number of the device where the GID value was found.
  * @index: The index into the GID table where the GID was found.  This
  *   parameter may be NULL.
  */
 int ib_find_gid(struct ib_device *device, union ib_gid *gid,
-               u8 *port_num, u16 *index)
+               struct net_device *ndev, u8 *port_num, u16 *index)
 {
        union ib_gid tmp_gid;
        int ret, port, i;
 
+       if (device->cache.roce_gid_table &&
+           !roce_gid_table_find_gid(device, gid, ndev, port_num, index))
+               return 0;
+
        for (port = rdma_start_port(device); port <= rdma_end_port(device); 
++port) {
-               for (i = 0; i < device->port_immutable[port].gid_tbl_len; ++i) {
+               if (rdma_cap_roce_gid_table(device, port))
+                       continue;
+
+               for (i = 0; i < device->port_immutable[port].pkey_tbl_len; ++i) 
{
                        ret = ib_query_gid(device, port, i, &tmp_gid);
                        if (ret)
                                return ret;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 1f918b0..4806d8b 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2093,6 +2093,25 @@ static inline bool rdma_cap_read_multi_sge(struct 
ib_device *device,
        return !(device->port_immutable[port_num].core_cap_flags & 
RDMA_CORE_CAP_PROT_IWARP);
 }
 
+/**
+ * rdma_cap_roce_gid_table - Check if the port of device uses roce_gid_table
+ * @device: Device to check
+ * @port_num: Port number to check
+ *
+ * RoCE GID table mechanism manages the various GIDs for a device.
+ *
+ * NOTE: if allocating the port's GID table has failed, this call will still
+ * return true, but any RoCE GID table API will fail.
+ *
+ * Return: true if the port uses RoCE GID table mechanism in order to manage
+ * its GIDs.
+ */
+static inline bool rdma_cap_roce_gid_table(const struct ib_device *device,
+                                          u8 port_num)
+{
+       return rdma_protocol_roce(device, port_num) && 
device->cache.roce_gid_table;
+}
+
 int ib_query_gid(struct ib_device *device,
                 u8 port_num, int index, union ib_gid *gid);
 
@@ -2108,7 +2127,7 @@ int ib_modify_port(struct ib_device *device,
                   struct ib_port_modify *port_modify);
 
 int ib_find_gid(struct ib_device *device, union ib_gid *gid,
-               u8 *port_num, u16 *index);
+               struct net_device *ndev, u8 *port_num, u16 *index);
 
 int ib_find_pkey(struct ib_device *device,
                 u8 port_num, u16 pkey, u16 *index);
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to