IB/core: Provide rdma_ versions of the gid cache API

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>
This commit is contained in:
Jason Gunthorpe 2018-06-05 08:40:20 +03:00
parent ddb457c699
commit c3d71b69a7
2 changed files with 180 additions and 105 deletions

View File

@ -649,80 +649,37 @@ static int __ib_cache_gid_get(struct ib_device *ib_dev, u8 port, int index,
return 0; 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 * rdma_find_gid_by_port - Returns the GID entry attributes when it finds
* GID value occurs. It searches for the specified GID value in the local * a valid GID entry for given search parameters. It searches for the specified
* software cache. * GID value in the local software cache.
* @device: The device to query. * @device: The device to query.
* @gid: The GID value to search for. * @gid: The GID value to search for.
* @gid_type: The GID type 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 * @port_num: The port number of the device where the GID value should be
* searched. * searched.
* @ndev: In RoCE, the net device of the device. Null means ignore. * @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. * 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 struct ib_gid_attr *
const union ib_gid *gid, rdma_find_gid_by_port(struct ib_device *ib_dev,
enum ib_gid_type gid_type, const union ib_gid *gid,
u8 port, struct net_device *ndev, enum ib_gid_type gid_type,
u16 *index) u8 port, struct net_device *ndev)
{ {
int local_index; int local_index;
struct ib_gid_table *table; struct ib_gid_table *table;
unsigned long mask = GID_ATTR_FIND_MASK_GID | unsigned long mask = GID_ATTR_FIND_MASK_GID |
GID_ATTR_FIND_MASK_GID_TYPE; GID_ATTR_FIND_MASK_GID_TYPE;
struct ib_gid_attr val = {.ndev = ndev, .gid_type = gid_type}; struct ib_gid_attr val = {.ndev = ndev, .gid_type = gid_type};
const struct ib_gid_attr *attr;
unsigned long flags; unsigned long flags;
if (!rdma_is_port_valid(ib_dev, port)) if (!rdma_is_port_valid(ib_dev, port))
return -ENOENT; return ERR_PTR(-ENOENT);
table = rdma_gid_table(ib_dev, port); 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); read_lock_irqsave(&table->rwlock, flags);
local_index = find_gid(table, gid, &val, false, mask, NULL); local_index = find_gid(table, gid, &val, false, mask, NULL);
if (local_index >= 0) { if (local_index >= 0) {
if (index) get_gid_entry(table->data_vec[local_index]);
*index = local_index; attr = &table->data_vec[local_index]->attr;
read_unlock_irqrestore(&table->rwlock, flags); read_unlock_irqrestore(&table->rwlock, flags);
return 0; return attr;
} }
read_unlock_irqrestore(&table->rwlock, flags); 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 * rdma_find_gid_by_filter - Returns the GID table attribute where a
* GID value occurs * specified GID value occurs
* @device: The device to query. * @device: The device to query.
* @gid: The GID value to search for. * @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. * searched.
* @filter: The filter function is executed on any matching GID in the table. * @filter: The filter function is executed on any matching GID in the table.
* If the filter function returns true, the corresponding index is returned, * If the filter function returns true, the corresponding index is returned,
* otherwise, we continue searching the GID table. It's guaranteed that * otherwise, we continue searching the GID table. It's guaranteed that
* while filter is executed, ndev field is valid and the structure won't * 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. * 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. * of which the filter function returns true in the port's GID table.
* This function is only supported on RoCE ports. * This function is only supported on RoCE ports.
* *
*/ */
static int ib_cache_gid_find_by_filter(struct ib_device *ib_dev, const struct ib_gid_attr *rdma_find_gid_by_filter(
const union ib_gid *gid, struct ib_device *ib_dev, const union ib_gid *gid, u8 port,
u8 port, bool (*filter)(const union ib_gid *gid, const struct ib_gid_attr *,
bool (*filter)(const union ib_gid *, void *),
const struct ib_gid_attr *, void *context)
void *),
void *context,
u16 *index)
{ {
const struct ib_gid_attr *res = ERR_PTR(-ENOENT);
struct ib_gid_table *table; struct ib_gid_table *table;
unsigned int i;
unsigned long flags; unsigned long flags;
bool found = false; unsigned int i;
if (!rdma_is_port_valid(ib_dev, port) || if (!rdma_is_port_valid(ib_dev, port) ||
!rdma_protocol_roce(ib_dev, port)) !rdma_protocol_roce(ib_dev, port))
return -EPROTONOSUPPORT; return ERR_PTR(-EPROTONOSUPPORT);
table = rdma_gid_table(ib_dev, port); table = rdma_gid_table(ib_dev, port);
@ -798,19 +749,35 @@ static int ib_cache_gid_find_by_filter(struct ib_device *ib_dev,
memcpy(&attr, &table->data_vec[i]->attr, sizeof(attr)); memcpy(&attr, &table->data_vec[i]->attr, sizeof(attr));
if (filter(gid, &attr, context)) { if (filter(gid, &attr, context)) {
found = true; get_gid_entry(table->data_vec[i]);
if (index) res = &table->data_vec[i]->attr;
*index = i;
break; break;
} }
} }
read_unlock_irqrestore(&table->rwlock, flags); read_unlock_irqrestore(&table->rwlock, flags);
return res;
if (!found)
return -ENOENT;
return 0;
} }
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;
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) static struct ib_gid_table *alloc_gid_table(int sz)
{ {
struct ib_gid_table *table = kzalloc(sizeof(*table), GFP_KERNEL); struct ib_gid_table *table = kzalloc(sizeof(*table), GFP_KERNEL);
@ -1016,27 +983,109 @@ int ib_get_cached_gid(struct ib_device *device,
EXPORT_SYMBOL(ib_get_cached_gid); EXPORT_SYMBOL(ib_get_cached_gid);
/** /**
* ib_find_cached_gid - Returns the port number and GID table index where * rdma_query_gid - Read the GID content from the GID software cache
* a specified GID value occurs. * @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. * @device: The device to query.
* @gid: The GID value to search for. * @gid: The GID value to search for.
* @gid_type: The GID type to search for. * @gid_type: The GID type to search for.
* @ndev: In RoCE, the net device of the device. NULL means ignore. * @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 * rdma_find_gid() searches for the specified GID value in the software cache.
* the local 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 struct ib_gid_attr *rdma_find_gid(struct ib_device *device,
const union ib_gid *gid, const union ib_gid *gid,
enum ib_gid_type gid_type, enum ib_gid_type gid_type,
struct net_device *ndev, struct net_device *ndev)
u8 *port_num,
u16 *index)
{ {
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); EXPORT_SYMBOL(ib_find_cached_gid);
@ -1048,13 +1097,22 @@ int ib_find_gid_by_filter(struct ib_device *device,
void *), void *),
void *context, u16 *index) void *context, u16 *index)
{ {
const struct ib_gid_attr *res;
/* Only RoCE GID table supports filter function */ /* Only RoCE GID table supports filter function */
if (!rdma_protocol_roce(device, port_num) && filter) if (!rdma_protocol_roce(device, port_num) && filter)
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
return ib_cache_gid_find_by_filter(device, gid, res = rdma_find_gid_by_filter(device, gid, port_num, filter,
port_num, filter, context);
context, index); 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, int ib_get_cached_pkey(struct ib_device *device,

View File

@ -54,6 +54,8 @@ int ib_get_cached_gid(struct ib_device *device,
int index, int index,
union ib_gid *gid, union ib_gid *gid,
struct ib_gid_attr *attr); 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, int ib_find_cached_gid(struct ib_device *device,
const union ib_gid *gid, const union ib_gid *gid,
@ -61,6 +63,10 @@ int ib_find_cached_gid(struct ib_device *device,
struct net_device *ndev, struct net_device *ndev,
u8 *port_num, u8 *port_num,
u16 *index); 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, int ib_find_cached_gid_by_port(struct ib_device *device,
const union ib_gid *gid, const union ib_gid *gid,
@ -68,6 +74,11 @@ int ib_find_cached_gid_by_port(struct ib_device *device,
u8 port_num, u8 port_num,
struct net_device *ndev, struct net_device *ndev,
u16 *index); 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, int ib_find_gid_by_filter(struct ib_device *device,
const union ib_gid *gid, const union ib_gid *gid,
@ -76,6 +87,12 @@ int ib_find_gid_by_filter(struct ib_device *device,
const struct ib_gid_attr *, const struct ib_gid_attr *,
void *), void *),
void *context, u16 *index); 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 * ib_get_cached_pkey - Returns a cached PKey table entry
* @device: The device to query. * @device: The device to query.