Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b39ffa1d authored by Matan Barak's avatar Matan Barak Committed by Doug Ledford
Browse files

IB/core: Add gid_type to gid attribute



In order to support multiple GID types, we need to store the gid_type
with each GID. This is also aligned with the RoCE v2 annex "RoCEv2 PORT
GID table entries shall have a "GID type" attribute that denotes the L3
Address type". The currently supported GID is IB_GID_TYPE_IB which is
also RoCE v1 GID type.

This implies that gid_type should be added to roce_gid_table meta-data.

Signed-off-by: default avatarMatan Barak <matanb@mellanox.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent cee3c4d0
Loading
Loading
Loading
Loading
+98 −46
Original line number Original line Diff line number Diff line
@@ -64,6 +64,7 @@ enum gid_attr_find_mask {
	GID_ATTR_FIND_MASK_GID          = 1UL << 0,
	GID_ATTR_FIND_MASK_GID          = 1UL << 0,
	GID_ATTR_FIND_MASK_NETDEV	= 1UL << 1,
	GID_ATTR_FIND_MASK_NETDEV	= 1UL << 1,
	GID_ATTR_FIND_MASK_DEFAULT	= 1UL << 2,
	GID_ATTR_FIND_MASK_DEFAULT	= 1UL << 2,
	GID_ATTR_FIND_MASK_GID_TYPE	= 1UL << 3,
};
};


enum gid_table_entry_props {
enum gid_table_entry_props {
@@ -125,6 +126,19 @@ static void dispatch_gid_change_event(struct ib_device *ib_dev, u8 port)
	}
	}
}
}


static const char * const gid_type_str[] = {
	[IB_GID_TYPE_IB]	= "IB/RoCE v1",
};

const char *ib_cache_gid_type_str(enum ib_gid_type gid_type)
{
	if (gid_type < ARRAY_SIZE(gid_type_str) && gid_type_str[gid_type])
		return gid_type_str[gid_type];

	return "Invalid GID type";
}
EXPORT_SYMBOL(ib_cache_gid_type_str);

