[PATCH rdma-next 2/2] IB/core: Free GID table entry during GID deletion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Parav Pandit <parav@xxxxxxxxxxxx>

If the GID table entry has no active users, which means its
kref count is 1. In such case, there is no need to schedule
GID deletion work. It can be completed in the caller's blocking
context in del_gid() directly.

This helps to eliminate issues when GID change is requested as part of
MAC address change or bonding event change where expectation is to
replace the GID almost immediately.

Fixes: b150c3862d21 ("IB/core: Introduce GID entry reference counts")
Reviewed-by: Daniel Jurgens <danielj@xxxxxxxxxxxx>
Signed-off-by: Parav Pandit <parav@xxxxxxxxxxxx>
Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx>
---
 drivers/infiniband/core/cache.c | 28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index a3072d77389a..357a5cb328c7 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -206,7 +206,7 @@ static void schedule_free_gid(struct kref *kref)
 	queue_work(ib_wq, &entry->del_work);
 }
 
-static void free_gid_entry(struct ib_gid_table_entry *entry)
+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;
@@ -216,10 +216,10 @@ static void free_gid_entry(struct ib_gid_table_entry *entry)
 		 device->name, port_num, entry->attr.index,
 		 entry->attr.gid.raw);
 
-	mutex_lock(&table->lock);
 	if (rdma_cap_roce_gid_table(device, port_num) &&
 	    entry->state != GID_TABLE_ENTRY_INVALID)
 		device->del_gid(&entry->attr, &entry->context);
+
 	write_lock_irq(&table->rwlock);
 
 	/*
@@ -232,13 +232,20 @@ static void free_gid_entry(struct ib_gid_table_entry *entry)
 		table->data_vec[entry->attr.index] = NULL;
 	/* Now this index is ready to be allocated */
 	write_unlock_irq(&table->rwlock);
-	mutex_unlock(&table->lock);
 
 	if (entry->attr.ndev)
 		dev_put(entry->attr.ndev);
 	kfree(entry);
 }
 
+static void free_gid_entry(struct kref *kref)
+{
+	struct ib_gid_table_entry *entry =
+			container_of(kref, struct ib_gid_table_entry, kref);
+
+	free_gid_entry_locked(entry);
+}
+
 /**
  * free_gid_work - Release reference to the GID entry
  * @work: Work structure to refer to GID entry which needs to be
@@ -251,7 +258,13 @@ 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);
-	free_gid_entry(entry);
+	struct ib_device *device = entry->attr.device;
+	u8 port_num = entry->attr.port_num;
+	struct ib_gid_table *table = rdma_gid_table(device, port_num);
+
+	mutex_lock(&table->lock);
+	free_gid_entry_locked(entry);
+	mutex_unlock(&table->lock);
 }
 
 static struct ib_gid_table_entry *
@@ -296,6 +309,11 @@ static void put_gid_entry(struct ib_gid_table_entry *entry)
 	kref_put(&entry->kref, schedule_free_gid);
 }
 
+static void put_gid_entry_locked(struct ib_gid_table_entry *entry)
+{
+	kref_put(&entry->kref, free_gid_entry);
+}
+
 static int add_roce_gid(struct ib_gid_table_entry *entry)
 {
 	const struct ib_gid_attr *attr = &entry->attr;
@@ -398,7 +416,7 @@ static void del_gid(struct ib_device *ib_dev, u8 port,
 		table->data_vec[ix] = NULL;
 	write_unlock_irq(&table->rwlock);
 
-	put_gid_entry(entry);
+	put_gid_entry_locked(entry);
 }
 
 /* rwlock should be read locked, or lock should be held */
-- 
2.14.4

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux