[PATCH] RDMA/core: Fix swapped list_add_tail() arguments in ib_add_sub_device()
From: lirongqing
Date: Wed Sep 16 2026 - 02:45:21 EST
From: Li RongQing <lirongqing@xxxxxxxxx>
ib_add_sub_device() links a new sub-device into its parent's sub-device
list with:
list_add_tail(&parent->subdev_list_head, &sub->subdev_list);
list_add_tail(new, head) expects the node to insert as the first
argument and the list head as the second, so the call above does the
opposite of what was intended: it treats the parent's list head as the
new node and the sub-device's node as the list head.
Because _ib_alloc_device() initialises subdev_list to a self-referencing
empty head, the misplaced insertion does not crash, but it corrupts the
parent->subdev_list_head list. After adding two or more sub-devices,
only the last one is reachable through the parent's head, and
ib_del_sub_device_and_put()'s list_del() on &sub->subdev_list rewrites
the head pointers, potentially severing earlier sub-devices from the
chain. During parent teardown, the reverse iteration over
subdev_list_head then skips the orphaned sub-devices, so their
del_sub_dev() callbacks are never invoked and ib_device_put() on the
parent is never paired, leaking both the HW sub-devices and a refcount.
Swap the arguments to match the documented intent: insert the
sub-device node into the parent's list head.
Fixes: bca51197620a ("RDMA/core: Support IB sub device with type "SMI"")
Signed-off-by: Li RongQing <lirongqing@xxxxxxxxx>
---
drivers/infiniband/core/device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 7a3ed5e..05dd890 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -3067,7 +3067,7 @@ int ib_add_sub_device(struct ib_device *parent,
sub->parent = parent;
mutex_lock(&parent->subdev_lock);
- list_add_tail(&parent->subdev_list_head, &sub->subdev_list);
+ list_add_tail(&sub->subdev_list, &parent->subdev_list_head);
mutex_unlock(&parent->subdev_lock);
return ret;
--
2.9.4