net/smc: add new link state and related helpers
authorKarsten Graul <kgraul@linux.ibm.com>
Wed, 29 Apr 2020 15:10:43 +0000 (17:10 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 29 Apr 2020 19:26:32 +0000 (12:26 -0700)
Before a link can be reused it must have been cleared. Lowest current
link state is INACTIVE, which does not mean that the link is already
cleared.
Add a new state UNUSED that is set when the link is cleared and can be
reused.
Add helper smc_llc_usable_link() to find an active link in a link group,
and smc_link_usable() to determine if a link is usable.

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_core.h
net/smc/smc_llc.c
net/smc/smc_llc.h
net/smc/smc_wr.c

index e8897d60b27f2cedd5bc7ce0d0312cc5f4d7a420..57890cbd4e8a0a68e161c1fb7798e7f10382ad4b 100644 (file)
@@ -260,7 +260,7 @@ static void smc_lgr_free_work(struct work_struct *work)
                for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
                        struct smc_link *lnk = &lgr->lnk[i];
 
-                       if (lnk->state != SMC_LNK_INACTIVE)
+                       if (smc_link_usable(lnk))
                                smc_llc_link_inactive(lnk);
                }
        }
@@ -286,7 +286,7 @@ static u8 smcr_next_link_id(struct smc_link_group *lgr)
                if (!link_id)   /* skip zero as link_id */
                        link_id = ++lgr->next_link_id;
                for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
-                       if (lgr->lnk[i].state != SMC_LNK_INACTIVE &&
+                       if (smc_link_usable(&lgr->lnk[i]) &&
                            lgr->lnk[i].link_id == link_id)
                                continue;
                }
@@ -350,6 +350,7 @@ clear_llc_lnk:
 out:
        put_device(&ini->ib_dev->ibdev->dev);
        memset(lnk, 0, sizeof(struct smc_link));
+       lnk->state = SMC_LNK_UNUSED;
        if (!atomic_dec_return(&ini->ib_dev->lnk_cnt))
                wake_up(&ini->ib_dev->lnks_deleted);
        return rc;
@@ -500,6 +501,8 @@ void smc_conn_free(struct smc_connection *conn)
 
 static void smcr_link_clear(struct smc_link *lnk)
 {
+       struct smc_ib_device *smcibdev;
+
        if (lnk->peer_qpn == 0)
                return;
        lnk->peer_qpn = 0;
@@ -510,8 +513,11 @@ static void smcr_link_clear(struct smc_link *lnk)
        smc_ib_dealloc_protection_domain(lnk);
        smc_wr_free_link_mem(lnk);
        put_device(&lnk->smcibdev->ibdev->dev);
-       if (!atomic_dec_return(&lnk->smcibdev->lnk_cnt))
-               wake_up(&lnk->smcibdev->lnks_deleted);
+       smcibdev = lnk->smcibdev;
+       memset(lnk, 0, sizeof(struct smc_link));
+       lnk->state = SMC_LNK_UNUSED;
+       if (!atomic_dec_return(&smcibdev->lnk_cnt))
+               wake_up(&smcibdev->lnks_deleted);
 }
 
 static void smcr_buf_free(struct smc_link_group *lgr, bool is_rmb,
@@ -604,9 +610,8 @@ static void smc_lgr_free(struct smc_link_group *lgr)
                        wake_up(&lgr->smcd->lgrs_deleted);
        } else {
                for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
-                       if (lgr->lnk[i].state == SMC_LNK_INACTIVE)
-                               continue;
-                       smcr_link_clear(&lgr->lnk[i]);
+                       if (lgr->lnk[i].state != SMC_LNK_UNUSED)
+                               smcr_link_clear(&lgr->lnk[i]);
                }
                if (!atomic_dec_return(&lgr_cnt))
                        wake_up(&lgrs_deleted);
@@ -686,7 +691,7 @@ static void smc_lgr_cleanup(struct smc_link_group *lgr)
                for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
                        struct smc_link *lnk = &lgr->lnk[i];
 
-                       if (lnk->state != SMC_LNK_INACTIVE)
+                       if (smc_link_usable(lnk))
                                smc_llc_link_inactive(lnk);
                }
        }
@@ -764,7 +769,7 @@ void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport)
                        continue;
                /* tbd - terminate only when no more links are active */
                for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
