]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net/smc: extend smc_llc_send_add_link() and smc_llc_send_delete_link()
authorKarsten Graul <kgraul@linux.ibm.com>
Fri, 1 May 2020 10:48:04 +0000 (12:48 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 1 May 2020 23:20:04 +0000 (16:20 -0700)
All LLC sends are done from worker context only, so remove the prep
functions which were used to build the message before it was sent, and
add the function content into the respective send function
smc_llc_send_add_link() and smc_llc_send_delete_link().
Extend smc_llc_send_add_link() to include the qp_mtu value in the LLC
message, which is needed to establish a link after the initial link was
created. Extend smc_llc_send_delete_link() to contain a link_id and a
reason code for the link deletion in the LLC message, which is needed
when a specific link should be deleted.
And add the list of existing DELETE_LINK reason codes.

Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Reviewed-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/smc/smc_core.c
net/smc/smc_llc.c
net/smc/smc_llc.h

index 0e87f652caeae2779f7e83564c0dcf6828e5f812..c905675017c7ec4843748321687cc7b61c3f6ed0 100644 (file)
@@ -199,7 +199,8 @@ void smc_lgr_cleanup_early(struct smc_connection *conn)
 static int smcr_link_send_delete(struct smc_link *lnk, bool orderly)
 {
        if (lnk->state == SMC_LNK_ACTIVE &&
-           !smc_llc_send_delete_link(lnk, SMC_LLC_REQ, orderly)) {
+           !smc_llc_send_delete_link(lnk, 0, SMC_LLC_REQ, orderly,
+                                     SMC_LLC_DEL_PROG_INIT_TERM)) {
                return 0;
        }
        return -ENOTCONN;
index 327cf30b98cc892fc22975a92126df3413869da7..171835926db6f67c5b032f2e02b87a036f8bfc71 100644 (file)
@@ -58,7 +58,13 @@ struct smc_llc_msg_add_link {                /* type 0x02 */
        u8 sender_gid[SMC_GID_SIZE];
        u8 sender_qp_num[3];
        u8 link_num;
-       u8 flags2;      /* QP mtu */
+#if defined(__BIG_ENDIAN_BITFIELD)
+       u8 reserved3 : 4,
+          qp_mtu   : 4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+       u8 qp_mtu   : 4,
+          reserved3 : 4;
+#endif
        u8 initial_psn[3];
        u8 reserved[8];
 };
@@ -427,26 +433,9 @@ static int smc_llc_send_delete_rkey(struct smc_link *link,
        return rc;
 }
 
-/* prepare an add link message */
-static void smc_llc_prep_add_link(struct smc_llc_msg_add_link *addllc,
-                                 struct smc_link *link, u8 mac[], u8 gid[],
-                                 enum smc_llc_reqresp reqresp)
-{
-       memset(addllc, 0, sizeof(*addllc));
-       addllc->hd.common.type = SMC_LLC_ADD_LINK;
-       addllc->hd.length = sizeof(struct smc_llc_msg_add_link);
-       if (reqresp == SMC_LLC_RESP) {
-               addllc->hd.flags |= SMC_LLC_FLAG_RESP;
-               /* always reject more links for now */
-               addllc->hd.flags |= SMC_LLC_FLAG_ADD_LNK_REJ;
-               addllc->hd.add_link_rej_rsn = SMC_LLC_REJ_RSN_NO_ALT_PATH;
-       }
-       memcpy(addllc->sender_mac, mac, ETH_ALEN);
-       memcpy(addllc->sender_gid, gid, SMC_GID_SIZE);
-}
-
 /* send ADD LINK request or response */
 int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[],
+                         struct smc_link *link_new,
                          enum smc_llc_reqresp reqresp)
 {
        struct smc_llc_msg_add_link *addllc;
@@ -458,32 +447,33 @@ int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[],
        if (rc)
                return rc;
        addllc = (struct smc_llc_msg_add_link *)wr_buf;
-       smc_llc_prep_add_link(addllc, link, mac, gid, reqresp);
+
+       memset(addllc, 0, sizeof(*addllc));
+       addllc->hd.common.type = SMC_LLC_ADD_LINK;
+       addllc->hd.length = sizeof(struct smc_llc_msg_add_link);
+       if (reqresp == SMC_LLC_RESP)
+               addllc->hd.flags |= SMC_LLC_FLAG_RESP;
+       memcpy(addllc->sender_mac, mac, ETH_ALEN);
+       memcpy(addllc->sender_gid, gid, SMC_GID_SIZE);
+       if (link_new) {
+               addllc->link_num = link_new->link_id;
+               hton24(addllc->sender_qp_num, link_new->roce_qp->qp_num);
+               hton24(addllc->initial_psn, link_new->psn_initial);
+               if (reqresp == SMC_LLC_REQ)
+                       addllc->qp_mtu = link_new->path_mtu;
+               else
+                       addllc->qp_mtu = min(link_new->path_mtu,
+                                            link_new->peer_mtu);
+       }
        /* send llc message */
        rc = smc_wr_tx_send(link, pend);
        return rc;
 }
 
-/* prepare a delete link message */
-static void smc_llc_prep_delete_link(struct smc_llc_msg_del_link *delllc,
-                                    struct smc_link *link,
-                                    enum smc_llc_reqresp reqresp, bool orderly)
-{
-       memset(delllc, 0, sizeof(*delllc));
-       delllc->hd.common.type = SMC_LLC_DELETE_LINK;
-       delllc->hd.length = sizeof(struct smc_llc_msg_add_link);
-       if (reqresp == SMC_LLC_RESP)
-               delllc->hd.flags |= SMC_LLC_FLAG_RESP;
-       /* DEL_LINK_ALL because only 1 link supported */
-       delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ALL;
-       if (orderly)
-               delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY;
-       delllc->link_num = link->link_id;
-}
-
 /* send DELETE LINK request or response */
-int smc_llc_send_delete_link(struct smc_link *link,
-                            enum smc_llc_reqresp reqresp, bool orderly)
+int smc_llc_send_delete_link(struct smc_link *link, u8 link_del_id,
+                            enum smc_llc_reqresp reqresp, bool orderly,
+                            u32 reason)
 {
        struct smc_llc_msg_del_link *delllc;
        struct smc_wr_tx_pend_priv *pend;
@@ -494,7 +484,19 @@ int smc_llc_send_delete_link(struct smc_link *link,
        if (rc)
                return rc;
        delllc = (struct smc_llc_msg_del_link *)wr_buf;
-       smc_llc_prep_delete_link(delllc, link, reqresp, orderly);
+
+       memset(delllc, 0, sizeof(*delllc));
+       delllc->hd.common.type = SMC_LLC_DELETE_LINK;
+       delllc->hd.length = sizeof(struct smc_llc_msg_del_link);
+       if (reqresp == SMC_LLC_RESP)
+               delllc->hd.flags |= SMC_LLC_FLAG_RESP;
+       if (orderly)
+               delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ORDERLY;
+       if (link_del_id)
+               delllc->link_num = link_del_id;
+       else
+               delllc->hd.flags |= SMC_LLC_FLAG_DEL_LINK_ALL;
+       delllc->reason = htonl(reason);
        /* send llc message */
        rc = smc_wr_tx_send(link, pend);
        return rc;
@@ -547,12 +549,13 @@ static void smc_llc_rx_delete_link(struct smc_link *link,
        smc_lgr_forget(lgr);
        if (lgr->role == SMC_SERV) {
                /* client asks to delete this link, send request */
-               smc_llc_prep_delete_link(llc, link, SMC_LLC_REQ, true);
+               smc_llc_send_delete_link(link, 0, SMC_LLC_REQ, true,
+                                        SMC_LLC_DEL_PROG_INIT_TERM);
        } else {
                /* server requests to delete this link, send response */
-               smc_llc_prep_delete_link(llc, link, SMC_LLC_RESP, true);
+               smc_llc_send_delete_link(link, 0, SMC_LLC_RESP, true,
+                                        SMC_LLC_DEL_PROG_INIT_TERM);
        }
-       smc_llc_send_message(link, llc);
        smc_lgr_terminate_sched(lgr);
 }
 
index 48029a5e14c3aa6a0f9414fbe2c862b885f3482a..d2c50d3e43a6b26c5cfc9d175bd3d76d154232d6 100644 (file)
@@ -35,6 +35,16 @@ enum smc_llc_msg_type {
        SMC_LLC_DELETE_RKEY             = 0x09,
 };
 
+/* LLC DELETE LINK Request Reason Codes */
+#define SMC_LLC_DEL_LOST_PATH          0x00010000
+#define SMC_LLC_DEL_OP_INIT_TERM       0x00020000
+#define SMC_LLC_DEL_PROG_INIT_TERM     0x00030000
+#define SMC_LLC_DEL_PROT_VIOL          0x00040000
+#define SMC_LLC_DEL_NO_ASYM_NEEDED     0x00050000
+/* LLC DELETE LINK Response Reason Codes */
+#define SMC_LLC_DEL_NOLNK      0x00100000  /* Unknown Link ID (no link) */
+#define SMC_LLC_DEL_NOLGR      0x00200000  /* Unknown Link Group */
+
 /* returns a usable link of the link group, or NULL */
 static inline struct smc_link *smc_llc_usable_link(struct smc_link_group *lgr)
 {
@@ -50,9 +60,11 @@ static inline struct smc_link *smc_llc_usable_link(struct smc_link_group *lgr)
 int smc_llc_send_confirm_link(struct smc_link *lnk,
                              enum smc_llc_reqresp reqresp);
 int smc_llc_send_add_link(struct smc_link *link, u8 mac[], u8 gid[],
+                         struct smc_link *link_new,
                          enum smc_llc_reqresp reqresp);
-int smc_llc_send_delete_link(struct smc_link *link,
-                            enum smc_llc_reqresp reqresp, bool orderly);
+int smc_llc_send_delete_link(struct smc_link *link, u8 link_del_id,
+                            enum smc_llc_reqresp reqresp, bool orderly,
+                            u32 reason);
 void smc_llc_lgr_init(struct smc_link_group *lgr, struct smc_sock *smc);
 void smc_llc_lgr_clear(struct smc_link_group *lgr);
 int smc_llc_link_init(struct smc_link *link);