diff options
Diffstat (limited to 'net/smc')
-rw-r--r-- | net/smc/af_smc.c | 11 | ||||
-rw-r--r-- | net/smc/smc_cdc.c | 26 | ||||
-rw-r--r-- | net/smc/smc_cdc.h | 60 | ||||
-rw-r--r-- | net/smc/smc_core.c | 20 | ||||
-rw-r--r-- | net/smc/smc_core.h | 5 | ||||
-rw-r--r-- | net/smc/smc_ism.c | 43 | ||||
-rw-r--r-- | net/smc/smc_ism.h | 1 | ||||
-rw-r--r-- | net/smc/smc_wr.c | 4 |
8 files changed, 120 insertions, 50 deletions
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 4b865250e238..63f08b4e51d6 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c | |||
@@ -127,6 +127,8 @@ static int smc_release(struct socket *sock) | |||
127 | smc = smc_sk(sk); | 127 | smc = smc_sk(sk); |
128 | 128 | ||
129 | /* cleanup for a dangling non-blocking connect */ | 129 | /* cleanup for a dangling non-blocking connect */ |
130 | if (smc->connect_info && sk->sk_state == SMC_INIT) | ||
131 | tcp_abort(smc->clcsock->sk, ECONNABORTED); | ||
130 | flush_work(&smc->connect_work); | 132 | flush_work(&smc->connect_work); |
131 | kfree(smc->connect_info); | 133 | kfree(smc->connect_info); |
132 | smc->connect_info = NULL; | 134 | smc->connect_info = NULL; |
@@ -551,7 +553,8 @@ static int smc_connect_rdma(struct smc_sock *smc, | |||
551 | 553 | ||
552 | mutex_lock(&smc_create_lgr_pending); | 554 | mutex_lock(&smc_create_lgr_pending); |
553 | local_contact = smc_conn_create(smc, false, aclc->hdr.flag, ibdev, | 555 | local_contact = smc_conn_create(smc, false, aclc->hdr.flag, ibdev, |
554 | ibport, &aclc->lcl, NULL, 0); | 556 | ibport, ntoh24(aclc->qpn), &aclc->lcl, |
557 | NULL, 0); | ||
555 | if (local_contact < 0) { | 558 | if (local_contact < 0) { |
556 | if (local_contact == -ENOMEM) | 559 | if (local_contact == -ENOMEM) |
557 | reason_code = SMC_CLC_DECL_MEM;/* insufficient memory*/ | 560 | reason_code = SMC_CLC_DECL_MEM;/* insufficient memory*/ |
@@ -621,7 +624,7 @@ static int smc_connect_ism(struct smc_sock *smc, | |||
621 | int rc = 0; | 624 | int rc = 0; |
622 | 625 | ||
623 | mutex_lock(&smc_create_lgr_pending); | 626 | mutex_lock(&smc_create_lgr_pending); |
624 | local_contact = smc_conn_create(smc, true, aclc->hdr.flag, NULL, 0, | 627 | local_contact = smc_conn_create(smc, true, aclc->hdr.flag, NULL, 0, 0, |
625 | NULL, ismdev, aclc->gid); | 628 | NULL, ismdev, aclc->gid); |
626 | if (local_contact < 0) | 629 | if (local_contact < 0) |
627 | return smc_connect_abort(smc, SMC_CLC_DECL_MEM, 0); | 630 | return smc_connect_abort(smc, SMC_CLC_DECL_MEM, 0); |
@@ -1086,7 +1089,7 @@ static int smc_listen_rdma_init(struct smc_sock *new_smc, | |||
1086 | int *local_contact) | 1089 | int *local_contact) |
1087 | { | 1090 | { |
1088 | /* allocate connection / link group */ | 1091 | /* allocate connection / link group */ |
1089 | *local_contact = smc_conn_create(new_smc, false, 0, ibdev, ibport, | 1092 | *local_contact = smc_conn_create(new_smc, false, 0, ibdev, ibport, 0, |
1090 | &pclc->lcl, NULL, 0); | 1093 | &pclc->lcl, NULL, 0); |
1091 | if (*local_contact < 0) { | 1094 | if (*local_contact < 0) { |
1092 | if (*local_contact == -ENOMEM) | 1095 | if (*local_contact == -ENOMEM) |
@@ -1110,7 +1113,7 @@ static int smc_listen_ism_init(struct smc_sock *new_smc, | |||
1110 | struct smc_clc_msg_smcd *pclc_smcd; | 1113 | struct smc_clc_msg_smcd *pclc_smcd; |
1111 | 1114 | ||
1112 | pclc_smcd = smc_get_clc_msg_smcd(pclc); | 1115 | pclc_smcd = smc_get_clc_msg_smcd(pclc); |
1113 | *local_contact = smc_conn_create(new_smc, true, 0, NULL, 0, NULL, | 1116 | *local_contact = smc_conn_create(new_smc, true, 0, NULL, 0, 0, NULL, |
1114 | ismdev, pclc_smcd->gid); | 1117 | ismdev, pclc_smcd->gid); |
1115 | if (*local_contact < 0) { | 1118 | if (*local_contact < 0) { |
1116 | if (*local_contact == -ENOMEM) | 1119 | if (*local_contact == -ENOMEM) |
diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c index ed5dcf03fe0b..db83332ac1c8 100644 --- a/net/smc/smc_cdc.c +++ b/net/smc/smc_cdc.c | |||
@@ -81,7 +81,7 @@ static inline void smc_cdc_add_pending_send(struct smc_connection *conn, | |||
81 | sizeof(struct smc_cdc_msg) > SMC_WR_BUF_SIZE, | 81 | sizeof(struct smc_cdc_msg) > SMC_WR_BUF_SIZE, |
82 | "must increase SMC_WR_BUF_SIZE to at least sizeof(struct smc_cdc_msg)"); | 82 | "must increase SMC_WR_BUF_SIZE to at least sizeof(struct smc_cdc_msg)"); |
83 | BUILD_BUG_ON_MSG( | 83 | BUILD_BUG_ON_MSG( |
84 | sizeof(struct smc_cdc_msg) != SMC_WR_TX_SIZE, | 84 | offsetofend(struct smc_cdc_msg, reserved) > SMC_WR_TX_SIZE, |
85 | "must adapt SMC_WR_TX_SIZE to sizeof(struct smc_cdc_msg); if not all smc_wr upper layer protocols use the same message size any more, must start to set link->wr_tx_sges[i].length on each individual smc_wr_tx_send()"); | 85 | "must adapt SMC_WR_TX_SIZE to sizeof(struct smc_cdc_msg); if not all smc_wr upper layer protocols use the same message size any more, must start to set link->wr_tx_sges[i].length on each individual smc_wr_tx_send()"); |
86 | BUILD_BUG_ON_MSG( | 86 | BUILD_BUG_ON_MSG( |
87 | sizeof(struct smc_cdc_tx_pend) > SMC_WR_TX_PEND_PRIV_SIZE, | 87 | sizeof(struct smc_cdc_tx_pend) > SMC_WR_TX_PEND_PRIV_SIZE, |
@@ -177,23 +177,24 @@ void smc_cdc_tx_dismiss_slots(struct smc_connection *conn) | |||
177 | int smcd_cdc_msg_send(struct smc_connection *conn) | 177 | int smcd_cdc_msg_send(struct smc_connection *conn) |
178 | { | 178 | { |
179 | struct smc_sock *smc = container_of(conn, struct smc_sock, conn); | 179 | struct smc_sock *smc = container_of(conn, struct smc_sock, conn); |
180 | union smc_host_cursor curs; | ||
180 | struct smcd_cdc_msg cdc; | 181 | struct smcd_cdc_msg cdc; |
181 | int rc, diff; | 182 | int rc, diff; |
182 | 183 | ||
183 | memset(&cdc, 0, sizeof(cdc)); | 184 | memset(&cdc, 0, sizeof(cdc)); |
184 | cdc.common.type = SMC_CDC_MSG_TYPE; | 185 | cdc.common.type = SMC_CDC_MSG_TYPE; |
185 | cdc.prod_wrap = conn->local_tx_ctrl.prod.wrap; | 186 | curs.acurs.counter = atomic64_read(&conn->local_tx_ctrl.prod.acurs); |
186 | cdc.prod_count = conn->local_tx_ctrl.prod.count; | 187 | cdc.prod.wrap = curs.wrap; |
187 | 188 | cdc.prod.count = curs.count; | |
188 | cdc.cons_wrap = conn->local_tx_ctrl.cons.wrap; | 189 | curs.acurs.counter = atomic64_read(&conn->local_tx_ctrl.cons.acurs); |
189 | cdc.cons_count = conn->local_tx_ctrl.cons.count; | 190 | cdc.cons.wrap = curs.wrap; |
190 | cdc.prod_flags = conn->local_tx_ctrl.prod_flags; | 191 | cdc.cons.count = curs.count; |
191 | cdc.conn_state_flags = conn->local_tx_ctrl.conn_state_flags; | 192 | cdc.cons.prod_flags = conn->local_tx_ctrl.prod_flags; |
193 | cdc.cons.conn_state_flags = conn->local_tx_ctrl.conn_state_flags; | ||
192 | rc = smcd_tx_ism_write(conn, &cdc, sizeof(cdc), 0, 1); | 194 | rc = smcd_tx_ism_write(conn, &cdc, sizeof(cdc), 0, 1); |
193 | if (rc) | 195 | if (rc) |
194 | return rc; | 196 | return rc; |
195 | smc_curs_copy(&conn->rx_curs_confirmed, &conn->local_tx_ctrl.cons, | 197 | smc_curs_copy(&conn->rx_curs_confirmed, &curs, conn); |
196 | conn); | ||
197 | /* Calculate transmitted data and increment free send buffer space */ | 198 | /* Calculate transmitted data and increment free send buffer space */ |
198 | diff = smc_curs_diff(conn->sndbuf_desc->len, &conn->tx_curs_fin, | 199 | diff = smc_curs_diff(conn->sndbuf_desc->len, &conn->tx_curs_fin, |
199 | &conn->tx_curs_sent); | 200 | &conn->tx_curs_sent); |
@@ -331,13 +332,16 @@ static void smc_cdc_msg_recv(struct smc_sock *smc, struct smc_cdc_msg *cdc) | |||
331 | static void smcd_cdc_rx_tsklet(unsigned long data) | 332 | static void smcd_cdc_rx_tsklet(unsigned long data) |
332 | { | 333 | { |
333 | struct smc_connection *conn = (struct smc_connection *)data; | 334 | struct smc_connection *conn = (struct smc_connection *)data; |
335 | struct smcd_cdc_msg *data_cdc; | ||
334 | struct smcd_cdc_msg cdc; | 336 | struct smcd_cdc_msg cdc; |
335 | struct smc_sock *smc; | 337 | struct smc_sock *smc; |
336 | 338 | ||
337 | if (!conn) | 339 | if (!conn) |
338 | return; | 340 | return; |
339 | 341 | ||
340 | memcpy(&cdc, conn->rmb_desc->cpu_addr, sizeof(cdc)); | 342 | data_cdc = (struct smcd_cdc_msg *)conn->rmb_desc->cpu_addr; |
343 | smcd_curs_copy(&cdc.prod, &data_cdc->prod, conn); | ||
344 | smcd_curs_copy(&cdc.cons, &data_cdc->cons, conn); | ||
341 | smc = container_of(conn, struct smc_sock, conn); | 345 | smc = container_of(conn, struct smc_sock, conn); |
342 | smc_cdc_msg_recv(smc, (struct smc_cdc_msg *)&cdc); | 346 | smc_cdc_msg_recv(smc, (struct smc_cdc_msg *)&cdc); |
343 | } | 347 | } |
diff --git a/net/smc/smc_cdc.h b/net/smc/smc_cdc.h index 934df4473a7c..b5bfe38c7f9b 100644 --- a/net/smc/smc_cdc.h +++ b/net/smc/smc_cdc.h | |||
@@ -48,21 +48,31 @@ struct smc_cdc_msg { | |||
48 | struct smc_cdc_producer_flags prod_flags; | 48 | struct smc_cdc_producer_flags prod_flags; |
49 | struct smc_cdc_conn_state_flags conn_state_flags; | 49 | struct smc_cdc_conn_state_flags conn_state_flags; |
50 | u8 reserved[18]; | 50 | u8 reserved[18]; |
51 | } __packed; /* format defined in RFC7609 */ | 51 | }; |
52 | |||
53 | /* SMC-D cursor format */ | ||
54 | union smcd_cdc_cursor { | ||
55 | struct { | ||
56 | u16 wrap; | ||
57 | u32 count; | ||
58 | struct smc_cdc_producer_flags prod_flags; | ||
59 | struct smc_cdc_conn_state_flags conn_state_flags; | ||
60 | } __packed; | ||
61 | #ifdef KERNEL_HAS_ATOMIC64 | ||
62 | atomic64_t acurs; /* for atomic processing */ | ||
63 | #else | ||
64 | u64 acurs; /* for atomic processing */ | ||
65 | #endif | ||
66 | } __aligned(8); | ||
52 | 67 | ||
53 | /* CDC message for SMC-D */ | 68 | /* CDC message for SMC-D */ |
54 | struct smcd_cdc_msg { | 69 | struct smcd_cdc_msg { |
55 | struct smc_wr_rx_hdr common; /* Type = 0xFE */ | 70 | struct smc_wr_rx_hdr common; /* Type = 0xFE */ |
56 | u8 res1[7]; | 71 | u8 res1[7]; |
57 | u16 prod_wrap; | 72 | union smcd_cdc_cursor prod; |
58 | u32 prod_count; | 73 | union smcd_cdc_cursor cons; |
59 | u8 res2[2]; | ||
60 | u16 cons_wrap; | ||
61 | u32 cons_count; | ||
62 | struct smc_cdc_producer_flags prod_flags; | ||
63 | struct smc_cdc_conn_state_flags conn_state_flags; | ||
64 | u8 res3[8]; | 74 | u8 res3[8]; |
65 | } __packed; | 75 | } __aligned(8); |
66 | 76 | ||
67 | static inline bool smc_cdc_rxed_any_close(struct smc_connection *conn) | 77 | static inline bool smc_cdc_rxed_any_close(struct smc_connection *conn) |
68 | { | 78 | { |
@@ -135,6 +145,21 @@ static inline void smc_curs_copy_net(union smc_cdc_cursor *tgt, | |||
135 | #endif | 145 | #endif |
136 | } | 146 | } |
137 | 147 | ||
148 | static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt, | ||
149 | union smcd_cdc_cursor *src, | ||
150 | struct smc_connection *conn) | ||
151 | { | ||
152 | #ifndef KERNEL_HAS_ATOMIC64 | ||
153 | unsigned long flags; | ||
154 | |||
155 | spin_lock_irqsave(&conn->acurs_lock, flags); | ||
156 | tgt->acurs = src->acurs; | ||
157 | spin_unlock_irqrestore(&conn->acurs_lock, flags); | ||
158 | #else | ||
159 | atomic64_set(&tgt->acurs, atomic64_read(&src->acurs)); | ||
160 | #endif | ||
161 | } | ||
162 | |||
138 | /* calculate cursor difference between old and new, where old <= new */ | 163 | /* calculate cursor difference between old and new, where old <= new */ |
139 | static inline int smc_curs_diff(unsigned int size, | 164 | static inline int smc_curs_diff(unsigned int size, |
140 | union smc_host_cursor *old, | 165 | union smc_host_cursor *old, |
@@ -222,12 +247,17 @@ static inline void smcr_cdc_msg_to_host(struct smc_host_cdc_msg *local, | |||
222 | static inline void smcd_cdc_msg_to_host(struct smc_host_cdc_msg *local, | 247 | static inline void smcd_cdc_msg_to_host(struct smc_host_cdc_msg *local, |
223 | struct smcd_cdc_msg *peer) | 248 | struct smcd_cdc_msg *peer) |
224 | { | 249 | { |
225 | local->prod.wrap = peer->prod_wrap; | 250 | union smc_host_cursor temp; |
226 | local->prod.count = peer->prod_count; | 251 | |
227 | local->cons.wrap = peer->cons_wrap; | 252 | temp.wrap = peer->prod.wrap; |
228 | local->cons.count = peer->cons_count; | 253 | temp.count = peer->prod.count; |
229 | local->prod_flags = peer->prod_flags; | 254 | atomic64_set(&local->prod.acurs, atomic64_read(&temp.acurs)); |
230 | local->conn_state_flags = peer->conn_state_flags; | 255 | |
256 | temp.wrap = peer->cons.wrap; | ||
257 | temp.count = peer->cons.count; | ||
258 | atomic64_set(&local->cons.acurs, atomic64_read(&temp.acurs)); | ||
259 | local->prod_flags = peer->cons.prod_flags; | ||
260 | local->conn_state_flags = peer->cons.conn_state_flags; | ||
231 | } | 261 | } |
232 | 262 | ||
233 | static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local, | 263 | static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local, |
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index 1382ddae591e..35c1cdc93e1c 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c | |||
@@ -189,6 +189,8 @@ free: | |||
189 | 189 | ||
190 | if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE) | 190 | if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE) |
191 | smc_llc_link_inactive(lnk); | 191 | smc_llc_link_inactive(lnk); |
192 | if (lgr->is_smcd) | ||
193 | smc_ism_signal_shutdown(lgr); | ||
192 | smc_lgr_free(lgr); | 194 | smc_lgr_free(lgr); |
193 | } | 195 | } |
194 | } | 196 | } |
@@ -495,7 +497,7 @@ void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport) | |||
495 | } | 497 | } |
496 | 498 | ||
497 | /* Called when SMC-D device is terminated or peer is lost */ | 499 | /* Called when SMC-D device is terminated or peer is lost */ |
498 | void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid) | 500 | void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan) |
499 | { | 501 | { |
500 | struct smc_link_group *lgr, *l; | 502 | struct smc_link_group *lgr, *l; |
501 | LIST_HEAD(lgr_free_list); | 503 | LIST_HEAD(lgr_free_list); |
@@ -505,7 +507,7 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid) | |||
505 | list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) { | 507 | list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) { |
506 | if (lgr->is_smcd && lgr->smcd == dev && | 508 | if (lgr->is_smcd && lgr->smcd == dev && |
507 | (!peer_gid || lgr->peer_gid == peer_gid) && | 509 | (!peer_gid || lgr->peer_gid == peer_gid) && |
508 | !list_empty(&lgr->list)) { | 510 | (vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) { |
509 | __smc_lgr_terminate(lgr); | 511 | __smc_lgr_terminate(lgr); |
510 | list_move(&lgr->list, &lgr_free_list); | 512 | list_move(&lgr->list, &lgr_free_list); |
511 | } | 513 | } |
@@ -516,6 +518,8 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid) | |||
516 | list_for_each_entry_safe(lgr, l, &lgr_free_list, list) { | 518 | list_for_each_entry_safe(lgr, l, &lgr_free_list, list) { |
517 | list_del_init(&lgr->list); | 519 | list_del_init(&lgr->list); |
518 | cancel_delayed_work_sync(&lgr->free_work); | 520 | cancel_delayed_work_sync(&lgr->free_work); |
521 | if (!peer_gid && vlan == VLAN_VID_MASK) /* dev terminated? */ | ||
522 | smc_ism_signal_shutdown(lgr); | ||
519 | smc_lgr_free(lgr); | 523 | smc_lgr_free(lgr); |
520 | } | 524 | } |
521 | } | 525 | } |
@@ -569,7 +573,7 @@ out: | |||
569 | 573 | ||
570 | static bool smcr_lgr_match(struct smc_link_group *lgr, | 574 | static bool smcr_lgr_match(struct smc_link_group *lgr, |
571 | struct smc_clc_msg_local *lcl, | 575 | struct smc_clc_msg_local *lcl, |
572 | enum smc_lgr_role role) | 576 | enum smc_lgr_role role, u32 clcqpn) |
573 | { | 577 | { |
574 | return !memcmp(lgr->peer_systemid, lcl->id_for_peer, | 578 | return !memcmp(lgr->peer_systemid, lcl->id_for_peer, |
575 | SMC_SYSTEMID_LEN) && | 579 | SMC_SYSTEMID_LEN) && |
@@ -577,7 +581,9 @@ static bool smcr_lgr_match(struct smc_link_group *lgr, | |||
577 | SMC_GID_SIZE) && | 581 | SMC_GID_SIZE) && |
578 | !memcmp(lgr->lnk[SMC_SINGLE_LINK].peer_mac, lcl->mac, | 582 | !memcmp(lgr->lnk[SMC_SINGLE_LINK].peer_mac, lcl->mac, |
579 | sizeof(lcl->mac)) && | 583 | sizeof(lcl->mac)) && |
580 | lgr->role == role; | 584 | lgr->role == role && |
585 | (lgr->role == SMC_SERV || | ||
586 | lgr->lnk[SMC_SINGLE_LINK].peer_qpn == clcqpn); | ||
581 | } | 587 | } |
582 | 588 | ||
583 | static bool smcd_lgr_match(struct smc_link_group *lgr, | 589 | static bool smcd_lgr_match(struct smc_link_group *lgr, |
@@ -588,7 +594,7 @@ static bool smcd_lgr_match(struct smc_link_group *lgr, | |||
588 | 594 | ||
589 | /* create a new SMC connection (and a new link group if necessary) */ | 595 | /* create a new SMC connection (and a new link group if necessary) */ |
590 | int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact, | 596 | int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact, |
591 | struct smc_ib_device *smcibdev, u8 ibport, | 597 | struct smc_ib_device *smcibdev, u8 ibport, u32 clcqpn, |
592 | struct smc_clc_msg_local *lcl, struct smcd_dev *smcd, | 598 | struct smc_clc_msg_local *lcl, struct smcd_dev *smcd, |
593 | u64 peer_gid) | 599 | u64 peer_gid) |
594 | { | 600 | { |
@@ -613,7 +619,7 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact, | |||
613 | list_for_each_entry(lgr, &smc_lgr_list.list, list) { | 619 | list_for_each_entry(lgr, &smc_lgr_list.list, list) { |
614 | write_lock_bh(&lgr->conns_lock); | 620 | write_lock_bh(&lgr->conns_lock); |
615 | if ((is_smcd ? smcd_lgr_match(lgr, smcd, peer_gid) : | 621 | if ((is_smcd ? smcd_lgr_match(lgr, smcd, peer_gid) : |
616 | smcr_lgr_match(lgr, lcl, role)) && | 622 | smcr_lgr_match(lgr, lcl, role, clcqpn)) && |
617 | !lgr->sync_err && | 623 | !lgr->sync_err && |
618 | lgr->vlan_id == vlan_id && | 624 | lgr->vlan_id == vlan_id && |
619 | (role == SMC_CLNT || | 625 | (role == SMC_CLNT || |
@@ -1034,6 +1040,8 @@ void smc_core_exit(void) | |||
1034 | smc_llc_link_inactive(lnk); | 1040 | smc_llc_link_inactive(lnk); |
1035 | } | 1041 | } |
1036 | cancel_delayed_work_sync(&lgr->free_work); | 1042 | cancel_delayed_work_sync(&lgr->free_work); |
1043 | if (lgr->is_smcd) | ||
1044 | smc_ism_signal_shutdown(lgr); | ||
1037 | smc_lgr_free(lgr); /* free link group */ | 1045 | smc_lgr_free(lgr); /* free link group */ |
1038 | } | 1046 | } |
1039 | } | 1047 | } |
diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h index e177c6675038..b00287989a3d 100644 --- a/net/smc/smc_core.h +++ b/net/smc/smc_core.h | |||
@@ -249,7 +249,8 @@ struct smc_clc_msg_local; | |||
249 | void smc_lgr_forget(struct smc_link_group *lgr); | 249 | void smc_lgr_forget(struct smc_link_group *lgr); |
250 | void smc_lgr_terminate(struct smc_link_group *lgr); | 250 | void smc_lgr_terminate(struct smc_link_group *lgr); |
251 | void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport); | 251 | void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport); |
252 | void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid); | 252 | void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, |
253 | unsigned short vlan); | ||
253 | int smc_buf_create(struct smc_sock *smc, bool is_smcd); | 254 | int smc_buf_create(struct smc_sock *smc, bool is_smcd); |
254 | int smc_uncompress_bufsize(u8 compressed); | 255 | int smc_uncompress_bufsize(u8 compressed); |
255 | int smc_rmb_rtoken_handling(struct smc_connection *conn, | 256 | int smc_rmb_rtoken_handling(struct smc_connection *conn, |
@@ -264,7 +265,7 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id); | |||
264 | 265 | ||
265 | void smc_conn_free(struct smc_connection *conn); | 266 | void smc_conn_free(struct smc_connection *conn); |
266 | int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact, | 267 | int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact, |
267 | struct smc_ib_device *smcibdev, u8 ibport, | 268 | struct smc_ib_device *smcibdev, u8 ibport, u32 clcqpn, |
268 | struct smc_clc_msg_local *lcl, struct smcd_dev *smcd, | 269 | struct smc_clc_msg_local *lcl, struct smcd_dev *smcd, |
269 | u64 peer_gid); | 270 | u64 peer_gid); |
270 | void smcd_conn_free(struct smc_connection *conn); | 271 | void smcd_conn_free(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 | ||
193 | union 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 | |||
192 | static void smcd_handle_sw_event(struct smc_ism_event_work *wrk) | 202 | static 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 | ||
224 | int 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 */ |
219 | static void smc_ism_event_work(struct work_struct *work) | 240 | static 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, | |||
45 | int smc_ism_unregister_dmb(struct smcd_dev *dev, struct smc_buf_desc *dmb_desc); | 45 | int smc_ism_unregister_dmb(struct smcd_dev *dev, struct smc_buf_desc *dmb_desc); |
46 | int smc_ism_write(struct smcd_dev *dev, const struct smc_ism_position *pos, | 46 | int 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); |
48 | int smc_ism_signal_shutdown(struct smc_link_group *lgr); | ||
48 | #endif | 49 | #endif |
diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c index 3c458d279855..c2694750a6a8 100644 --- a/net/smc/smc_wr.c +++ b/net/smc/smc_wr.c | |||
@@ -215,12 +215,14 @@ int smc_wr_tx_put_slot(struct smc_link *link, | |||
215 | 215 | ||
216 | pend = container_of(wr_pend_priv, struct smc_wr_tx_pend, priv); | 216 | pend = container_of(wr_pend_priv, struct smc_wr_tx_pend, priv); |
217 | if (pend->idx < link->wr_tx_cnt) { | 217 | if (pend->idx < link->wr_tx_cnt) { |
218 | u32 idx = pend->idx; | ||
219 | |||
218 | /* clear the full struct smc_wr_tx_pend including .priv */ | 220 | /* clear the full struct smc_wr_tx_pend including .priv */ |
219 | memset(&link->wr_tx_pends[pend->idx], 0, | 221 | memset(&link->wr_tx_pends[pend->idx], 0, |
220 | sizeof(link->wr_tx_pends[pend->idx])); | 222 | sizeof(link->wr_tx_pends[pend->idx])); |
221 | memset(&link->wr_tx_bufs[pend->idx], 0, | 223 | memset(&link->wr_tx_bufs[pend->idx], 0, |
222 | sizeof(link->wr_tx_bufs[pend->idx])); | 224 | sizeof(link->wr_tx_bufs[pend->idx])); |
223 | test_and_clear_bit(pend->idx, link->wr_tx_mask); | 225 | test_and_clear_bit(idx, link->wr_tx_mask); |
224 | return 1; | 226 | return 1; |
225 | } | 227 | } |
226 | 228 | ||