-                       if (lgr->lnk[i].state == SMC_LNK_INACTIVE ||
+                       if (!smc_link_usable(&lgr->lnk[i]) ||
                            lgr->lnk[i].state == SMC_LNK_DELETING)
                                continue;
                        if (lgr->lnk[i].smcibdev == smcibdev &&
@@ -1161,8 +1166,7 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr,
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
                struct smc_link *lnk = &lgr->lnk[i];
 
-               if (lnk->state != SMC_LNK_ACTIVE &&
-                   lnk->state != SMC_LNK_ACTIVATING)
+               if (!smc_link_usable(lnk))
                        continue;
                if (smcr_buf_map_link(buf_desc, is_rmb, lnk)) {
                        smcr_buf_unuse(buf_desc, lnk);
@@ -1294,14 +1298,14 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
 
 void smc_sndbuf_sync_sg_for_cpu(struct smc_connection *conn)
 {
-       if (!conn->lgr || conn->lgr->is_smcd)
+       if (!conn->lgr || conn->lgr->is_smcd || !smc_link_usable(conn->lnk))
                return;
        smc_ib_sync_sg_for_cpu(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE);
 }
 
 void smc_sndbuf_sync_sg_for_device(struct smc_connection *conn)
 {
-       if (!conn->lgr || conn->lgr->is_smcd)
+       if (!conn->lgr || conn->lgr->is_smcd || !smc_link_usable(conn->lnk))
                return;
        smc_ib_sync_sg_for_device(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE);
 }
@@ -1313,8 +1317,7 @@ void smc_rmb_sync_sg_for_cpu(struct smc_connection *conn)
        if (!conn->lgr || conn->lgr->is_smcd)
                return;
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
-               if (conn->lgr->lnk[i].state != SMC_LNK_ACTIVE &&
-                   conn->lgr->lnk[i].state != SMC_LNK_ACTIVATING)
+               if (!smc_link_usable(&conn->lgr->lnk[i]))
                        continue;
                smc_ib_sync_sg_for_cpu(&conn->lgr->lnk[i], conn->rmb_desc,
                                       DMA_FROM_DEVICE);
@@ -1328,8 +1331,7 @@ void smc_rmb_sync_sg_for_device(struct smc_connection *conn)
        if (!conn->lgr || conn->lgr->is_smcd)
                return;
        for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
-               if (conn->lgr->lnk[i].state != SMC_LNK_ACTIVE &&
-                   conn->lgr->lnk[i].state != SMC_LNK_ACTIVATING)
+               if (!smc_link_usable(&conn->lgr->lnk[i]))
                        continue;
                smc_ib_sync_sg_for_device(&conn->lgr->lnk[i], conn->rmb_desc,
                                          DMA_FROM_DEVICE);
index f68ba187ecf8c16f7ced0b2243453ed150e2e080..2b1960c8c8ce08b18fac325a75b5a3922b1a967d 100644 (file)
@@ -32,6 +32,7 @@ enum smc_lgr_role {           /* possible roles of a link group */
 };
 
 enum smc_link_state {                  /* possible states of a link */
+       SMC_LNK_UNUSED,         /* link is unused */
        SMC_LNK_INACTIVE,       /* link is inactive */
        SMC_LNK_ACTIVATING,     /* link is being activated */
        SMC_LNK_ACTIVE,         /* link is active */
@@ -295,6 +296,14 @@ static inline struct smc_connection *smc_lgr_find_conn(
        return res;
 }
 
+/* returns true if the specified link is usable */
+static inline bool smc_link_usable(struct smc_link *lnk)
+{
+       if (lnk->state == SMC_LNK_UNUSED || lnk->state == SMC_LNK_INACTIVE)
+               return false;
+       return true;
+}
+
 struct smc_sock;
 struct smc_clc_msg_accept_confirm;
 struct smc_clc_msg_local;
index 903ae068da3a08f04b952e7c7304b9bed2053397..c267f5006faa985d2524861108a50deec3a8d312 100644 (file)
@@ -372,7 +372,7 @@ static void smc_llc_send_message_work(struct work_struct *work)
        struct smc_wr_buf *wr_buf;
        int rc;
 
-       if (llcwrk->link->state == SMC_LNK_INACTIVE)
+       if (!smc_link_usable(llcwrk->link))
                goto out;
        rc = smc_llc_add_pending_send(llcwrk->link, &wr_buf, &pend);
        if (rc)
@@ -562,7 +562,7 @@ static void smc_llc_rx_handler(struct ib_wc *wc, void *buf)
                return; /* short message */
        if (llc->raw.hdr.length != sizeof(*llc))
                return; /* invalid message */
-       if (link->state == SMC_LNK_INACTIVE)
+       if (!smc_link_usable(link))
                return; /* link not active, drop msg */
 
        switch (llc->raw.hdr.common.type) {
index 461c0c3ef76ef9f424c54c86226cbc30bd71faf3..08171131110c8e8b63ece0a7e0bb46c7d981300b 100644 (file)
@@ -35,6 +35,17 @@ enum smc_llc_msg_type {
        SMC_LLC_DELETE_RKEY             = 0x09,
 };
 
+/* returns a usable link of the link group, or NULL */
+static inline struct smc_link *smc_llc_usable_link(struct smc_link_group *lgr)
+{
+       int i;
+
+       for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++)
+               if (smc_link_usable(&lgr->lnk[i]))
+                       return &lgr->lnk[i];
+       return NULL;
+}
+
 /* transmit */
 int smc_llc_send_confirm_link(struct smc_link *lnk,
                              enum smc_llc_reqresp reqresp);
index 337ee52ad3d3cc17fc7267d16e13c068c015deb6..93223628c0023b2a3f572b26167aa347a235cff8 100644 (file)
@@ -207,7 +207,7 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
        } else {
                rc = wait_event_interruptible_timeout(
                        link->wr_tx_wait,
-                       link->state == SMC_LNK_INACTIVE ||
+                       !smc_link_usable(link) ||
                        lgr->terminating ||
                        (smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY),
                        SMC_WR_TX_WAIT_FREE_SLOT_TIME);