summaryrefslogtreecommitdiffstats
path: root/net/smc
diff options
context:
space:
mode:
authorHans Wippel <hwippel@linux.ibm.com>2018-11-20 10:46:41 -0500
committerDavid S. Miller <davem@davemloft.net>2018-11-21 19:14:56 -0500
commit0512f69e388c963dbe955d4bd9ae0f7d88d2dc54 (patch)
tree38627f33d9ef54a2c83beb2628ec2bbf7c663827 /net/smc
parentee05ff7af26509f39360534a5225ee714416cdfd (diff)
net/smc: add SMC-D shutdown signal
When a SMC-D link group is freed, a shutdown signal should be sent to the peer to indicate that the link group is invalid. This patch adds the shutdown signal to the SMC code. Signed-off-by: Hans Wippel <hwippel@linux.ibm.com> Signed-off-by: Ursula Braun <ubraun@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/smc')
-rw-r--r--net/smc/smc_core.c10
-rw-r--r--net/smc/smc_core.h3
-rw-r--r--net/smc/smc_ism.c43
-rw-r--r--net/smc/smc_ism.h1
4 files changed, 43 insertions, 14 deletions
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
index 3c023de58afd..1c9fa7f0261a 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -184,6 +184,8 @@ free:
184 184
185 if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE) 185 if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE)
186 smc_llc_link_inactive(lnk); 186 smc_llc_link_inactive(lnk);
187 if (lgr->is_smcd)
188 smc_ism_signal_shutdown(lgr);
187 smc_lgr_free(lgr); 189 smc_lgr_free(lgr);
188 } 190 }
189} 191}
@@ -485,7 +487,7 @@ void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport)
485} 487}
486 488
487/* Called when SMC-D device is terminated or peer is lost */ 489/* Called when SMC-D device is terminated or peer is lost */
488void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid) 490void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
489{ 491{
490 struct smc_link_group *lgr, *l; 492 struct smc_link_group *lgr, *l;
491 LIST_HEAD(lgr_free_list); 493 LIST_HEAD(lgr_free_list);
@@ -495,7 +497,7 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
495 list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) { 497 list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) {
496 if (lgr->is_smcd && lgr->smcd == dev && 498 if (lgr->is_smcd && lgr->smcd == dev &&
497 (!peer_gid || lgr->peer_gid == peer_gid) && 499 (!peer_gid || lgr->peer_gid == peer_gid) &&
498 !list_empty(&lgr->list)) { 500 (vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) {
499 __smc_lgr_terminate(lgr); 501 __smc_lgr_terminate(lgr);
500 list_move(&lgr->list, &lgr_free_list); 502 list_move(&lgr->list, &lgr_free_list);
501 } 503 }
@@ -506,6 +508,8 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
506 list_for_each_entry_safe(lgr, l, &lgr_free_list, list) { 508 list_for_each_entry_safe(lgr, l, &lgr_free_list, list) {
507 list_del_init(&lgr->list); 509 list_del_init(&lgr->list);
508 cancel_delayed_work_sync(&lgr->free_work); 510 cancel_delayed_work_sync(&lgr->free_work);
511 if (!peer_gid && vlan == VLAN_VID_MASK) /* dev terminated? */
512 smc_ism_signal_shutdown(lgr);
509 smc_lgr_free(lgr); 513 smc_lgr_free(lgr);
510 } 514 }
511} 515}
@@ -1026,6 +1030,8 @@ void smc_core_exit(void)
1026 smc_llc_link_inactive(lnk); 1030 smc_llc_link_inactive(lnk);
1027 } 1031 }
1028 cancel_delayed_work_sync(&lgr->free_work); 1032 cancel_delayed_work_sync(&lgr->free_work);
1033 if (lgr->is_smcd)
1034 smc_ism_signal_shutdown(lgr);
1029 smc_lgr_free(lgr); /* free link group */ 1035 smc_lgr_free(lgr); /* free link group */
1030 } 1036 }
1031} 1037}
diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h
index 5bc6cbaf0ed5..cf98f4d6093e 100644
--- a/net/smc/smc_core.h
+++ b/net/smc/smc_core.h
@@ -247,7 +247,8 @@ void smc_lgr_free(struct smc_link_group *lgr);
247void smc_lgr_forget(struct smc_link_group *lgr); 247void smc_lgr_forget(struct smc_link_group *lgr);
248void smc_lgr_terminate(struct smc_link_group *lgr); 248void smc_lgr_terminate(struct smc_link_group *lgr);
249void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport); 249void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport);
250void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid); 250void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid,
251 unsigned short vlan);
251int smc_buf_create(struct smc_sock *smc, bool is_smcd); 252int smc_buf_create(struct smc_sock *smc, bool is_smcd);
252int smc_uncompress_bufsize(u8 compressed); 253int smc_uncompress_bufsize(u8 compressed);
253int smc_rmb_rtoken_handling(struct smc_connection *conn, 254int smc_rmb_rtoken_handling(struct smc_connection *conn,
diff --git a/net/smc/smc_ism.c b/net/smc/smc_ism.c
index e36f21ce7252..2fff79db1a59 100644
--- a/net/smc/smc_ism.c
+++ b/net/smc/smc_ism.c
@@ -187,22 +187,28 @@ struct smc_ism_event_work {
187#define ISM_EVENT_REQUEST 0x0001 187#define ISM_EVENT_REQUEST 0x0001
188#define ISM_EVENT_RESPONSE 0x0002 188#define ISM_EVENT_RESPONSE 0x0002
189#define ISM_EVENT_REQUEST_IR 0x00000001 189#define ISM_EVENT_REQUEST_IR 0x00000001
190#define ISM_EVENT_CODE_SHUTDOWN 0x80
190#define ISM_EVENT_CODE_TESTLINK 0x83 191#define ISM_EVENT_CODE_TESTLINK 0x83
191 192
193union smcd_sw_event_info {
194 u64 info;
195 struct {
196 u8 uid[SMC_LGR_ID_SIZE];
197 unsigned short vlan_id;
198 u16 code;
199 };
200};
201
192static void smcd_handle_sw_event(struct smc_ism_event_work *wrk) 202static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
193{ 203{
194 union { 204 union smcd_sw_event_info ev_info;
195 u64 info;
196 struct {
197 u32 uid;
198 unsigned short vlanid;
199 u16 code;
200 };
201 } ev_info;
202 205
206 ev_info.info = wrk->event.info;
203 switch (wrk->event.code) { 207 switch (wrk->event.code) {
208 case ISM_EVENT_CODE_SHUTDOWN: /* Peer shut down DMBs */
209 smc_smcd_terminate(wrk->smcd, wrk->event.tok, ev_info.vlan_id);
210 break;
204 case ISM_EVENT_CODE_TESTLINK: /* Activity timer */ 211 case ISM_EVENT_CODE_TESTLINK: /* Activity timer */
205 ev_info.info = wrk->event.info;
206 if (ev_info.code == ISM_EVENT_REQUEST) { 212 if (ev_info.code == ISM_EVENT_REQUEST) {
207 ev_info.code = ISM_EVENT_RESPONSE; 213 ev_info.code = ISM_EVENT_RESPONSE;
208 wrk->smcd->ops->signal_event(wrk->smcd, 214 wrk->smcd->ops->signal_event(wrk->smcd,
@@ -215,6 +221,21 @@ static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
215 } 221 }
216} 222}
217 223
224int smc_ism_signal_shutdown(struct smc_link_group *lgr)
225{
226 int rc;
227 union smcd_sw_event_info ev_info;
228
229 memcpy(ev_info.uid, lgr->id, SMC_LGR_ID_SIZE);
230 ev_info.vlan_id = lgr->vlan_id;
231 ev_info.code = ISM_EVENT_REQUEST;
232 rc = lgr->smcd->ops->signal_event(lgr->smcd, lgr->peer_gid,
233 ISM_EVENT_REQUEST_IR,
234 ISM_EVENT_CODE_SHUTDOWN,
235 ev_info.info);
236 return rc;
237}
238
218/* worker for SMC-D events */ 239/* worker for SMC-D events */
219static void smc_ism_event_work(struct work_struct *work) 240static void smc_ism_event_work(struct work_struct *work)
220{ 241{
@@ -223,7 +244,7 @@ static void smc_ism_event_work(struct work_struct *work)
223 244
224 switch (wrk->event.type) { 245 switch (wrk->event.type) {
225 case ISM_EVENT_GID: /* GID event, token is peer GID */ 246 case ISM_EVENT_GID: /* GID event, token is peer GID */
226 smc_smcd_terminate(wrk->smcd, wrk->event.tok); 247 smc_smcd_terminate(wrk->smcd, wrk->event.tok, VLAN_VID_MASK);
227 break; 248 break;
228 case ISM_EVENT_DMB: 249 case ISM_EVENT_DMB:
229 break; 250 break;
@@ -289,7 +310,7 @@ void smcd_unregister_dev(struct smcd_dev *smcd)
289 spin_unlock(&smcd_dev_list.lock); 310 spin_unlock(&smcd_dev_list.lock);
290 flush_workqueue(smcd->event_wq); 311 flush_workqueue(smcd->event_wq);
291 destroy_workqueue(smcd->event_wq); 312 destroy_workqueue(smcd->event_wq);
292 smc_smcd_terminate(smcd, 0); 313 smc_smcd_terminate(smcd, 0, VLAN_VID_MASK);
293 314
294 device_del(&smcd->dev); 315 device_del(&smcd->dev);
295} 316}
diff --git a/net/smc/smc_ism.h b/net/smc/smc_ism.h
index aee45b860b79..4da946cbfa29 100644
--- a/net/smc/smc_ism.h
+++ b/net/smc/smc_ism.h
@@ -45,4 +45,5 @@ int smc_ism_register_dmb(struct smc_link_group *lgr, int buf_size,
45int smc_ism_unregister_dmb(struct smcd_dev *dev, struct smc_buf_desc *dmb_desc); 45int smc_ism_unregister_dmb(struct smcd_dev *dev, struct smc_buf_desc *dmb_desc);
46int smc_ism_write(struct smcd_dev *dev, const struct smc_ism_position *pos, 46int smc_ism_write(struct smcd_dev *dev, const struct smc_ism_position *pos,
47 void *data, size_t len); 47 void *data, size_t len);
48int smc_ism_signal_shutdown(struct smc_link_group *lgr);
48#endif 49#endif