|
30 | 30 | #define SMC_LGR_FREE_DELAY_SERV (600 * HZ) |
31 | 31 | #define SMC_LGR_FREE_DELAY_CLNT (SMC_LGR_FREE_DELAY_SERV + 10) |
32 | 32 |
|
33 | | -static u32 smc_lgr_num; /* unique link group number */ |
| 33 | +static struct smc_lgr_list smc_lgr_list = { /* established link groups */ |
| 34 | + .lock = __SPIN_LOCK_UNLOCKED(smc_lgr_list.lock), |
| 35 | + .list = LIST_HEAD_INIT(smc_lgr_list.list), |
| 36 | + .num = 0, |
| 37 | +}; |
34 | 38 |
|
35 | 39 | static void smc_buf_free(struct smc_buf_desc *buf_desc, struct smc_link *lnk, |
36 | 40 | bool is_rmb); |
@@ -181,8 +185,8 @@ static int smc_lgr_create(struct smc_sock *smc, |
181 | 185 | INIT_LIST_HEAD(&lgr->sndbufs[i]); |
182 | 186 | INIT_LIST_HEAD(&lgr->rmbs[i]); |
183 | 187 | } |
184 | | - smc_lgr_num += SMC_LGR_NUM_INCR; |
185 | | - memcpy(&lgr->id, (u8 *)&smc_lgr_num, SMC_LGR_ID_SIZE); |
| 188 | + smc_lgr_list.num += SMC_LGR_NUM_INCR; |
| 189 | + memcpy(&lgr->id, (u8 *)&smc_lgr_list.num, SMC_LGR_ID_SIZE); |
186 | 190 | INIT_DELAYED_WORK(&lgr->free_work, smc_lgr_free_work); |
187 | 191 | lgr->conns_all = RB_ROOT; |
188 | 192 |
|
@@ -374,6 +378,18 @@ void smc_lgr_terminate(struct smc_link_group *lgr) |
374 | 378 | smc_lgr_schedule_free_work(lgr); |
375 | 379 | } |
376 | 380 |
|
| 381 | +/* Called when IB port is terminated */ |
| 382 | +void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport) |
| 383 | +{ |
| 384 | + struct smc_link_group *lgr, *l; |
| 385 | + |
| 386 | + list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) { |
| 387 | + if (lgr->lnk[SMC_SINGLE_LINK].smcibdev == smcibdev && |
| 388 | + lgr->lnk[SMC_SINGLE_LINK].ibport == ibport) |
| 389 | + smc_lgr_terminate(lgr); |
| 390 | + } |
| 391 | +} |
| 392 | + |
377 | 393 | /* Determine vlan of internal TCP socket. |
378 | 394 | * @vlan_id: address to store the determined vlan id into |
379 | 395 | */ |
@@ -802,3 +818,21 @@ int smc_rmb_rtoken_handling(struct smc_connection *conn, |
802 | 818 | return conn->rtoken_idx; |
803 | 819 | return 0; |
804 | 820 | } |
| 821 | + |
| 822 | +/* Called (from smc_exit) when module is removed */ |
| 823 | +void smc_core_exit(void) |
| 824 | +{ |
| 825 | + struct smc_link_group *lgr, *lg; |
| 826 | + LIST_HEAD(lgr_freeing_list); |
| 827 | + |
| 828 | + spin_lock_bh(&smc_lgr_list.lock); |
| 829 | + if (!list_empty(&smc_lgr_list.list)) |
| 830 | + list_splice_init(&smc_lgr_list.list, &lgr_freeing_list); |
| 831 | + spin_unlock_bh(&smc_lgr_list.lock); |
| 832 | + list_for_each_entry_safe(lgr, lg, &lgr_freeing_list, list) { |
| 833 | + list_del_init(&lgr->list); |
| 834 | + smc_llc_link_inactive(&lgr->lnk[SMC_SINGLE_LINK]); |
| 835 | + cancel_delayed_work_sync(&lgr->free_work); |
| 836 | + smc_lgr_free(lgr); /* free link group */ |
| 837 | + } |
| 838 | +} |
0 commit comments