net/smc: introduce link group termination worker
authorUrsula Braun <ubraun@linux.ibm.com>
Mon, 21 Oct 2019 14:13:14 +0000 (16:13 +0200)
committerJakub Kicinski <jakub.kicinski@netronome.com>
Tue, 22 Oct 2019 18:23:44 +0000 (11:23 -0700)
Use a worker for link group termination to guarantee process context.

Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_llc.c
net/smc/smc_wr.c

index 6faaa38412b1fdc6751e1cd302d41346fc14154e..46d4b944c4c436d940197901e7883aba84ca0018 100644 (file)
@@ -219,6 +219,14 @@ static void smc_lgr_free_work(struct work_struct *work)
        smc_lgr_free(lgr);
 }
 
+static void smc_lgr_terminate_work(struct work_struct *work)
+{
+       struct smc_link_group *lgr = container_of(work, struct smc_link_group,
+                                                 terminate_work);
+
+       smc_lgr_terminate(lgr);
+}
+
 /* create a new SMC link group */
 static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
 {
@@ -258,6 +266,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
        smc_lgr_list.num += SMC_LGR_NUM_INCR;
        memcpy(&lgr->id, (u8 *)&smc_lgr_list.num, SMC_LGR_ID_SIZE);
        INIT_DELAYED_WORK(&lgr->free_work, smc_lgr_free_work);
+       INIT_WORK(&lgr->terminate_work, smc_lgr_terminate_work);
        lgr->conns_all = RB_ROOT;
        if (ini->is_smcd) {
                /* SMC-D specific settings */
index 12c2818b293fa9d4f717e950119ef1a01a9f5696..e6fd1ed42064ccaf0898e32c8ada175bc3216c18 100644 (file)
@@ -202,6 +202,7 @@ struct smc_link_group {
 
        u8                      id[SMC_LGR_ID_SIZE];    /* unique lgr id */
        struct delayed_work     free_work;      /* delayed freeing of an lgr */
+       struct work_struct      terminate_work; /* abnormal lgr termination */
        u8                      sync_err : 1;   /* lgr no longer fits to peer */
        u8                      terminating : 1;/* lgr is terminating */
        u8                      freefast : 1;   /* free worker scheduled fast */
@@ -282,6 +283,12 @@ static inline struct smc_connection *smc_lgr_find_conn(
        return res;
 }
 
+static inline void smc_lgr_terminate_sched(struct smc_link_group *lgr)
+{
+       if (!lgr->terminating)
+               schedule_work(&lgr->terminate_work);
+}
+
 struct smc_sock;
 struct smc_clc_msg_accept_confirm;
 struct smc_clc_msg_local;
index 4fd60c522802949e8b0f6931f911fc445765873b..e1918ffaf1253ee4a08da9aa02f444445e23a53e 100644 (file)
@@ -475,7 +475,7 @@ static void smc_llc_rx_delete_link(struct smc_link *link,
                        smc_llc_prep_delete_link(llc, link, SMC_LLC_RESP, true);
                }
                smc_llc_send_message(link, llc, sizeof(*llc));
-               smc_lgr_schedule_free_work_fast(lgr);
+               smc_lgr_terminate_sched(lgr);
        }
 }
 
index 253aa75dc2b6818c1a9d4646535c51e1e59bc3f3..50743dc56c86364c49821de36d031cb77731d8c5 100644 (file)
@@ -101,7 +101,7 @@ static inline void smc_wr_tx_process_cqe(struct ib_wc *wc)
                        clear_bit(i, link->wr_tx_mask);
                }
                /* terminate connections of this link group abnormally */
-               smc_lgr_terminate(smc_get_lgr(link));
+               smc_lgr_terminate_sched(smc_get_lgr(link));
        }
        if (pnd_snd.handler)
                pnd_snd.handler(&pnd_snd.priv, link, wc->status);
@@ -191,7 +191,7 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
                        SMC_WR_TX_WAIT_FREE_SLOT_TIME);
                if (!rc) {
                        /* timeout - terminate connections */
-                       smc_lgr_terminate(smc_get_lgr(link));
+                       smc_lgr_terminate_sched(smc_get_lgr(link));
                        return -EPIPE;
                }
                if (idx == link->wr_tx_cnt)
@@ -247,7 +247,7 @@ int smc_wr_tx_send(struct smc_link *link, struct smc_wr_tx_pend_priv *priv)
        rc = ib_post_send(link->roce_qp, &link->wr_tx_ibs[pend->idx], NULL);
        if (rc) {
                smc_wr_tx_put_slot(link, priv);
-               smc_lgr_terminate(smc_get_lgr(link));
+               smc_lgr_terminate_sched(smc_get_lgr(link));
        }
        return rc;
 }
@@ -272,7 +272,7 @@ int smc_wr_reg_send(struct smc_link *link, struct ib_mr *mr)
                                              SMC_WR_REG_MR_WAIT_TIME);
        if (!rc) {
                /* timeout - terminate connections */
-               smc_lgr_terminate(smc_get_lgr(link));
+               smc_lgr_terminate_sched(smc_get_lgr(link));
                return -EPIPE;
        }
        if (rc == -ERESTARTSYS)
@@ -373,7 +373,7 @@ static inline void smc_wr_rx_process_cqes(struct ib_wc wc[], int num)
                                /* terminate connections of this link group
                                 * abnormally
                                 */
-                               smc_lgr_terminate(smc_get_lgr(link));
+                               smc_lgr_terminate_sched(smc_get_lgr(link));
                                break;
                        default:
                                smc_wr_rx_post(link); /* refill WR RX */