/* This function expects that rwlock will be write locked in all
/* This function expects that rwlock will be write locked in all
 * scenarios and that lock will be locked in sleep-able (RoCE)
 * scenarios and that lock will be locked in sleep-able (RoCE)
 * scenarios.
 * scenarios.
@@ -233,6 +247,10 @@ static int find_gid(struct ib_gid_table *table, const union ib_gid *gid,
		if (found >= 0)
		if (found >= 0)
			continue;
			continue;


		if (mask & GID_ATTR_FIND_MASK_GID_TYPE &&
		    attr->gid_type != val->gid_type)
			continue;

		if (mask & GID_ATTR_FIND_MASK_GID &&
		if (mask & GID_ATTR_FIND_MASK_GID &&
		    memcmp(gid, &data->gid, sizeof(*gid)))
		    memcmp(gid, &data->gid, sizeof(*gid)))
			continue;
			continue;
@@ -296,6 +314,7 @@ int ib_cache_gid_add(struct ib_device *ib_dev, u8 port,
	write_lock_irq(&table->rwlock);
	write_lock_irq(&table->rwlock);


	ix = find_gid(table, gid, attr, false, GID_ATTR_FIND_MASK_GID |
	ix = find_gid(table, gid, attr, false, GID_ATTR_FIND_MASK_GID |
		      GID_ATTR_FIND_MASK_GID_TYPE |
		      GID_ATTR_FIND_MASK_NETDEV, &empty);
		      GID_ATTR_FIND_MASK_NETDEV, &empty);
	if (ix >= 0)
	if (ix >= 0)
		goto out_unlock;
		goto out_unlock;
@@ -329,6 +348,7 @@ int ib_cache_gid_del(struct ib_device *ib_dev, u8 port,


	ix = find_gid(table, gid, attr, false,
	ix = find_gid(table, gid, attr, false,
		      GID_ATTR_FIND_MASK_GID	  |
		      GID_ATTR_FIND_MASK_GID	  |
		      GID_ATTR_FIND_MASK_GID_TYPE |
		      GID_ATTR_FIND_MASK_NETDEV	  |
		      GID_ATTR_FIND_MASK_NETDEV	  |
		      GID_ATTR_FIND_MASK_DEFAULT,
		      GID_ATTR_FIND_MASK_DEFAULT,
		      NULL);
		      NULL);
@@ -427,11 +447,13 @@ static int _ib_cache_gid_table_find(struct ib_device *ib_dev,


static int ib_cache_gid_find(struct ib_device *ib_dev,
static int ib_cache_gid_find(struct ib_device *ib_dev,
			     const union ib_gid *gid,
			     const union ib_gid *gid,
			     enum ib_gid_type gid_type,
			     struct net_device *ndev, u8 *port,
			     struct net_device *ndev, u8 *port,
			     u16 *index)
			     u16 *index)
{
{
	unsigned long mask = GID_ATTR_FIND_MASK_GID;
	unsigned long mask = GID_ATTR_FIND_MASK_GID |
	struct ib_gid_attr gid_attr_val = {.ndev = ndev};
			     GID_ATTR_FIND_MASK_GID_TYPE;
	struct ib_gid_attr gid_attr_val = {.ndev = ndev, .gid_type = gid_type};


	if (ndev)
	if (ndev)
		mask |= GID_ATTR_FIND_MASK_NETDEV;
		mask |= GID_ATTR_FIND_MASK_NETDEV;
@@ -442,14 +464,16 @@ static int ib_cache_gid_find(struct ib_device *ib_dev,


int ib_find_cached_gid_by_port(struct ib_device *ib_dev,
int ib_find_cached_gid_by_port(struct ib_device *ib_dev,
			       const union ib_gid *gid,
			       const union ib_gid *gid,
			       enum ib_gid_type gid_type,
			       u8 port, struct net_device *ndev,
			       u8 port, struct net_device *ndev,
			       u16 *index)
			       u16 *index)
{
{
	int local_index;
	int local_index;
	struct ib_gid_table **ports_table = ib_dev->cache.gid_cache;
	struct ib_gid_table **ports_table = ib_dev->cache.gid_cache;
	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 |
	struct ib_gid_attr val = {.ndev = ndev};
			     GID_ATTR_FIND_MASK_GID_TYPE;
	struct ib_gid_attr val = {.ndev = ndev, .gid_type = gid_type};
	unsigned long flags;
	unsigned long flags;


	if (port < rdma_start_port(ib_dev) ||
	if (port < rdma_start_port(ib_dev) ||
@@ -607,15 +631,15 @@ static void cleanup_gid_table_port(struct ib_device *ib_dev, u8 port,


void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
				  struct net_device *ndev,
				  struct net_device *ndev,
				  unsigned long gid_type_mask,
				  enum ib_cache_gid_default_mode mode)
				  enum ib_cache_gid_default_mode mode)
{
{
	struct ib_gid_table **ports_table = ib_dev->cache.gid_cache;
	struct ib_gid_table **ports_table = ib_dev->cache.gid_cache;
	union ib_gid gid;
	union ib_gid gid;
	struct ib_gid_attr gid_attr;
	struct ib_gid_attr gid_attr;
	struct ib_gid_attr zattr_type = zattr;
	struct ib_gid_table *table;
	struct ib_gid_table *table;
	int ix;
	unsigned int gid_type;
	union ib_gid current_gid;
	struct ib_gid_attr current_gid_attr = {};


	table  = ports_table[port - rdma_start_port(ib_dev)];
	table  = ports_table[port - rdma_start_port(ib_dev)];


@@ -623,55 +647,82 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
	memset(&gid_attr, 0, sizeof(gid_attr));
	memset(&gid_attr, 0, sizeof(gid_attr));
	gid_attr.ndev = ndev;
	gid_attr.ndev = ndev;


	for (gid_type = 0; gid_type < IB_GID_TYPE_SIZE; ++gid_type) {
		int ix;
		union ib_gid current_gid;
		struct ib_gid_attr current_gid_attr = {};

		if (1UL << gid_type & ~gid_type_mask)
			continue;

		gid_attr.gid_type = gid_type;

		mutex_lock(&table->lock);
		mutex_lock(&table->lock);
		write_lock_irq(&table->rwlock);
		write_lock_irq(&table->rwlock);
	ix = find_gid(table, NULL, NULL, true, GID_ATTR_FIND_MASK_DEFAULT, NULL);
		ix = find_gid(table, NULL, &gid_attr, true,
			      GID_ATTR_FIND_MASK_GID_TYPE |
			      GID_ATTR_FIND_MASK_DEFAULT,
			      NULL);


		/* Coudn't find default GID location */
		/* Coudn't find default GID location */
		WARN_ON(ix < 0);
		WARN_ON(ix < 0);


		zattr_type.gid_type = gid_type;

		if (!__ib_cache_gid_get(ib_dev, port, ix,
		if (!__ib_cache_gid_get(ib_dev, port, ix,
					&current_gid, &current_gid_attr) &&
					&current_gid, &current_gid_attr) &&
		    mode == IB_CACHE_GID_DEFAULT_MODE_SET &&
		    mode == IB_CACHE_GID_DEFAULT_MODE_SET &&
		    !memcmp(&gid, &current_gid, sizeof(gid)) &&
		    !memcmp(&gid, &current_gid, sizeof(gid)) &&
		    !memcmp(&gid_attr, &current_gid_attr, sizeof(gid_attr)))
		    !memcmp(&gid_attr, &current_gid_attr, sizeof(gid_attr)))
		goto unlock;
			goto release;


		if (memcmp(&current_gid, &zgid, sizeof(current_gid)) ||
		if (memcmp(&current_gid, &zgid, sizeof(current_gid)) ||
	    memcmp(&current_gid_attr, &zattr,
		    memcmp(&current_gid_attr, &zattr_type,
			   sizeof(current_gid_attr))) {
			   sizeof(current_gid_attr))) {
			if (del_gid(ib_dev, port, table, ix, true)) {
			if (del_gid(ib_dev, port, table, ix, true)) {
				pr_warn("ib_cache_gid: can't delete index %d for default gid %pI6\n",
				pr_warn("ib_cache_gid: can't delete index %d for default gid %pI6\n",
					ix, gid.raw);
					ix, gid.raw);
			goto unlock;
				goto release;
			} else {
			} else {
				dispatch_gid_change_event(ib_dev, port);
				dispatch_gid_change_event(ib_dev, port);
			}
			}
		}
		}


		if (mode == IB_CACHE_GID_DEFAULT_MODE_SET) {
		if (mode == IB_CACHE_GID_DEFAULT_MODE_SET) {
		if (add_gid(ib_dev, port, table, ix, &gid, &gid_attr, true)) {
			if (add_gid(ib_dev, port, table, ix, &gid, &gid_attr, true))
				pr_warn("ib_cache_gid: unable to add default gid %pI6\n",
				pr_warn("ib_cache_gid: unable to add default gid %pI6\n",
					gid.raw);
					gid.raw);
		} else {
			else
				dispatch_gid_change_event(ib_dev, port);
				dispatch_gid_change_event(ib_dev, port);
		}
		}
	}


