]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
smb: smbdirect: introduce smbdirect_connection_negotiate_rdma_resources()
authorStefan Metzmacher <metze@samba.org>
Wed, 17 Sep 2025 04:19:46 +0000 (06:19 +0200)
committerSteve French <stfrench@microsoft.com>
Thu, 16 Apr 2026 02:58:19 +0000 (21:58 -0500)
This is a copy of the same logic used in client and server,
it's inlined there, but they will use the new helper function
soon.

Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/common/smbdirect/smbdirect_connection.c

index ac3f2341320b8148788bf367c3d653930122afbc..5308bdd4797eb041b1afdf5bb27336723b6bfed3 100644 (file)
@@ -275,6 +275,68 @@ smbdirect_connection_reassembly_first_recv_io(struct smbdirect_socket *sc)
        return msg;
 }
 
+__maybe_unused /* this is temporary while this file is included in others */
+static void smbdirect_connection_negotiate_rdma_resources(struct smbdirect_socket *sc,
+                                                         u8 peer_initiator_depth,
+                                                         u8 peer_responder_resources,
+                                                         const struct rdma_conn_param *param)
+{
+       struct smbdirect_socket_parameters *sp = &sc->parameters;
+
+       if (rdma_protocol_iwarp(sc->ib.dev, sc->rdma.cm_id->port_num) &&
+           param->private_data_len == 8) {
+               /*
+                * Legacy clients with only iWarp MPA v1 support
+                * need a private blob in order to negotiate
+                * the IRD/ORD values.
+                */
+               const __be32 *ird_ord_hdr = param->private_data;
+               u32 ird32 = be32_to_cpu(ird_ord_hdr[0]);
+               u32 ord32 = be32_to_cpu(ird_ord_hdr[1]);
+
+               /*
+                * cifs.ko sends the legacy IRD/ORD negotiation
+                * event if iWarp MPA v2 was used.
+                *
+                * Here we check that the values match and only
+                * mark the client as legacy if they don't match.
+                */
+               if ((u32)param->initiator_depth != ird32 ||
+                   (u32)param->responder_resources != ord32) {
+                       /*
+                        * There are broken clients (old cifs.ko)
+                        * using little endian and also
+                        * struct rdma_conn_param only uses u8
+                        * for initiator_depth and responder_resources,
+                        * so we truncate the value to U8_MAX.
+                        *
+                        * smb_direct_accept_client() will then
+                        * do the real negotiation in order to
+                        * select the minimum between client and
+                        * server.
+                        */
+                       ird32 = min_t(u32, ird32, U8_MAX);
+                       ord32 = min_t(u32, ord32, U8_MAX);
+
+                       sc->rdma.legacy_iwarp = true;
+                       peer_initiator_depth = (u8)ird32;
+                       peer_responder_resources = (u8)ord32;
+               }
+       }
+
+       /*
+        * negotiate the value by using the minimum
+        * between client and server if the client provided
+        * non 0 values.
+        */
+       if (peer_initiator_depth != 0)
+               sp->initiator_depth = min_t(u8, sp->initiator_depth,
+                                           peer_initiator_depth);
+       if (peer_responder_resources != 0)
+               sp->responder_resources = min_t(u8, sp->responder_resources,
+                                               peer_responder_resources);
+}
+
 static void smbdirect_connection_idle_timer_work(struct work_struct *work)
 {
        struct smbdirect_socket *sc =