diff mbox series

[for-next,1/2] IB/core: Add option to retrieve driver gid context from ib_gid_attr

Message ID 1576146143-28264-2-git-send-email-selvin.xavier@broadcom.com (mailing list archive)
State Superseded
Headers show
Series Retrieve HW GID context from ib_gid_attr | expand

Commit Message

Selvin Xavier Dec. 12, 2019, 10:22 a.m. UTC
Provide an option to retrieve the driver gid context from ib_gid_attr
structure. Introduce ib_gid_attr_info structure which include both
gid_attr and the GID's HW context. Replace the attr and context
members of ib_gid_table_entry with the new ib_gid_attr_info
structure. Vendor drivers can refer to its own HW gid context
using the container_of macro.

Suggested-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Devesh Sharma <devesh.sharma@broadcom.com>
Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
---
 drivers/infiniband/core/cache.c | 79 +++++++++++++++++++++++------------------
 include/rdma/ib_verbs.h         |  5 +++
 2 files changed, 50 insertions(+), 34 deletions(-)

Comments

Parav Pandit Dec. 13, 2019, 11:17 p.m. UTC | #1
On 12/12/2019 3:52 PM, Selvin Xavier wrote:
> Provide an option to retrieve the driver gid context from ib_gid_attr
> structure. Introduce ib_gid_attr_info structure which include both
> gid_attr and the GID's HW context. Replace the attr and context
> members of ib_gid_table_entry with the new ib_gid_attr_info
> structure. Vendor drivers can refer to its own HW gid context
> using the container_of macro.
> 
> Suggested-by: Jason Gunthorpe <jgg@mellanox.com>
> Signed-off-by: Devesh Sharma <devesh.sharma@broadcom.com>
> Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
> ---
>  drivers/infiniband/core/cache.c | 79 +++++++++++++++++++++++------------------
>  include/rdma/ib_verbs.h         |  5 +++
>  2 files changed, 50 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
> index d535995..54ed25d 100644
> --- a/drivers/infiniband/core/cache.c
> +++ b/drivers/infiniband/core/cache.c
> @@ -86,8 +86,7 @@ struct roce_gid_ndev_storage {
>  struct ib_gid_table_entry {
>  	struct kref			kref;
>  	struct work_struct		del_work;
> -	struct ib_gid_attr		attr;
> -	void				*context;
> +	struct ib_gid_attr_info		attr_info;
>  	/* Store the ndev pointer to release reference later on in
>  	 * call_rcu context because by that time gid_table_entry
>  	 * and attr might be already freed. So keep a copy of it.
> @@ -233,12 +232,13 @@ static void put_gid_ndev(struct rcu_head *head)
>  
>  static void free_gid_entry_locked(struct ib_gid_table_entry *entry)
>  {
> -	struct ib_device *device = entry->attr.device;
> -	u8 port_num = entry->attr.port_num;
> +	struct ib_device *device = entry->attr_info.attr.device;
> +	u8 port_num = entry->attr_info.attr.port_num;
>  	struct ib_gid_table *table = rdma_gid_table(device, port_num);
>  
>  	dev_dbg(&device->dev, "%s port=%d index=%d gid %pI6\n", __func__,
> -		port_num, entry->attr.index, entry->attr.gid.raw);
> +		port_num, entry->attr_info.attr.index,
> +		entry->attr_info.attr.gid.raw);
>  
>  	write_lock_irq(&table->rwlock);
>  
> @@ -248,8 +248,8 @@ static void free_gid_entry_locked(struct ib_gid_table_entry *entry)
>  	 * If new entry in table is added by the time we free here,
>  	 * don't overwrite the table entry.
>  	 */
> -	if (entry == table->data_vec[entry->attr.index])
> -		table->data_vec[entry->attr.index] = NULL;
> +	if (entry == table->data_vec[entry->attr_info.attr.index])
> +		table->data_vec[entry->attr_info.attr.index] = NULL;
>  	/* Now this index is ready to be allocated */
>  	write_unlock_irq(&table->rwlock);
>  
> @@ -278,8 +278,8 @@ static void free_gid_work(struct work_struct *work)
>  {
>  	struct ib_gid_table_entry *entry =
>  		container_of(work, struct ib_gid_table_entry, del_work);
> -	struct ib_device *device = entry->attr.device;
> -	u8 port_num = entry->attr.port_num;
> +	struct ib_device *device = entry->attr_info.attr.device;
> +	u8 port_num = entry->attr_info.attr.port_num;
>  	struct ib_gid_table *table = rdma_gid_table(device, port_num);
>  
>  	mutex_lock(&table->lock);
> @@ -309,7 +309,7 @@ alloc_gid_entry(const struct ib_gid_attr *attr)
>  		entry->ndev_storage->ndev = ndev;
>  	}
>  	kref_init(&entry->kref);
> -	memcpy(&entry->attr, attr, sizeof(*attr));
> +	memcpy(&entry->attr_info.attr, attr, sizeof(*attr));
>  	INIT_WORK(&entry->del_work, free_gid_work);
>  	entry->state = GID_TABLE_ENTRY_INVALID;
>  	return entry;
> @@ -320,13 +320,15 @@ static void store_gid_entry(struct ib_gid_table *table,
>  {
>  	entry->state = GID_TABLE_ENTRY_VALID;
>  
> -	dev_dbg(&entry->attr.device->dev, "%s port=%d index=%d gid %pI6\n",
> -		__func__, entry->attr.port_num, entry->attr.index,
> -		entry->attr.gid.raw);
> +	dev_dbg(&entry->attr_info.attr.device->dev,
> +		"%s port=%d index=%d gid %pI6\n",
> +		__func__, entry->attr_info.attr.port_num,
> +		entry->attr_info.attr.index,
> +		entry->attr_info.attr.gid.raw);
>  
>  	lockdep_assert_held(&table->lock);
>  	write_lock_irq(&table->rwlock);
> -	table->data_vec[entry->attr.index] = entry;
> +	table->data_vec[entry->attr_info.attr.index] = entry;
>  	write_unlock_irq(&table->rwlock);
>  }
>  
> @@ -347,7 +349,7 @@ static void put_gid_entry_locked(struct ib_gid_table_entry *entry)
>  
>  static int add_roce_gid(struct ib_gid_table_entry *entry)
>  {
> -	const struct ib_gid_attr *attr = &entry->attr;
> +	const struct ib_gid_attr *attr = &entry->attr_info.attr;
>  	int ret;
>  
>  	if (!attr->ndev) {
> @@ -356,7 +358,8 @@ static int add_roce_gid(struct ib_gid_table_entry *entry)
>  		return -EINVAL;
>  	}
>  	if (rdma_cap_roce_gid_table(attr->device, attr->port_num)) {
> -		ret = attr->device->ops.add_gid(attr, &entry->context);
> +		ret = attr->device->ops.add_gid(attr,
> +						&entry->attr_info.context);
>  		if (ret) {
>  			dev_err(&attr->device->dev,
>  				"%s GID add failed port=%d index=%d\n",
> @@ -385,7 +388,7 @@ static void del_gid(struct ib_device *ib_dev, u8 port,
>  	lockdep_assert_held(&table->lock);
>  
>  	dev_dbg(&ib_dev->dev, "%s port=%d index=%d gid %pI6\n", __func__, port,
> -		ix, table->data_vec[ix]->attr.gid.raw);
> +		ix, table->data_vec[ix]->attr_info.attr.gid.raw);
>  
>  	write_lock_irq(&table->rwlock);
>  	entry = table->data_vec[ix];
> @@ -400,12 +403,13 @@ static void del_gid(struct ib_device *ib_dev, u8 port,
>  	ndev_storage = entry->ndev_storage;
>  	if (ndev_storage) {
>  		entry->ndev_storage = NULL;
> -		rcu_assign_pointer(entry->attr.ndev, NULL);
> +		rcu_assign_pointer(entry->attr_info.attr.ndev, NULL);
>  		call_rcu(&ndev_storage->rcu_head, put_gid_ndev);
>  	}
>  
>  	if (rdma_cap_roce_gid_table(ib_dev, port))
> -		ib_dev->ops.del_gid(&entry->attr, &entry->context);
> +		ib_dev->ops.del_gid(&entry->attr_info.attr,
> +				    &entry->attr_info.context);
>  
>  	put_gid_entry_locked(entry);
>  }
> @@ -508,13 +512,13 @@ static int find_gid(struct ib_gid_table *table, const union ib_gid *gid,
>  		if (found >= 0)
>  			continue;
>  
> -		attr = &data->attr;
> +		attr = &data->attr_info.attr;
>  		if (mask & GID_ATTR_FIND_MASK_GID_TYPE &&
>  		    attr->gid_type != val->gid_type)
>  			continue;
>  
>  		if (mask & GID_ATTR_FIND_MASK_GID &&
> -		    memcmp(gid, &data->attr.gid, sizeof(*gid)))
> +		    memcmp(gid, &data->attr_info.attr.gid, sizeof(*gid)))
>  			continue;
>  
>  		if (mask & GID_ATTR_FIND_MASK_NETDEV &&
> @@ -648,7 +652,7 @@ int ib_cache_gid_del_all_netdev_gids(struct ib_device *ib_dev, u8 port,
>  
>  	for (ix = 0; ix < table->sz; ix++) {
>  		if (is_gid_entry_valid(table->data_vec[ix]) &&
> -		    table->data_vec[ix]->attr.ndev == ndev) {
> +		    table->data_vec[ix]->attr_info.attr.ndev == ndev) {
>  			del_gid(ib_dev, port, table, ix);
>  			deleted = true;
>  		}
> @@ -703,7 +707,7 @@ rdma_find_gid_by_port(struct ib_device *ib_dev,
>  	local_index = find_gid(table, gid, &val, false, mask, NULL);
>  	if (local_index >= 0) {
>  		get_gid_entry(table->data_vec[local_index]);
> -		attr = &table->data_vec[local_index]->attr;
> +		attr = &table->data_vec[local_index]->attr_info.attr;
>  		read_unlock_irqrestore(&table->rwlock, flags);
>  		return attr;
>  	}
> @@ -753,12 +757,12 @@ const struct ib_gid_attr *rdma_find_gid_by_filter(
>  		if (!is_gid_entry_valid(entry))
>  			continue;
>  
> -		if (memcmp(gid, &entry->attr.gid, sizeof(*gid)))
> +		if (memcmp(gid, &entry->attr_info.attr.gid, sizeof(*gid)))
>  			continue;
>  
> -		if (filter(gid, &entry->attr, context)) {
> +		if (filter(gid, &entry->attr_info.attr, context)) {
>  			get_gid_entry(entry);
> -			res = &entry->attr;
> +			res = &entry->attr_info.attr;
>  			break;
>  		}
>  	}
> @@ -964,7 +968,7 @@ int rdma_query_gid(struct ib_device *device, u8 port_num,
>  	    !is_gid_entry_valid(table->data_vec[index]))
>  		goto done;
>  
> -	memcpy(gid, &table->data_vec[index]->attr.gid, sizeof(*gid));
> +	memcpy(gid, &table->data_vec[index]->attr_info.attr.gid, sizeof(*gid));
>  	res = 0;
>  
>  done:
> @@ -1011,7 +1015,7 @@ const struct ib_gid_attr *rdma_find_gid(struct ib_device *device,
>  			const struct ib_gid_attr *attr;
>  
>  			get_gid_entry(table->data_vec[index]);
> -			attr = &table->data_vec[index]->attr;
> +			attr = &table->data_vec[index]->attr_info.attr;
>  			read_unlock_irqrestore(&table->rwlock, flags);
>  			return attr;
>  		}
> @@ -1210,7 +1214,7 @@ rdma_get_gid_attr(struct ib_device *device, u8 port_num, int index)
>  		goto done;
>  
>  	get_gid_entry(table->data_vec[index]);
> -	attr = &table->data_vec[index]->attr;
> +	attr = &table->data_vec[index]->attr_info.attr;
>  done:
>  	read_unlock_irqrestore(&table->rwlock, flags);
>  	return attr;
> @@ -1230,8 +1234,10 @@ EXPORT_SYMBOL(rdma_get_gid_attr);
>   */
>  void rdma_put_gid_attr(const struct ib_gid_attr *attr)
>  {
> +	struct ib_gid_attr_info *info =
> +		container_of(attr, struct ib_gid_attr_info, attr);
>  	struct ib_gid_table_entry *entry =
> -		container_of(attr, struct ib_gid_table_entry, attr);
> +		container_of(info, struct ib_gid_table_entry, attr_info);
>  
>  	put_gid_entry(entry);
>  }
> @@ -1249,8 +1255,10 @@ EXPORT_SYMBOL(rdma_put_gid_attr);
>   */
>  void rdma_hold_gid_attr(const struct ib_gid_attr *attr)
>  {
> +	struct ib_gid_attr_info *info =
> +		container_of(attr, struct ib_gid_attr_info, attr);
>  	struct ib_gid_table_entry *entry =
> -		container_of(attr, struct ib_gid_table_entry, attr);
> +		container_of(info, struct ib_gid_table_entry, attr_info);
>  
>  	get_gid_entry(entry);
>  }
> @@ -1270,11 +1278,14 @@ EXPORT_SYMBOL(rdma_hold_gid_attr);
>   */
>  struct net_device *rdma_read_gid_attr_ndev_rcu(const struct ib_gid_attr *attr)
>  {
> +	struct ib_gid_attr_info *info =
> +		container_of(attr, struct ib_gid_attr_info, attr);
>  	struct ib_gid_table_entry *entry =
> -			container_of(attr, struct ib_gid_table_entry, attr);
> -	struct ib_device *device = entry->attr.device;
> +			container_of(info, struct ib_gid_table_entry,
> +				     attr_info);
> +	struct ib_device *device = entry->attr_info.attr.device;
>  	struct net_device *ndev = ERR_PTR(-ENODEV);
> -	u8 port_num = entry->attr.port_num;
> +	u8 port_num = entry->attr_info.attr.port_num;
>  	struct ib_gid_table *table;
>  	unsigned long flags;
>  	bool valid;
> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
> index 9d8d7fd..272b8f8 100644
> --- a/include/rdma/ib_verbs.h
> +++ b/include/rdma/ib_verbs.h
> @@ -174,6 +174,11 @@ struct ib_gid_attr {
>  	u8			port_num;
>  };
>  
> +struct ib_gid_attr_info {
> +	struct ib_gid_attr		attr;
> +	void				*context;
No need for tabs in newsly added struct.
	struct ib_gid_attr attr;
..
is fine.

> +};
> +
>  enum {
>  	/* set the local administered indication */
>  	IB_SA_WELL_KNOWN_GUID	= BIT_ULL(57) | 2,
> 
With above nit change.
Reviewed-by: Parav Pandit <parav@mellanox.com>
diff mbox series

Patch

diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index d535995..54ed25d 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -86,8 +86,7 @@  struct roce_gid_ndev_storage {
 struct ib_gid_table_entry {
 	struct kref			kref;
 	struct work_struct		del_work;
-	struct ib_gid_attr		attr;
-	void				*context;
+	struct ib_gid_attr_info		attr_info;
 	/* Store the ndev pointer to release reference later on in
 	 * call_rcu context because by that time gid_table_entry
 	 * and attr might be already freed. So keep a copy of it.
@@ -233,12 +232,13 @@  static void put_gid_ndev(struct rcu_head *head)
 
 static void free_gid_entry_locked(struct ib_gid_table_entry *entry)
 {
-	struct ib_device *device = entry->attr.device;
-	u8 port_num = entry->attr.port_num;
+	struct ib_device *device = entry->attr_info.attr.device;
+	u8 port_num = entry->attr_info.attr.port_num;
 	struct ib_gid_table *table = rdma_gid_table(device, port_num);
 
 	dev_dbg(&device->dev, "%s port=%d index=%d gid %pI6\n", __func__,
-		port_num, entry->attr.index, entry->attr.gid.raw);
+		port_num, entry->attr_info.attr.index,
+		entry->attr_info.attr.gid.raw);
 
 	write_lock_irq(&table->rwlock);
 
@@ -248,8 +248,8 @@  static void free_gid_entry_locked(struct ib_gid_table_entry *entry)
 	 * If new entry in table is added by the time we free here,
 	 * don't overwrite the table entry.
 	 */
-	if (entry == table->data_vec[entry->attr.index])
-		table->data_vec[entry->attr.index] = NULL;
+	if (entry == table->data_vec[entry->attr_info.attr.index])
+		table->data_vec[entry->attr_info.attr.index] = NULL;
 	/* Now this index is ready to be allocated */
 	write_unlock_irq(&table->rwlock);
 
@@ -278,8 +278,8 @@  static void free_gid_work(struct work_struct *work)
 {
 	struct ib_gid_table_entry *entry =
 		container_of(work, struct ib_gid_table_entry, del_work);
-	struct ib_device *device = entry->attr.device;
-	u8 port_num = entry->attr.port_num;
+	struct ib_device *device = entry->attr_info.attr.device;
+	u8 port_num = entry->attr_info.attr.port_num;
 	struct ib_gid_table *table = rdma_gid_table(device, port_num);
 
 	mutex_lock(&table->lock);
@@ -309,7 +309,7 @@  alloc_gid_entry(const struct ib_gid_attr *attr)
 		entry->ndev_storage->ndev = ndev;
 	}
 	kref_init(&entry->kref);
-	memcpy(&entry->attr, attr, sizeof(*attr));
+	memcpy(&entry->attr_info.attr, attr, sizeof(*attr));
 	INIT_WORK(&entry->del_work, free_gid_work);
 	entry->state = GID_TABLE_ENTRY_INVALID;
 	return entry;
@@ -320,13 +320,15 @@  static void store_gid_entry(struct ib_gid_table *table,
 {
 	entry->state = GID_TABLE_ENTRY_VALID;
 
-	dev_dbg(&entry->attr.device->dev, "%s port=%d index=%d gid %pI6\n",
-		__func__, entry->attr.port_num, entry->attr.index,
-		entry->attr.gid.raw);
+	dev_dbg(&entry->attr_info.attr.device->dev,
+		"%s port=%d index=%d gid %pI6\n",
+		__func__, entry->attr_info.attr.port_num,
+		entry->attr_info.attr.index,
+		entry->attr_info.attr.gid.raw);
 
 	lockdep_assert_held(&table->lock);
 	write_lock_irq(&table->rwlock);
-	table->data_vec[entry->attr.index] = entry;
+	table->data_vec[entry->attr_info.attr.index] = entry;
 	write_unlock_irq(&table->rwlock);
 }
 
@@ -347,7 +349,7 @@  static void put_gid_entry_locked(struct ib_gid_table_entry *entry)
 
 static int add_roce_gid(struct ib_gid_table_entry *entry)
 {
-	const struct ib_gid_attr *attr = &entry->attr;
+	const struct ib_gid_attr *attr = &entry->attr_info.attr;
 	int ret;
 
 	if (!attr->ndev) {
@@ -356,7 +358,8 @@  static int add_roce_gid(struct ib_gid_table_entry *entry)
 		return -EINVAL;
 	}
 	if (rdma_cap_roce_gid_table(attr->device, attr->port_num)) {
-		ret = attr->device->ops.add_gid(attr, &entry->context);
+		ret = attr->device->ops.add_gid(attr,
+						&entry->attr_info.context);
 		if (ret) {
 			dev_err(&attr->device->dev,
 				"%s GID add failed port=%d index=%d\n",
@@ -385,7 +388,7 @@  static void del_gid(struct ib_device *ib_dev, u8 port,
 	lockdep_assert_held(&table->lock);
 
 	dev_dbg(&ib_dev->dev, "%s port=%d index=%d gid %pI6\n", __func__, port,
-		ix, table->data_vec[ix]->attr.gid.raw);
+		ix, table->data_vec[ix]->attr_info.attr.gid.raw);
 
 	write_lock_irq(&table->rwlock);
 	entry = table->data_vec[ix];
@@ -400,12 +403,13 @@  static void del_gid(struct ib_device *ib_dev, u8 port,
 	ndev_storage = entry->ndev_storage;
 	if (ndev_storage) {
 		entry->ndev_storage = NULL;
-		rcu_assign_pointer(entry->attr.ndev, NULL);
+		rcu_assign_pointer(entry->attr_info.attr.ndev, NULL);
 		call_rcu(&ndev_storage->rcu_head, put_gid_ndev);
 	}
 
 	if (rdma_cap_roce_gid_table(ib_dev, port))
-		ib_dev->ops.del_gid(&entry->attr, &entry->context);
+		ib_dev->ops.del_gid(&entry->attr_info.attr,
+				    &entry->attr_info.context);
 
 	put_gid_entry_locked(entry);
 }
@@ -508,13 +512,13 @@  static int find_gid(struct ib_gid_table *table, const union ib_gid *gid,
 		if (found >= 0)
 			continue;
 
-		attr = &data->attr;
+		attr = &data->attr_info.attr;
 		if (mask & GID_ATTR_FIND_MASK_GID_TYPE &&
 		    attr->gid_type != val->gid_type)
 			continue;
 
 		if (mask & GID_ATTR_FIND_MASK_GID &&
-		    memcmp(gid, &data->attr.gid, sizeof(*gid)))
+		    memcmp(gid, &data->attr_info.attr.gid, sizeof(*gid)))
 			continue;
 
 		if (mask & GID_ATTR_FIND_MASK_NETDEV &&
@@ -648,7 +652,7 @@  int ib_cache_gid_del_all_netdev_gids(struct ib_device *ib_dev, u8 port,
 
 	for (ix = 0; ix < table->sz; ix++) {
 		if (is_gid_entry_valid(table->data_vec[ix]) &&
-		    table->data_vec[ix]->attr.ndev == ndev) {
+		    table->data_vec[ix]->attr_info.attr.ndev == ndev) {
 			del_gid(ib_dev, port, table, ix);
 			deleted = true;
 		}
@@ -703,7 +707,7 @@  rdma_find_gid_by_port(struct ib_device *ib_dev,
 	local_index = find_gid(table, gid, &val, false, mask, NULL);
 	if (local_index >= 0) {
 		get_gid_entry(table->data_vec[local_index]);
-		attr = &table->data_vec[local_index]->attr;
+		attr = &table->data_vec[local_index]->attr_info.attr;
 		read_unlock_irqrestore(&table->rwlock, flags);
 		return attr;
 	}
@@ -753,12 +757,12 @@  const struct ib_gid_attr *rdma_find_gid_by_filter(
 		if (!is_gid_entry_valid(entry))
 			continue;
 
-		if (memcmp(gid, &entry->attr.gid, sizeof(*gid)))
+		if (memcmp(gid, &entry->attr_info.attr.gid, sizeof(*gid)))
 			continue;
 
-		if (filter(gid, &entry->attr, context)) {
+		if (filter(gid, &entry->attr_info.attr, context)) {
 			get_gid_entry(entry);
-			res = &entry->attr;
+			res = &entry->attr_info.attr;
 			break;
 		}
 	}
@@ -964,7 +968,7 @@  int rdma_query_gid(struct ib_device *device, u8 port_num,
 	    !is_gid_entry_valid(table->data_vec[index]))
 		goto done;
 
-	memcpy(gid, &table->data_vec[index]->attr.gid, sizeof(*gid));
+	memcpy(gid, &table->data_vec[index]->attr_info.attr.gid, sizeof(*gid));
 	res = 0;
 
 done:
@@ -1011,7 +1015,7 @@  const struct ib_gid_attr *rdma_find_gid(struct ib_device *device,
 			const struct ib_gid_attr *attr;
 
 			get_gid_entry(table->data_vec[index]);
-			attr = &table->data_vec[index]->attr;
+			attr = &table->data_vec[index]->attr_info.attr;
 			read_unlock_irqrestore(&table->rwlock, flags);
 			return attr;
 		}
@@ -1210,7 +1214,7 @@  rdma_get_gid_attr(struct ib_device *device, u8 port_num, int index)
 		goto done;
 
 	get_gid_entry(table->data_vec[index]);
-	attr = &table->data_vec[index]->attr;
+	attr = &table->data_vec[index]->attr_info.attr;
 done:
 	read_unlock_irqrestore(&table->rwlock, flags);
 	return attr;
@@ -1230,8 +1234,10 @@  EXPORT_SYMBOL(rdma_get_gid_attr);
  */
 void rdma_put_gid_attr(const struct ib_gid_attr *attr)
 {
+	struct ib_gid_attr_info *info =
+		container_of(attr, struct ib_gid_attr_info, attr);
 	struct ib_gid_table_entry *entry =
-		container_of(attr, struct ib_gid_table_entry, attr);
+		container_of(info, struct ib_gid_table_entry, attr_info);
 
 	put_gid_entry(entry);
 }
@@ -1249,8 +1255,10 @@  EXPORT_SYMBOL(rdma_put_gid_attr);
  */
 void rdma_hold_gid_attr(const struct ib_gid_attr *attr)
 {
+	struct ib_gid_attr_info *info =
+		container_of(attr, struct ib_gid_attr_info, attr);
 	struct ib_gid_table_entry *entry =
-		container_of(attr, struct ib_gid_table_entry, attr);
+		container_of(info, struct ib_gid_table_entry, attr_info);
 
 	get_gid_entry(entry);
 }
@@ -1270,11 +1278,14 @@  EXPORT_SYMBOL(rdma_hold_gid_attr);
  */
 struct net_device *rdma_read_gid_attr_ndev_rcu(const struct ib_gid_attr *attr)
 {
+	struct ib_gid_attr_info *info =
+		container_of(attr, struct ib_gid_attr_info, attr);
 	struct ib_gid_table_entry *entry =
-			container_of(attr, struct ib_gid_table_entry, attr);
-	struct ib_device *device = entry->attr.device;
+			container_of(info, struct ib_gid_table_entry,
+				     attr_info);
+	struct ib_device *device = entry->attr_info.attr.device;
 	struct net_device *ndev = ERR_PTR(-ENODEV);
-	u8 port_num = entry->attr.port_num;
+	u8 port_num = entry->attr_info.attr.port_num;
 	struct ib_gid_table *table;
 	unsigned long flags;
 	bool valid;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 9d8d7fd..272b8f8 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -174,6 +174,11 @@  struct ib_gid_attr {
 	u8			port_num;
 };
 
+struct ib_gid_attr_info {
+	struct ib_gid_attr		attr;
+	void				*context;
+};
+
 enum {
 	/* set the local administered indication */
 	IB_SA_WELL_KNOWN_GUID	= BIT_ULL(57) | 2,