IB/core: Provide rdma_ versions of the gid cache API
authorJason Gunthorpe <jgg@mellanox.com>
Tue, 5 Jun 2018 05:40:20 +0000 (08:40 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Mon, 18 Jun 2018 17:09:05 +0000 (11:09 -0600)
These versions are functionally similar but all return gid_attrs and
related information via reference instead of via copy.

The old API is preserved, implemented as wrappers around the new, until
all callers can be converted.

Signed-off-by: Parav Pandit <parav@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/core/cache.c
include/rdma/ib_cache.h

index d92525f..8a06e74 100644 (file)
@@ -649,80 +649,37 @@ static int __ib_cache_gid_get(struct ib_device *ib_dev, u8 port, int index,
        return 0;
 }
 
-static int _ib_cache_gid_table_find(struct ib_device *ib_dev,
-                                   const union ib_gid *gid,
-                                   const struct ib_gid_attr *val,
-                                   unsigned long mask,
-                                   u8 *port, u16 *index)
-{
-       struct ib_gid_table *table;
-       u8 p;
-       int local_index;
-       unsigned long flags;
-
-       for (p = 0; p < ib_dev->phys_port_cnt; p++) {
-               table = ib_dev->cache.ports[p].gid;
-               read_lock_irqsave(&table->rwlock, flags);
-               local_index = find_gid(table, gid, val, false, mask, NULL);
-               if (local_index >= 0) {
-                       if (index)
-                               *index = local_index;
-                       if (port)
-                               *port = p + rdma_start_port(ib_dev);
-                       read_unlock_irqrestore(&table->rwlock, flags);
-                       return 0;
-               }
-               read_unlock_irqrestore(&table->rwlock, flags);
-       }
-
-       return -ENOENT;
-}
-
-static int ib_cache_gid_find(struct ib_device *ib_dev,
-                            const union ib_gid *gid,
-                            enum ib_gid_type gid_type,
-                            struct net_device *ndev, u8 *port,
-                            u16 *index)
-{
-       unsigned long mask = GID_ATTR_FIND_MASK_GID |
-                            GID_ATTR_FIND_MASK_GID_TYPE;
-       struct ib_gid_attr gid_attr_val = {.ndev = ndev, .gid_type = gid_type};
-
-       if (ndev)
-               mask |= GID_ATTR_FIND_MASK_NETDEV;
-
-       return _ib_cache_gid_table_find(ib_dev, gid, &gid_attr_val,
-                                       mask, port, index);
-}
-
 /**
- * ib_find_cached_gid_by_port - Returns the GID table index where a specified
- * GID value occurs. It searches for the specified GID value in the local
- * software cache.
+ * rdma_find_gid_by_port - Returns the GID entry attributes when it finds
+ * a valid GID entry for given search parameters. It searches for the specified
+ * GID value in the local software cache.
  * @device: The device to query.
  * @gid: The GID value to search for.
  * @gid_type: The GID type to search for.
  * @port_num: The port number of the device where the GID value should be
  *   searched.
- * @ndev: In RoCE, the net device of the device. Null means ignore.
- * @index: The index into the cached GID table where the GID was found. This
- *   parameter may be NULL.
+ * @ndev: In RoCE, the net device of the device. NULL means ignore.
+ *
+ * Returns sgid attributes if the GID is found with valid reference or
+ * returns ERR_PTR for the error.
+ * The caller must invoke rdma_put_gid_attr() to release the reference.
  */
-int ib_find_cached_gid_by_port(struct ib_device *ib_dev,
-                              const union ib_gid *gid,
-                              enum ib_gid_type gid_type,
-                              u8 port, struct net_device *ndev,
-                              u16 *index)
+const struct ib_gid_attr *
+rdma_find_gid_by_port(struct ib_device *ib_dev,
+                     const union ib_gid *gid,
+                     enum ib_gid_type gid_type,
+                     u8 port, struct net_device *ndev)
 {
        int local_index;
        struct ib_gid_table *table;
        unsigned long mask = GID_ATTR_FIND_MASK_GID |
                             GID_ATTR_FIND_MASK_GID_TYPE;
        struct ib_gid_attr val = {.ndev = ndev, .gid_type = gid_type};
+       const struct ib_gid_attr *attr;
        unsigned long flags;
 
        if (!rdma_is_port_valid(ib_dev, port))
-               return -ENOENT;
+               return ERR_PTR(-ENOENT);
 
        table = rdma_gid_table(ib_dev, port);
 
@@ -732,55 +689,49 @@ int ib_find_cached_gid_by_port(struct ib_device *ib_dev,
        read_lock_irqsave(&table->rwlock, flags);
        local_index = find_gid(table, gid, &val, false, mask, NULL);
        if (local_index >= 0) {
-               if (index)
-                       *index = local_index;
+               get_gid_entry(table->data_vec[local_index]);
+               attr = &table->data_vec[local_index]->attr;
                read_unlock_irqrestore(&table->rwlock, flags);
-               return 0;
+               return attr;
        }
 
        read_unlock_irqrestore(&table->rwlock, flags);
-       return -ENOENT;
+       return ERR_PTR(-ENOENT);
 }
-EXPORT_SYMBOL(ib_find_cached_gid_by_port);
+EXPORT_SYMBOL(rdma_find_gid_by_port);
 
 /**
- * ib_cache_gid_find_by_filter - Returns the GID table index where a specified
- * GID value occurs
+ * rdma_find_gid_by_filter - Returns the GID table attribute where a
+ * specified GID value occurs
  * @device: The device to query.
  * @gid: The GID value to search for.
- * @port_num: The port number of the device where the GID value could be
+ * @port: The port number of the device where the GID value could be
  *   searched.
  * @filter: The filter function is executed on any matching GID in the table.
  *   If the filter function returns true, the corresponding index is returned,
  *   otherwise, we continue searching the GID table. It's guaranteed that
  *   while filter is executed, ndev field is valid and the structure won't
  *   change. filter is executed in an atomic context. filter must not be NULL.
- * @index: The index into the cached GID table where the GID was found. This
- *   parameter may be NULL.
  *
- * ib_cache_gid_find_by_filter() searches for the specified GID value
+ * rdma_find_gid_by_filter() searches for the specified GID value
  * of which the filter function returns true in the port's GID table.
  * This function is only supported on RoCE ports.
  *
  */
-static int ib_cache_gid_find_by_filter(struct ib_device *ib_dev,
-                                      const union ib_gid *gid,
-                                      u8 port,
-                                      bool (*filter)(const union ib_gid *,
-                                                     const struct ib_gid_attr *,
-                                                     void *),
-                                      void *context,
-                                      u16 *index)
+const struct ib_gid_attr *rdma_find_gid_by_filter(
+       struct ib_device *ib_dev, const union ib_gid *gid, u8 port,
+       bool (*filter)(const union ib_gid *gid, const struct ib_gid_attr *,
+                      void *),
+       void *context)
 {
+       const struct ib_gid_attr *res = ERR_PTR(-ENOENT);
        struct ib_gid_table *table;
-       unsigned int i;
        unsigned long flags;
-       bool found = false;
-
+       unsigned int i;
 
        if (!rdma_is_port_valid(ib_dev, port) ||
            !rdma_protocol_roce(ib_dev, port))
-               return -EPROTONOSUPPORT;
+               return ERR_PTR(-EPROTONOSUPPORT);
 
        table = rdma_gid_table(ib_dev, port);
 
@@ -798,18 +749,34 @@ static int ib_cache_gid_find_by_filter(struct ib_device *ib_dev,
                memcpy(&attr, &table->data_vec[i]->attr, sizeof(attr));
 
                if (filter(gid, &attr, context)) {
-                       found = true;
-                       if (index)
-                               *index = i;
+                       get_gid_entry(table->data_vec[i]);
+                       res = &table->data_vec[i]->attr;
                        break;
                }
        }
        read_unlock_irqrestore(&table->rwlock, flags);
+       return res;
+}
+
+int ib_find_cached_gid_by_port(struct ib_device *ib_dev,
+                              const union ib_gid *gid,
+                              enum ib_gid_type gid_type,
+                              u8 port, struct net_device *ndev,
+                              u16 *index)
+{
+       const struct ib_gid_attr *res;
 
-       if (!found)
-               return -ENOENT;
+       res = rdma_find_gid_by_port(ib_dev, gid, gid_type, port, ndev);
+       if (IS_ERR(res))
+               return PTR_ERR(res);
+
+       if (index)
+               *index = res->index;
+       rdma_put_gid_attr(res);
        return 0;
+
 }
+EXPORT_SYMBOL(ib_find_cached_gid_by_port);
 
 static struct ib_gid_table *alloc_gid_table(int sz)
 {
@@ -1016,27 +983,109 @@ int ib_get_cached_gid(struct ib_device *device,
 EXPORT_SYMBOL(ib_get_cached_gid);
 
 /**
- * ib_find_cached_gid - Returns the port number and GID table index where
- *   a specified GID value occurs.
+ * rdma_query_gid - Read the GID content from the GID software cache
+ * @device:            Device to query the GID
+ * @port_num:          Port number of the device
+ * @index:             Index of the GID table entry to read
+ * @gid:               Pointer to GID where to store the entry's GID
+ *
+ * rdma_query_gid() only reads the GID entry content for requested device,
+ * port and index. It reads for IB, RoCE and iWarp link layers.  It doesn't
+ * hold any reference to the GID table entry in the HCA or software cache.
+ *
+ * Returns 0 on success or appropriate error code.
+ *
+ */
+int rdma_query_gid(struct ib_device *device, u8 port_num,
+                  int index, union ib_gid *gid)
+{
+       struct ib_gid_table *table;
+       unsigned long flags;
+       int res = -EINVAL;
+
+       if (!rdma_is_port_valid(device, port_num))
+               return -EINVAL;
+
+       table = rdma_gid_table(device, port_num);
+       read_lock_irqsave(&table->rwlock, flags);
+
+       if (index < 0 || index >= table->sz ||
+           !is_gid_entry_valid(table->data_vec[index]))
+               goto done;
+
+       memcpy(gid, &table->data_vec[index]->attr.gid, sizeof(*gid));
+       res = 0;
+
+done:
+       read_unlock_irqrestore(&table->rwlock, flags);
+       return res;
+}
+EXPORT_SYMBOL(rdma_query_gid);
+
+/**
+ * rdma_find_gid - Returns SGID attributes if the matching GID is found.
  * @device: The device to query.
  * @gid: The GID value to search for.
  * @gid_type: The GID type 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 cached GID table where the GID was found.  This
- *   parameter may be NULL.
  *
- * ib_find_cached_gid() searches for the specified GID value in
- * the local software cache.
+ * rdma_find_gid() searches for the specified GID value in the software cache.
+ *
+ * Returns GID attributes if a valid GID is found or returns ERR_PTR for the
+ * error. The caller must invoke rdma_put_gid_attr() to release the reference.
+ *
  */
-int ib_find_cached_gid(struct ib_device *device,
-                      const union ib_gid *gid,
-                      enum ib_gid_type gid_type,
-                      struct net_device *ndev,
-                      u8               *port_num,
-                      u16              *index)
+const struct ib_gid_attr *rdma_find_gid(struct ib_device *device,
+                                       const union ib_gid *gid,
+                                       enum ib_gid_type gid_type,
+                                       struct net_device *ndev)
 {
-       return ib_cache_gid_find(device, gid, gid_type, ndev, port_num, index);
+       unsigned long mask = GID_ATTR_FIND_MASK_GID |
+                            GID_ATTR_FIND_MASK_GID_TYPE;
+       struct ib_gid_attr gid_attr_val = {.ndev = ndev, .gid_type = gid_type};
+       u8 p;
+
+       if (ndev)
+               mask |= GID_ATTR_FIND_MASK_NETDEV;
+
+       for (p = 0; p < device->phys_port_cnt; p++) {
+               struct ib_gid_table *table;
+               unsigned long flags;
+               int index;
+
+               table = device->cache.ports[p].gid;
+               read_lock_irqsave(&table->rwlock, flags);
+               index = find_gid(table, gid, &gid_attr_val, false, mask, NULL);
+               if (index >= 0) {
+                       const struct ib_gid_attr *attr;
+
+                       get_gid_entry(table->data_vec[index]);
+                       attr = &table->data_vec[index]->attr;
+                       read_unlock_irqrestore(&table->rwlock, flags);
+                       return attr;
+               }
+               read_unlock_irqrestore(&table->rwlock, flags);
+       }
+
+       return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(rdma_find_gid);
+
+int ib_find_cached_gid(struct ib_device *device, const union ib_gid *gid,
+                      enum ib_gid_type gid_type, struct net_device *ndev,
+                      u8 *port_num, u16 *index)
+{
+       const struct ib_gid_attr *res;
+
+       res = rdma_find_gid(device, gid, gid_type, ndev);
+       if (IS_ERR(res))
+               return PTR_ERR(res);
+       if (port_num)
+               *port_num = res->port_num;
+       if (index)
+               *index = res->index;
+       rdma_put_gid_attr(res);
+       return 0;
 }
 EXPORT_SYMBOL(ib_find_cached_gid);
 
@@ -1048,13 +1097,22 @@ int ib_find_gid_by_filter(struct ib_device *device,
                                         void *),
                          void *context, u16 *index)
 {
+       const struct ib_gid_attr *res;
+
        /* Only RoCE GID table supports filter function */
        if (!rdma_protocol_roce(device, port_num) && filter)
                return -EPROTONOSUPPORT;
 
-       return ib_cache_gid_find_by_filter(device, gid,
-                                          port_num, filter,
-                                          context, index);
+       res = rdma_find_gid_by_filter(device, gid, port_num, filter,
+                                     context);
+       if (IS_ERR(res))
+               return PTR_ERR(res);
+
+       if (index)
+               *index = res->index;
+
+       rdma_put_gid_attr(res);
+       return 0;
 }
 
 int ib_get_cached_pkey(struct ib_device *device,
index 00ccd00..059f7d8 100644 (file)
@@ -54,6 +54,8 @@ int ib_get_cached_gid(struct ib_device    *device,
                      int                  index,
                      union ib_gid        *gid,
                      struct ib_gid_attr  *attr);
+int rdma_query_gid(struct ib_device *device, u8 port_num, int index,
+                  union ib_gid *gid);
 
 int ib_find_cached_gid(struct ib_device *device,
                       const union ib_gid *gid,
@@ -61,6 +63,10 @@ int ib_find_cached_gid(struct ib_device *device,
                       struct net_device *ndev,
                       u8               *port_num,
                       u16              *index);
+const struct ib_gid_attr *rdma_find_gid(struct ib_device *device,
+                                       const union ib_gid *gid,
+                                       enum ib_gid_type gid_type,
+                                       struct net_device *ndev);
 
 int ib_find_cached_gid_by_port(struct ib_device *device,
                               const union ib_gid *gid,
@@ -68,6 +74,11 @@ int ib_find_cached_gid_by_port(struct ib_device *device,
                               u8               port_num,
                               struct net_device *ndev,
                               u16              *index);
+const struct ib_gid_attr *rdma_find_gid_by_port(struct ib_device *ib_dev,
+                                               const union ib_gid *gid,
+                                               enum ib_gid_type gid_type,
+                                               u8 port,
+                                               struct net_device *ndev);
 
 int ib_find_gid_by_filter(struct ib_device *device,
                          const union ib_gid *gid,
@@ -76,6 +87,12 @@ int ib_find_gid_by_filter(struct ib_device *device,
                                         const struct ib_gid_attr *,
                                         void *),
                          void *context, u16 *index);
+const struct ib_gid_attr *rdma_find_gid_by_filter(
+       struct ib_device *device, const union ib_gid *gid, u8 port_num,
+       bool (*filter)(const union ib_gid *gid, const struct ib_gid_attr *,
+                      void *),
+       void *context);
+
 /**
  * ib_get_cached_pkey - Returns a cached PKey table entry
  * @device: The device to query.