unlock:
release:
		if (current_gid_attr.ndev)
		if (current_gid_attr.ndev)
			dev_put(current_gid_attr.ndev);
			dev_put(current_gid_attr.ndev);
		write_unlock_irq(&table->rwlock);
		write_unlock_irq(&table->rwlock);
		mutex_unlock(&table->lock);
		mutex_unlock(&table->lock);
	}
	}
}


static int gid_table_reserve_default(struct ib_device *ib_dev, u8 port,
static int gid_table_reserve_default(struct ib_device *ib_dev, u8 port,
				     struct ib_gid_table *table)
				     struct ib_gid_table *table)
{
{
	if (rdma_protocol_roce(ib_dev, port)) {
	unsigned int i;
		struct ib_gid_table_entry *entry = &table->data_vec[0];
	unsigned long roce_gid_type_mask;
	unsigned int num_default_gids;
	unsigned int current_gid = 0;

	roce_gid_type_mask = roce_gid_type_mask_support(ib_dev, port);
	num_default_gids = hweight_long(roce_gid_type_mask);
	for (i = 0; i < num_default_gids && i < table->sz; i++) {
		struct ib_gid_table_entry *entry =
			&table->data_vec[i];


		entry->props |= GID_TABLE_ENTRY_DEFAULT;
		entry->props |= GID_TABLE_ENTRY_DEFAULT;
		current_gid = find_next_bit(&roce_gid_type_mask,
					    BITS_PER_LONG,
					    current_gid);
		entry->attr.gid_type = current_gid++;
	}
	}


	return 0;
	return 0;
@@ -794,11 +845,12 @@ EXPORT_SYMBOL(ib_get_cached_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,
		       enum ib_gid_type gid_type,
		       struct net_device *ndev,
		       struct net_device *ndev,
		       u8               *port_num,
		       u8               *port_num,
		       u16              *index)
		       u16              *index)
{
{
	return ib_cache_gid_find(device, gid, ndev, port_num, index);
	return ib_cache_gid_find(device, gid, gid_type, ndev, port_num, index);
}
}
EXPORT_SYMBOL(ib_find_cached_gid);
EXPORT_SYMBOL(ib_find_cached_gid);


+1 −1
Original line number Original line Diff line number Diff line
@@ -364,7 +364,7 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
	read_lock_irqsave(&cm.device_lock, flags);
	read_lock_irqsave(&cm.device_lock, flags);
	list_for_each_entry(cm_dev, &cm.device_list, list) {
	list_for_each_entry(cm_dev, &cm.device_list, list) {
		if (!ib_find_cached_gid(cm_dev->ib_device, &path->sgid,
		if (!ib_find_cached_gid(cm_dev->ib_device, &path->sgid,
					ndev, &p, NULL)) {
					IB_GID_TYPE_IB, ndev, &p, NULL)) {
			port = cm_dev->port[p-1];
			port = cm_dev->port[p-1];
			break;
			break;
		}
		}
+2 −1
Original line number Original line Diff line number Diff line
@@ -456,7 +456,8 @@ static inline int cma_validate_port(struct ib_device *device, u8 port,
	if (dev_type == ARPHRD_ETHER)
	if (dev_type == ARPHRD_ETHER)
		ndev = dev_get_by_index(&init_net, bound_if_index);
		ndev = dev_get_by_index(&init_net, bound_if_index);


	ret = ib_find_cached_gid_by_port(device, gid, port, ndev, NULL);
	ret = ib_find_cached_gid_by_port(device, gid, IB_GID_TYPE_IB, port,
					 ndev, NULL);


	if (ndev)
	if (ndev)
		dev_put(ndev);
		dev_put(ndev);
+4 −0
Original line number Original line Diff line number Diff line
@@ -70,8 +70,11 @@ enum ib_cache_gid_default_mode {
	IB_CACHE_GID_DEFAULT_MODE_DELETE
	IB_CACHE_GID_DEFAULT_MODE_DELETE
};
};


const char *ib_cache_gid_type_str(enum ib_gid_type gid_type);

void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
				  struct net_device *ndev,
				  struct net_device *ndev,
				  unsigned long gid_type_mask,
				  enum ib_cache_gid_default_mode mode);
				  enum ib_cache_gid_default_mode mode);


int ib_cache_gid_add(struct ib_device *ib_dev, u8 port,
int ib_cache_gid_add(struct ib_device *ib_dev, u8 port,
@@ -87,6 +90,7 @@ int roce_gid_mgmt_init(void);
void roce_gid_mgmt_cleanup(void);
void roce_gid_mgmt_cleanup(void);


int roce_rescan_device(struct ib_device *ib_dev);
int roce_rescan_device(struct ib_device *ib_dev);
unsigned long roce_gid_type_mask_support(struct ib_device *ib_dev, u8 port);


int ib_cache_setup_one(struct ib_device *device);
int ib_cache_setup_one(struct ib_device *device);
void ib_cache_cleanup_one(struct ib_device *device);
void ib_cache_cleanup_one(struct ib_device *device);
+7 −2
Original line number Original line Diff line number Diff line
@@ -815,26 +815,31 @@ EXPORT_SYMBOL(ib_modify_port);
 *   a specified GID value occurs.
 *   a 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.
 * @gid_type: Type of GID.
 * @ndev: The ndev related to the GID to search for.
 * @ndev: The ndev related to the GID to search for.
 * @port_num: The port number of the device where the GID value was found.
 * @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
 * @index: The index into the GID table where the GID was found.  This
 *   parameter may be NULL.
 *   parameter may be NULL.
 */
 */
int ib_find_gid(struct ib_device *device, union ib_gid *gid,
int ib_find_gid(struct ib_device *device, union ib_gid *gid,
		struct net_device *ndev, u8 *port_num, u16 *index)
		enum ib_gid_type gid_type, struct net_device *ndev,
		u8 *port_num, u16 *index)
{
{
	union ib_gid tmp_gid;
	union ib_gid tmp_gid;
	int ret, port, i;
	int ret, port, i;


	for (port = rdma_start_port(device); port <= rdma_end_port(device); ++port) {
	for (port = rdma_start_port(device); port <= rdma_end_port(device); ++port) {
		if (rdma_cap_roce_gid_table(device, port)) {
		if (rdma_cap_roce_gid_table(device, port)) {
			if (!ib_find_cached_gid_by_port(device, gid, port,
			if (!ib_find_cached_gid_by_port(device, gid, gid_type, port,
							ndev, index)) {
							ndev, index)) {
				*port_num = port;
				*port_num = port;
				return 0;
				return 0;
			}
			}
		}
		}


		if (gid_type != IB_GID_TYPE_IB)
			continue;

		for (i = 0; i < device->port_immutable[port].gid_tbl_len; ++i) {
		for (i = 0; i < device->port_immutable[port].gid_tbl_len; ++i) {
			ret = ib_query_gid(device, port, i, &tmp_gid, NULL);
			ret = ib_query_gid(device, port, i, &tmp_gid, NULL);
			if (ret)
			if (ret)
Loading