RE: [PATCH v2] IB/mlx4: Fix stale CM id_map entries when RTU is never received
From: Praveen Kannoju
Date: Mon Jul 06 2026 - 08:16:49 EST
Oracle Confidential
+- Anand, Manjunath.
Oracle Confidential
+AD4- -----Original Message-----
+AD4- From: Praveen Kumar Kannoju +ADw-praveen.kannoju+AEA-oracle.com+AD4-
+AD4- Sent: Monday, July 6, 2026 5:33 PM
+AD4- To: yishaih+AEA-nvidia.com+ADs- jgg+AEA-ziepe.ca+ADs- leon+AEA-kernel.org+ADs- linux-
+AD4- rdma+AEA-vger.kernel.org+ADs- linux-kernel+AEA-vger.kernel.org
+AD4- Cc: Praveen Kannoju +ADw-praveen.kannoju+AEA-oracle.com+AD4-
+AD4- Subject: +AFs-PATCH v2+AF0- IB/mlx4: Fix stale CM id+AF8-map entries when RTU is never
+AD4- received
+AD4-
+AD4- mlx4+AF8-ib+AF8-multiplex+AF8-cm+AF8-handler() allocates an id+AF8-map+AF8-entry for CM
+AD4- transactions, but the entry is normally released only on DREQ or REJ
+AD4- flows.
+AD4-
+AD4- In the duplicate REP handling scenario, cm+AF8-dup+AF8-rep+AF8-handler() may be
+AD4- invoked when the remote side receives a REP for which no matching
+AD4- cm+AF8-id+AF8-priv exists. In such cases the CM handshake never reaches RTU, and
+AD4- the sender side may never receive either DREQ or REJ cleanup events.
+AD4-
+AD4- As a result, the allocated id+AF8-map+AF8-entry remains indefinitely, resulting in
+AD4- a stale mapping leak.
+AD4-
+AD4- Fix this by arming an RTU-abandon cleanup timeout when the id+AF8-map+AF8-entry is
+AD4- allocated. The timeout uses the mlx4 CM workqueue and the existing
+AD4- schedule+AF8-delayed() path, so later DREQ/REJ cleanup can shorten the pending
+AD4- timeout with mod+AF8-delayed+AF8-work().
+AD4-
+AD4- Track whether a pending cleanup timeout is still waiting for RTU. RTU
+AD4- cancels only that initial timeout+ADs- if DREQ/REJ has already converted it to
+AD4- normal teardown cleanup, a late or duplicate RTU does not cancel the
+AD4- teardown timer. If the RTU timeout callback has already started, leave the
+AD4- entry on the timeout path and make the RTU packet lose that race.
+AD4-
+AD4- Hold id+AF8-map+AF8-lock while looking up the entry, canceling the RTU timeout,
+AD4- scheduling teardown cleanup, and copying the id values needed by the CM
+AD4- handlers. The delayed-work callback rechecks scheduled+AF8-delete under the
+AD4- same lock before removing and freeing the entry, avoiding use-after-free
+AD4- when RTU races with timeout execution.
+AD4-
+AD4- Signed-off-by: Praveen Kumar Kannoju +ADw-praveen.kannoju+AEA-oracle.com+AD4-
+AD4- ---
+AD4- v1: https://lore.kernel.org/linux-rdma/20260507154755.452008-1-
+AD4- praveen.kannoju+AEA-oracle.com/T/+ACM-u
+AD4-
+AD4- Changes in v2:
+AD4- - Queue the RTU-abandon timeout on the mlx4 CM workqueue through
+AD4- schedule+AF8-delayed() and use mod+AF8-delayed+AF8-work() so DREQ/REJ cleanup can
+AD4- shorten a pending RTU timeout.
+AD4- - Track RTU-abandon cleanup separately from normal DREQ/REJ cleanup so a
+AD4- late or duplicate RTU does not cancel a teardown timer.
+AD4- - Hold id+AF8-map+AF8-lock while looking up id+AF8-map entries, canceling or updating
+AD4- delayed work, and copying CM IDs needed by the handlers.
+AD4- - Make RTU lose the race when the timeout callback has already started.
+AD4-
+AD4- drivers/infiniband/hw/mlx4/cm.c +AHw- 101
+AD4- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-----------
+AD4- 1 file changed, 76 insertions(+-), 25 deletions(-)
+AD4-
+AD4- diff --git a/drivers/infiniband/hw/mlx4/cm.c
+AD4- b/drivers/infiniband/hw/mlx4/cm.c
+AD4- index 63a868a..f7905df 100644
+AD4- --- a/drivers/infiniband/hw/mlx4/cm.c
+AD4- +-+-+- b/drivers/infiniband/hw/mlx4/cm.c
+AD4- +AEAAQA- -40,6 +-40,7 +AEAAQA-
+AD4- +ACM-include +ACI-mlx4+AF8-ib.h+ACI-
+AD4-
+AD4- +ACM-define CM+AF8-CLEANUP+AF8-CACHE+AF8-TIMEOUT (30 +ACo- HZ)
+AD4- +-+ACM-define CM+AF8-RTU+AF8-TIMEOUT (60 +ACo- HZ)
+AD4-
+AD4- struct id+AF8-map+AF8-entry +AHs-
+AD4- struct rb+AF8-node node+ADs-
+AD4- +AEAAQA- -48,6 +-49,7 +AEAAQA- struct id+AF8-map+AF8-entry +AHs-
+AD4- u32 pv+AF8-cm+AF8-id+ADs-
+AD4- int slave+AF8-id+ADs-
+AD4- int scheduled+AF8-delete+ADs-
+AD4- +- bool rtu+AF8-timeout+ADs-
+AD4- struct mlx4+AF8-ib+AF8-dev +ACo-dev+ADs-
+AD4-
+AD4- struct list+AF8-head list+ADs-
+AD4- +AEAAQA- -184,6 +-186,10 +AEAAQA- static void id+AF8-map+AF8-ent+AF8-timeout(struct work+AF8-struct
+AD4- +ACo-work)
+AD4- struct rb+AF8-root +ACo-sl+AF8-id+AF8-map +AD0- +ACY-sriov-+AD4-sl+AF8-id+AF8-map+ADs-
+AD4-
+AD4- spin+AF8-lock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- +- if (+ACE-ent-+AD4-scheduled+AF8-delete) +AHs-
+AD4- +- spin+AF8-unlock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- +- return+ADs-
+AD4- +- +AH0-
+AD4- if (+ACE-xa+AF8-erase(+ACY-sriov-+AD4-pv+AF8-id+AF8-table, ent-+AD4-pv+AF8-cm+AF8-id))
+AD4- goto out+ADs-
+AD4- found+AF8-ent +AD0- id+AF8-map+AF8-find+AF8-by+AF8-sl+AF8-id(+ACY-dev-+AD4-ib+AF8-dev, ent-+AD4-slave+AF8-id, ent-
+AD4- +AD4-sl+AF8-cm+AF8-id)+ADs-
+AD4- +AEAAQA- -228,8 +-234,12 +AEAAQA- static void sl+AF8-id+AF8-map+AF8-add(struct ib+AF8-device +ACo-ibdev,
+AD4- struct id+AF8-map+AF8-entry +ACo-new)
+AD4- rb+AF8-insert+AF8-color(+ACY-new-+AD4-node, sl+AF8-id+AF8-map)+ADs-
+AD4- +AH0-
+AD4-
+AD4- +-static void schedule+AF8-delayed(struct ib+AF8-device +ACo-ibdev, struct id+AF8-map+AF8-entry
+AD4- +ACo-id,
+AD4- +- unsigned long timeout, bool rtu+AF8-timeout)+ADs-
+AD4- +-
+AD4- static struct id+AF8-map+AF8-entry +ACo-
+AD4- -id+AF8-map+AF8-alloc(struct ib+AF8-device +ACo-ibdev, int slave+AF8-id, u32 sl+AF8-cm+AF8-id)
+AD4- +-id+AF8-map+AF8-alloc(struct ib+AF8-device +ACo-ibdev, int slave+AF8-id, u32 sl+AF8-cm+AF8-id,
+AD4- +- u32 +ACo-pv+AF8-cm+AF8-id)
+AD4- +AHs-
+AD4- int ret+ADs-
+AD4- struct id+AF8-map+AF8-entry +ACo-ent+ADs-
+AD4- +AEAAQA- -242,6 +-252,7 +AEAAQA- id+AF8-map+AF8-alloc(struct ib+AF8-device +ACo-ibdev, int slave+AF8-id,
+AD4- u32 sl+AF8-cm+AF8-id)
+AD4- ent-+AD4-sl+AF8-cm+AF8-id +AD0- sl+AF8-cm+AF8-id+ADs-
+AD4- ent-+AD4-slave+AF8-id +AD0- slave+AF8-id+ADs-
+AD4- ent-+AD4-scheduled+AF8-delete +AD0- 0+ADs-
+AD4- +- ent-+AD4-rtu+AF8-timeout +AD0- false+ADs-
+AD4- ent-+AD4-dev +AD0- to+AF8-mdev(ibdev)+ADs-
+AD4- INIT+AF8-DELAYED+AF8-WORK(+ACY-ent-+AD4-timeout, id+AF8-map+AF8-ent+AF8-timeout)+ADs-
+AD4-
+AD4- +AEAAQA- -251,6 +-262,8 +AEAAQA- id+AF8-map+AF8-alloc(struct ib+AF8-device +ACo-ibdev, int slave+AF8-id,
+AD4- u32 sl+AF8-cm+AF8-id)
+AD4- spin+AF8-lock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- sl+AF8-id+AF8-map+AF8-add(ibdev, ent)+ADs-
+AD4- list+AF8-add+AF8-tail(+ACY-ent-+AD4-list, +ACY-sriov-+AD4-cm+AF8-list)+ADs-
+AD4- +- +ACo-pv+AF8-cm+AF8-id +AD0- ent-+AD4-pv+AF8-cm+AF8-id+ADs-
+AD4- +- schedule+AF8-delayed(ibdev, ent, CM+AF8-RTU+AF8-TIMEOUT, true)+ADs-
+AD4- spin+AF8-unlock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- return ent+ADs-
+AD4- +AH0-
+AD4- +AEAAQA- -261,48 +-274,46 +AEAAQA- id+AF8-map+AF8-alloc(struct ib+AF8-device +ACo-ibdev, int slave+AF8-id,
+AD4- u32 sl+AF8-cm+AF8-id)
+AD4- return ERR+AF8-PTR(-ENOMEM)+ADs-
+AD4- +AH0-
+AD4-
+AD4- +-/+ACo- Lock should be taken before called +ACo-/
+AD4- static struct id+AF8-map+AF8-entry +ACo-
+AD4- id+AF8-map+AF8-get(struct ib+AF8-device +ACo-ibdev, int +ACo-pv+AF8-cm+AF8-id, int slave+AF8-id, int sl+AF8-cm+AF8-id)
+AD4- +AHs-
+AD4- struct id+AF8-map+AF8-entry +ACo-ent+ADs-
+AD4- - struct mlx4+AF8-ib+AF8-sriov +ACo-sriov +AD0- +ACY-to+AF8-mdev(ibdev)-+AD4-sriov+ADs-
+AD4-
+AD4- - spin+AF8-lock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- if (+ACo-pv+AF8-cm+AF8-id +AD0APQ- -1) +AHs-
+AD4- ent +AD0- id+AF8-map+AF8-find+AF8-by+AF8-sl+AF8-id(ibdev, slave+AF8-id, sl+AF8-cm+AF8-id)+ADs-
+AD4- if (ent)
+AD4- +ACo-pv+AF8-cm+AF8-id +AD0- (int) ent-+AD4-pv+AF8-cm+AF8-id+ADs-
+AD4- +AH0- else
+AD4- - ent +AD0- xa+AF8-load(+ACY-sriov-+AD4-pv+AF8-id+AF8-table, +ACo-pv+AF8-cm+AF8-id)+ADs-
+AD4- - spin+AF8-unlock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- +- ent +AD0- xa+AF8-load(+ACY-to+AF8-mdev(ibdev)-+AD4-sriov.pv+AF8-id+AF8-table,
+AD4- +ACo-pv+AF8-cm+AF8-id)+ADs-
+AD4-
+AD4- return ent+ADs-
+AD4- +AH0-
+AD4-
+AD4- -static void schedule+AF8-delayed(struct ib+AF8-device +ACo-ibdev, struct id+AF8-map+AF8-entry
+AD4- +ACo-id)
+AD4- +-/+ACo- Lock should be taken before called +ACo-/
+AD4- +-static void schedule+AF8-delayed(struct ib+AF8-device +ACo-ibdev, struct id+AF8-map+AF8-entry
+AD4- +ACo-id,
+AD4- +- unsigned long timeout, bool rtu+AF8-timeout)
+AD4- +AHs-
+AD4- struct mlx4+AF8-ib+AF8-sriov +ACo-sriov +AD0- +ACY-to+AF8-mdev(ibdev)-+AD4-sriov+ADs-
+AD4- unsigned long flags+ADs-
+AD4-
+AD4- - spin+AF8-lock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- spin+AF8-lock+AF8-irqsave(+ACY-sriov-+AD4-going+AF8-down+AF8-lock, flags)+ADs-
+AD4- /+ACo-make sure that there is no schedule inside the scheduled work.+ACo-/
+AD4- - if (+ACE-sriov-+AD4-is+AF8-going+AF8-down +ACYAJg- +ACE-id-+AD4-scheduled+AF8-delete) +AHs-
+AD4- +- if (+ACE-sriov-+AD4-is+AF8-going+AF8-down +AHwAfA- id-+AD4-scheduled+AF8-delete) +AHs-
+AD4- id-+AD4-scheduled+AF8-delete +AD0- 1+ADs-
+AD4- - queue+AF8-delayed+AF8-work(cm+AF8-wq, +ACY-id-+AD4-timeout,
+AD4- CM+AF8-CLEANUP+AF8-CACHE+AF8-TIMEOUT)+ADs-
+AD4- - +AH0- else if (id-+AD4-scheduled+AF8-delete) +AHs-
+AD4- - /+ACo- Adjust timeout if already scheduled +ACo-/
+AD4- - mod+AF8-delayed+AF8-work(cm+AF8-wq, +ACY-id-+AD4-timeout,
+AD4- CM+AF8-CLEANUP+AF8-CACHE+AF8-TIMEOUT)+ADs-
+AD4- +- id-+AD4-rtu+AF8-timeout +AD0- rtu+AF8-timeout+ADs-
+AD4- +- mod+AF8-delayed+AF8-work(cm+AF8-wq, +ACY-id-+AD4-timeout, timeout)+ADs-
+AD4- +AH0-
+AD4- spin+AF8-unlock+AF8-irqrestore(+ACY-sriov-+AD4-going+AF8-down+AF8-lock, flags)+ADs-
+AD4- - spin+AF8-unlock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- +AH0-
+AD4-
+AD4- +ACM-define REJ+AF8-REASON(m) be16+AF8-to+AF8-cpu(((struct cm+AF8-generic+AF8-msg +ACo-)(m))-
+AD4- +AD4-rej+AF8-reason)
+AD4- int mlx4+AF8-ib+AF8-multiplex+AF8-cm+AF8-handler(struct ib+AF8-device +ACo-ibdev, int port, int
+AD4- slave+AF8-id,
+AD4- struct ib+AF8-mad +ACo-mad)
+AD4- +AHs-
+AD4- +- struct mlx4+AF8-ib+AF8-sriov +ACo-sriov +AD0- +ACY-to+AF8-mdev(ibdev)-+AD4-sriov+ADs-
+AD4- struct id+AF8-map+AF8-entry +ACo-id+ADs-
+AD4- +- u32 pv+AF8-cm+AF8-id+AF8-to+AF8-set +AD0- 0+ADs-
+AD4- u32 sl+AF8-cm+AF8-id+ADs-
+AD4- int pv+AF8-cm+AF8-id +AD0- -1+ADs-
+AD4-
+AD4- +AEAAQA- -312,10 +-323,15 +AEAAQA- int mlx4+AF8-ib+AF8-multiplex+AF8-cm+AF8-handler(struct ib+AF8-device
+AD4- +ACo-ibdev, int port, int slave+AF8-id
+AD4- mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ- CM+AF8-SIDR+AF8-REQ+AF8-ATTR+AF8-ID +AHwAfA-
+AD4- (mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ- CM+AF8-REJ+AF8-ATTR+AF8-ID +ACYAJg- REJ+AF8-REASON(mad)
+AD4- +AD0APQ- IB+AF8-CM+AF8-REJ+AF8-TIMEOUT)) +AHs-
+AD4- sl+AF8-cm+AF8-id +AD0- get+AF8-local+AF8-comm+AF8-id(mad)+ADs-
+AD4- +- spin+AF8-lock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- id +AD0- id+AF8-map+AF8-get(ibdev, +ACY-pv+AF8-cm+AF8-id, slave+AF8-id, sl+AF8-cm+AF8-id)+ADs-
+AD4- +- if (id)
+AD4- +- pv+AF8-cm+AF8-id+AF8-to+AF8-set +AD0- id-+AD4-pv+AF8-cm+AF8-id+ADs-
+AD4- +- spin+AF8-unlock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- if (id)
+AD4- goto cont+ADs-
+AD4- - id +AD0- id+AF8-map+AF8-alloc(ibdev, slave+AF8-id, sl+AF8-cm+AF8-id)+ADs-
+AD4- +- id +AD0- id+AF8-map+AF8-alloc(ibdev, slave+AF8-id, sl+AF8-cm+AF8-id,
+AD4- +- +ACY-pv+AF8-cm+AF8-id+AF8-to+AF8-set)+ADs-
+AD4- if (IS+AF8-ERR(id)) +AHs-
+AD4- mlx4+AF8-ib+AF8-warn(ibdev, +ACIAJQ-s: id+AHs-slave: +ACU-d, sl+AF8-cm+AF8-id:
+AD4- 0x+ACU-x+AH0- Failed to id+AF8-map+AF8-alloc+AFw-n+ACI-,
+AD4- +AF8AXw-func+AF8AXw-, slave+AF8-id, sl+AF8-cm+AF8-id)+ADs-
+AD4- +AEAAQA- -326,7 +-342,25 +AEAAQA- int mlx4+AF8-ib+AF8-multiplex+AF8-cm+AF8-handler(struct ib+AF8-device
+AD4- +ACo-ibdev, int port, int slave+AF8-id
+AD4- return 0+ADs-
+AD4- +AH0- else +AHs-
+AD4- sl+AF8-cm+AF8-id +AD0- get+AF8-local+AF8-comm+AF8-id(mad)+ADs-
+AD4- +- spin+AF8-lock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- id +AD0- id+AF8-map+AF8-get(ibdev, +ACY-pv+AF8-cm+AF8-id, slave+AF8-id, sl+AF8-cm+AF8-id)+ADs-
+AD4- +- if (id) +AHs-
+AD4- +- if (mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ- CM+AF8-RTU+AF8-ATTR+AF8-ID +ACYAJg-
+AD4- +- id-+AD4-rtu+AF8-timeout) +AHs-
+AD4- +- id-+AD4-rtu+AF8-timeout +AD0- false+ADs-
+AD4- +- if (cancel+AF8-delayed+AF8-work(+ACY-id-+AD4-timeout))
+AD4- +- id-+AD4-scheduled+AF8-delete +AD0- 0+ADs-
+AD4- +- else
+AD4- +- id +AD0- NULL+ADs-
+AD4- +- +AH0-
+AD4- +- if (id)
+AD4- +- pv+AF8-cm+AF8-id+AF8-to+AF8-set +AD0- id-+AD4-pv+AF8-cm+AF8-id+ADs-
+AD4- +- if (id +ACYAJg- mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ-
+AD4- CM+AF8-DREQ+AF8-ATTR+AF8-ID)
+AD4- +- schedule+AF8-delayed(ibdev, id,
+AD4- +-
+AD4- CM+AF8-CLEANUP+AF8-CACHE+AF8-TIMEOUT,
+AD4- +- false)+ADs-
+AD4- +- +AH0-
+AD4- +- spin+AF8-unlock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- +AH0-
+AD4-
+AD4- if (+ACE-id) +AHs-
+AD4- +AEAAQA- -336,10 +-370,7 +AEAAQA- int mlx4+AF8-ib+AF8-multiplex+AF8-cm+AF8-handler(struct ib+AF8-device
+AD4- +ACo-ibdev, int port, int slave+AF8-id
+AD4- +AH0-
+AD4-
+AD4- cont:
+AD4- - set+AF8-local+AF8-comm+AF8-id(mad, id-+AD4-pv+AF8-cm+AF8-id)+ADs-
+AD4- -
+AD4- - if (mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ- CM+AF8-DREQ+AF8-ATTR+AF8-ID)
+AD4- - schedule+AF8-delayed(ibdev, id)+ADs-
+AD4- +- set+AF8-local+AF8-comm+AF8-id(mad, pv+AF8-cm+AF8-id+AF8-to+AF8-set)+ADs-
+AD4- return 0+ADs-
+AD4- +AH0-
+AD4-
+AD4- +AEAAQA- -429,7 +-460,10 +AEAAQA- int mlx4+AF8-ib+AF8-demux+AF8-cm+AF8-handler(struct ib+AF8-device
+AD4- +ACo-ibdev, int port, int +ACo-slave,
+AD4- struct mlx4+AF8-ib+AF8-sriov +ACo-sriov +AD0- +ACY-to+AF8-mdev(ibdev)-+AD4-sriov+ADs-
+AD4- u32 rem+AF8-pv+AF8-cm+AF8-id +AD0- get+AF8-local+AF8-comm+AF8-id(mad)+ADs-
+AD4- u32 pv+AF8-cm+AF8-id+ADs-
+AD4- +- u32 sl+AF8-cm+AF8-id +AD0- 0+ADs-
+AD4- struct id+AF8-map+AF8-entry +ACo-id+ADs-
+AD4- +- int pv+AF8-cm+AF8-id+AF8-int+ADs-
+AD4- +- int slave+AF8-id +AD0- 0+ADs-
+AD4- int sts+ADs-
+AD4-
+AD4- if (mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ- CM+AF8-REQ+AF8-ATTR+AF8-ID +AHwAfA-
+AD4- +AEAAQA- -457,7 +-491,28 +AEAAQA- int mlx4+AF8-ib+AF8-demux+AF8-cm+AF8-handler(struct ib+AF8-device
+AD4- +ACo-ibdev, int port, int +ACo-slave,
+AD4- +AH0-
+AD4-
+AD4- pv+AF8-cm+AF8-id +AD0- get+AF8-remote+AF8-comm+AF8-id(mad)+ADs-
+AD4- - id +AD0- id+AF8-map+AF8-get(ibdev, (int +ACo-)+ACY-pv+AF8-cm+AF8-id, -1, -1)+ADs-
+AD4- +- pv+AF8-cm+AF8-id+AF8-int +AD0- pv+AF8-cm+AF8-id+ADs-
+AD4- +- spin+AF8-lock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4- +- id +AD0- id+AF8-map+AF8-get(ibdev, +ACY-pv+AF8-cm+AF8-id+AF8-int, -1, -1)+ADs-
+AD4- +- if (id) +AHs-
+AD4- +- if (mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ- CM+AF8-RTU+AF8-ATTR+AF8-ID +ACYAJg-
+AD4- +- id-+AD4-rtu+AF8-timeout) +AHs-
+AD4- +- id-+AD4-rtu+AF8-timeout +AD0- false+ADs-
+AD4- +- if (cancel+AF8-delayed+AF8-work(+ACY-id-+AD4-timeout))
+AD4- +- id-+AD4-scheduled+AF8-delete +AD0- 0+ADs-
+AD4- +- else
+AD4- +- id +AD0- NULL+ADs-
+AD4- +- +AH0-
+AD4- +- if (id +ACYAJg- slave)
+AD4- +- slave+AF8-id +AD0- id-+AD4-slave+AF8-id+ADs-
+AD4- +- if (id)
+AD4- +- sl+AF8-cm+AF8-id +AD0- id-+AD4-sl+AF8-cm+AF8-id+ADs-
+AD4- +- if (id +ACYAJg- (mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ- CM+AF8-DREQ+AF8-ATTR+AF8-ID +AHwAfA-
+AD4- +- mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ- CM+AF8-REJ+AF8-ATTR+AF8-ID))
+AD4- +- schedule+AF8-delayed(ibdev, id,
+AD4- +- CM+AF8-CLEANUP+AF8-CACHE+AF8-TIMEOUT,
+AD4- false)+ADs-
+AD4- +- +AH0-
+AD4- +- spin+AF8-unlock(+ACY-sriov-+AD4-id+AF8-map+AF8-lock)+ADs-
+AD4-
+AD4- if (+ACE-id) +AHs-
+AD4- if (mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ- CM+AF8-REJ+AF8-ATTR+AF8-ID +ACYAJg-
+AD4- +AEAAQA- -472,12 +-527,8 +AEAAQA- int mlx4+AF8-ib+AF8-demux+AF8-cm+AF8-handler(struct ib+AF8-device
+AD4- +ACo-ibdev, int port, int +ACo-slave,
+AD4- +AH0-
+AD4-
+AD4- if (slave)
+AD4- - +ACo-slave +AD0- id-+AD4-slave+AF8-id+ADs-
+AD4- - set+AF8-remote+AF8-comm+AF8-id(mad, id-+AD4-sl+AF8-cm+AF8-id)+ADs-
+AD4- -
+AD4- - if (mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ- CM+AF8-DREQ+AF8-ATTR+AF8-ID +AHwAfA-
+AD4- - mad-+AD4-mad+AF8-hdr.attr+AF8-id +AD0APQ- CM+AF8-REJ+AF8-ATTR+AF8-ID)
+AD4- - schedule+AF8-delayed(ibdev, id)+ADs-
+AD4- +- +ACo-slave +AD0- slave+AF8-id+ADs-
+AD4- +- set+AF8-remote+AF8-comm+AF8-id(mad, sl+AF8-cm+AF8-id)+ADs-
+AD4-
+AD4- return 0+ADs-
+AD4- +AH0-