diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 2325171dd4473f..cd99c4675a0ec0 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -917,9 +917,11 @@ static void gid_table_cleanup_one(struct ib_device *ib_dev) { u32 p; - rdma_for_each_port (ib_dev, p) + rdma_for_each_port (ib_dev, p) { + ib_dev->port_data[p].cache_is_initialized = 0; cleanup_gid_table_port(ib_dev, p, ib_dev->port_data[p].cache.gid); + } } static int gid_table_setup_one(struct ib_device *ib_dev) @@ -1466,6 +1468,7 @@ ib_cache_update(struct ib_device *device, u32 port, bool update_gids, struct ib_port_attr *tprops = NULL; struct ib_pkey_cache *pkey_cache = NULL; struct ib_pkey_cache *old_pkey_cache = NULL; + union ib_gid gid; int i; int ret; @@ -1523,13 +1526,21 @@ ib_cache_update(struct ib_device *device, u32 port, bool update_gids, device->port_data[port].cache.lmc = tprops->lmc; device->port_data[port].cache.port_state = tprops->state; - device->port_data[port].cache.subnet_prefix = tprops->subnet_prefix; + ret = rdma_query_gid(device, port, 0, &gid); + if (ret) { + write_unlock_irq(&device->cache.lock); + goto err; + } + + device->port_data[port].cache.subnet_prefix = + be64_to_cpu(gid.global.subnet_prefix); + write_unlock_irq(&device->cache_lock); if (enforce_security) ib_security_cache_change(device, port, - tprops->subnet_prefix); + be64_to_cpu(gid.global.subnet_prefix)); kfree(old_pkey_cache); kfree(tprops); @@ -1629,6 +1640,7 @@ int ib_cache_setup_one(struct ib_device *device) err = ib_cache_update(device, p, true, true, true); if (err) return err; + device->port_data[p].cache_is_initialized = 1; } return 0; diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 7a617e4265c000..57b9039b755249 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -2057,6 +2057,15 @@ static int __ib_query_port(struct ib_device *device, IB_LINK_LAYER_INFINIBAND) return 0; + if (!ib_cache_is_initialised(device, port_num)) + goto query_gid_from_device; + + ib_get_cached_subnet_prefix(device, port_num, + &port_attr->subnet_prefix); + + return 0; + +query_gid_from_device: err = device->ops.query_gid(device, port_num, 0, &gid); if (err) return err; diff --git a/include/rdma/ib_cache.h b/include/rdma/ib_cache.h index 226ae3702d8a8e..46b43a703555df 100644 --- a/include/rdma/ib_cache.h +++ b/include/rdma/ib_cache.h @@ -114,4 +114,9 @@ ssize_t rdma_query_gid_table(struct ib_device *device, struct ib_uverbs_gid_entry *entries, size_t max_entries); +static inline bool ib_cache_is_initialised(struct ib_device *device, + u32 port_num) +{ + return device->port_data[port_num].cache_is_initialized; +} #endif /* _IB_CACHE_H */ diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index c96d6012f06e8d..405f7da3c98dce 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -2177,6 +2177,7 @@ struct ib_port_data { spinlock_t netdev_lock; + u8 cache_is_initialized:1; struct list_head pkey_list; struct ib_port_cache cache;