Commit f06f095f authored by David S. Miller's avatar David S. Miller

Merge branch 'smc-next'

Ursula Braun says:

====================
net/smc: patches 2019-02-07

here are patches for SMC:
* patches 1, 3, and 6 are cleanups without functional change
* patch 2 postpones closing of internal clcsock
* patches 4 and 5 improve link group creation locking
* patch 7 restores AF_SMC as diag_family field
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents fc4aa1ca 232dc8ef
...@@ -11,13 +11,5 @@ ...@@ -11,13 +11,5 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/types.h> #include <linux/types.h>
#define PNETIDS_LEN 64 /* Total utility string length in bytes
* to cover up to 4 PNETIDs of 16 bytes
* for up to 4 device ports
*/
#define MAX_PNETID_LEN 16 /* Max.length of a single port PNETID */
#define MAX_PNETID_PORTS (PNETIDS_LEN / MAX_PNETID_LEN)
/* Max. # of ports with a PNETID */
int pnet_id_by_dev_port(struct device *dev, unsigned short port, u8 *pnetid); int pnet_id_by_dev_port(struct device *dev, unsigned short port, u8 *pnetid);
#endif /* _ASM_S390_PNET_H */ #endif /* _ASM_S390_PNET_H */
...@@ -13,6 +13,14 @@ ...@@ -13,6 +13,14 @@
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#include <asm/pnet.h> #include <asm/pnet.h>
#define PNETIDS_LEN 64 /* Total utility string length in bytes
* to cover up to 4 PNETIDs of 16 bytes
* for up to 4 device ports
*/
#define MAX_PNETID_LEN 16 /* Max.length of a single port PNETID */
#define MAX_PNETID_PORTS (PNETIDS_LEN / MAX_PNETID_LEN)
/* Max. # of ports with a PNETID */
/* /*
* Get the PNETIDs from a device. * Get the PNETIDs from a device.
* s390 hardware supports the definition of a so-called Physical Network * s390 hardware supports the definition of a so-called Physical Network
......
...@@ -42,8 +42,11 @@ ...@@ -42,8 +42,11 @@
#include "smc_rx.h" #include "smc_rx.h"
#include "smc_close.h" #include "smc_close.h"
static DEFINE_MUTEX(smc_create_lgr_pending); /* serialize link group static DEFINE_MUTEX(smc_server_lgr_pending); /* serialize link group
* creation * creation on server
*/
static DEFINE_MUTEX(smc_client_lgr_pending); /* serialize link group
* creation on client
*/ */
static void smc_tcp_listen_work(struct work_struct *); static void smc_tcp_listen_work(struct work_struct *);
...@@ -145,32 +148,33 @@ static int smc_release(struct socket *sock) ...@@ -145,32 +148,33 @@ static int smc_release(struct socket *sock)
rc = smc_close_active(smc); rc = smc_close_active(smc);
sock_set_flag(sk, SOCK_DEAD); sock_set_flag(sk, SOCK_DEAD);
sk->sk_shutdown |= SHUTDOWN_MASK; sk->sk_shutdown |= SHUTDOWN_MASK;
} } else {
if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT)
sk->sk_prot->unhash(sk); sock_put(sk); /* passive closing */
if (sk->sk_state == SMC_LISTEN) {
if (smc->clcsock) {
if (smc->use_fallback && sk->sk_state == SMC_LISTEN) {
/* wake up clcsock accept */ /* wake up clcsock accept */
rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR); rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR);
} }
mutex_lock(&smc->clcsock_release_lock);
sock_release(smc->clcsock);
smc->clcsock = NULL;
mutex_unlock(&smc->clcsock_release_lock);
}
if (smc->use_fallback) {
if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT)
sock_put(sk); /* passive closing */
sk->sk_state = SMC_CLOSED; sk->sk_state = SMC_CLOSED;
sk->sk_state_change(sk); sk->sk_state_change(sk);
} }
sk->sk_prot->unhash(sk);
if (sk->sk_state == SMC_CLOSED) {
if (smc->clcsock) {
mutex_lock(&smc->clcsock_release_lock);
sock_release(smc->clcsock);
smc->clcsock = NULL;
mutex_unlock(&smc->clcsock_release_lock);
}
if (!smc->use_fallback)
smc_conn_free(&smc->conn);
}
/* detach socket */ /* detach socket */
sock_orphan(sk); sock_orphan(sk);
sock->sk = NULL; sock->sk = NULL;
if (!smc->use_fallback && sk->sk_state == SMC_CLOSED)
smc_conn_free(&smc->conn);
release_sock(sk); release_sock(sk);
sock_put(sk); /* final sock_put */ sock_put(sk); /* final sock_put */
...@@ -476,7 +480,12 @@ static int smc_connect_abort(struct smc_sock *smc, int reason_code, ...@@ -476,7 +480,12 @@ static int smc_connect_abort(struct smc_sock *smc, int reason_code,
{ {
if (local_contact == SMC_FIRST_CONTACT) if (local_contact == SMC_FIRST_CONTACT)
smc_lgr_forget(smc->conn.lgr); smc_lgr_forget(smc->conn.lgr);
mutex_unlock(&smc_create_lgr_pending); if (smc->conn.lgr->is_smcd)
/* there is only one lgr role for SMC-D; use server lock */
mutex_unlock(&smc_server_lgr_pending);
else
mutex_unlock(&smc_client_lgr_pending);
smc_conn_free(&smc->conn); smc_conn_free(&smc->conn);
return reason_code; return reason_code;
} }
...@@ -561,7 +570,7 @@ static int smc_connect_rdma(struct smc_sock *smc, ...@@ -561,7 +570,7 @@ static int smc_connect_rdma(struct smc_sock *smc,
struct smc_link *link; struct smc_link *link;
int reason_code = 0; int reason_code = 0;
mutex_lock(&smc_create_lgr_pending); mutex_lock(&smc_client_lgr_pending);
local_contact = smc_conn_create(smc, false, aclc->hdr.flag, ibdev, local_contact = smc_conn_create(smc, false, aclc->hdr.flag, ibdev,
ibport, ntoh24(aclc->qpn), &aclc->lcl, ibport, ntoh24(aclc->qpn), &aclc->lcl,
NULL, 0); NULL, 0);
...@@ -572,7 +581,8 @@ static int smc_connect_rdma(struct smc_sock *smc, ...@@ -572,7 +581,8 @@ static int smc_connect_rdma(struct smc_sock *smc,
reason_code = SMC_CLC_DECL_SYNCERR; /* synchr. error */ reason_code = SMC_CLC_DECL_SYNCERR; /* synchr. error */
else else
reason_code = SMC_CLC_DECL_INTERR; /* other error */ reason_code = SMC_CLC_DECL_INTERR; /* other error */
return smc_connect_abort(smc, reason_code, 0); mutex_unlock(&smc_client_lgr_pending);
return reason_code;
} }
link = &smc->conn.lgr->lnk[SMC_SINGLE_LINK]; link = &smc->conn.lgr->lnk[SMC_SINGLE_LINK];
...@@ -616,7 +626,7 @@ static int smc_connect_rdma(struct smc_sock *smc, ...@@ -616,7 +626,7 @@ static int smc_connect_rdma(struct smc_sock *smc,
return smc_connect_abort(smc, reason_code, return smc_connect_abort(smc, reason_code,
local_contact); local_contact);
} }
mutex_unlock(&smc_create_lgr_pending); mutex_unlock(&smc_client_lgr_pending);
smc_copy_sock_settings_to_clc(smc); smc_copy_sock_settings_to_clc(smc);
if (smc->sk.sk_state == SMC_INIT) if (smc->sk.sk_state == SMC_INIT)
...@@ -633,11 +643,14 @@ static int smc_connect_ism(struct smc_sock *smc, ...@@ -633,11 +643,14 @@ static int smc_connect_ism(struct smc_sock *smc,
int local_contact = SMC_FIRST_CONTACT; int local_contact = SMC_FIRST_CONTACT;
int rc = 0; int rc = 0;
mutex_lock(&smc_create_lgr_pending); /* there is only one lgr role for SMC-D; use server lock */
mutex_lock(&smc_server_lgr_pending);
local_contact = smc_conn_create(smc, true, aclc->hdr.flag, NULL, 0, 0, local_contact = smc_conn_create(smc, true, aclc->hdr.flag, NULL, 0, 0,
NULL, ismdev, aclc->gid); NULL, ismdev, aclc->gid);
if (local_contact < 0) if (local_contact < 0) {
return smc_connect_abort(smc, SMC_CLC_DECL_MEM, 0); mutex_unlock(&smc_server_lgr_pending);
return SMC_CLC_DECL_MEM;
}
/* Create send and receive buffers */ /* Create send and receive buffers */
if (smc_buf_create(smc, true)) if (smc_buf_create(smc, true))
...@@ -651,7 +664,7 @@ static int smc_connect_ism(struct smc_sock *smc, ...@@ -651,7 +664,7 @@ static int smc_connect_ism(struct smc_sock *smc,
rc = smc_clc_send_confirm(smc); rc = smc_clc_send_confirm(smc);
if (rc) if (rc)
return smc_connect_abort(smc, rc, local_contact); return smc_connect_abort(smc, rc, local_contact);
mutex_unlock(&smc_create_lgr_pending); mutex_unlock(&smc_server_lgr_pending);
smc_copy_sock_settings_to_clc(smc); smc_copy_sock_settings_to_clc(smc);
if (smc->sk.sk_state == SMC_INIT) if (smc->sk.sk_state == SMC_INIT)
...@@ -1250,7 +1263,7 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1250,7 +1263,7 @@ static void smc_listen_work(struct work_struct *work)
return; return;
} }
mutex_lock(&smc_create_lgr_pending); mutex_lock(&smc_server_lgr_pending);
smc_close_init(new_smc); smc_close_init(new_smc);
smc_rx_init(new_smc); smc_rx_init(new_smc);
smc_tx_init(new_smc); smc_tx_init(new_smc);
...@@ -1272,7 +1285,7 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1272,7 +1285,7 @@ static void smc_listen_work(struct work_struct *work)
&local_contact) || &local_contact) ||
smc_listen_rdma_reg(new_smc, local_contact))) { smc_listen_rdma_reg(new_smc, local_contact))) {
/* SMC not supported, decline */ /* SMC not supported, decline */
mutex_unlock(&smc_create_lgr_pending); mutex_unlock(&smc_server_lgr_pending);
smc_listen_decline(new_smc, SMC_CLC_DECL_MODEUNSUPP, smc_listen_decline(new_smc, SMC_CLC_DECL_MODEUNSUPP,
local_contact); local_contact);
return; return;
...@@ -1281,29 +1294,33 @@ static void smc_listen_work(struct work_struct *work) ...@@ -1281,29 +1294,33 @@ static void smc_listen_work(struct work_struct *work)
/* send SMC Accept CLC message */ /* send SMC Accept CLC message */
rc = smc_clc_send_accept(new_smc, local_contact); rc = smc_clc_send_accept(new_smc, local_contact);
if (rc) { if (rc) {
mutex_unlock(&smc_create_lgr_pending); mutex_unlock(&smc_server_lgr_pending);
smc_listen_decline(new_smc, rc, local_contact); smc_listen_decline(new_smc, rc, local_contact);
return; return;
} }
/* SMC-D does not need this lock any more */
if (ism_supported)
mutex_unlock(&smc_server_lgr_pending);
/* receive SMC Confirm CLC message */ /* receive SMC Confirm CLC message */
reason_code = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc), reason_code = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc),
SMC_CLC_CONFIRM, CLC_WAIT_TIME); SMC_CLC_CONFIRM, CLC_WAIT_TIME);
if (reason_code) { if (reason_code) {
mutex_unlock(&smc_create_lgr_pending); if (!ism_supported)
mutex_unlock(&smc_server_lgr_pending);
smc_listen_decline(new_smc, reason_code, local_contact); smc_listen_decline(new_smc, reason_code, local_contact);
return; return;
} }
/* finish worker */ /* finish worker */
if (!ism_supported) { if (!ism_supported) {
if (smc_listen_rdma_finish(new_smc, &cclc, local_contact)) { rc = smc_listen_rdma_finish(new_smc, &cclc, local_contact);
mutex_unlock(&smc_create_lgr_pending); mutex_unlock(&smc_server_lgr_pending);
if (rc)
return; return;
}
} }
smc_conn_save_peer_info(new_smc, &cclc); smc_conn_save_peer_info(new_smc, &cclc);
mutex_unlock(&smc_create_lgr_pending);
smc_listen_out_connected(new_smc); smc_listen_out_connected(new_smc);
} }
......
...@@ -245,17 +245,18 @@ static inline void smcr_cdc_msg_to_host(struct smc_host_cdc_msg *local, ...@@ -245,17 +245,18 @@ static inline void smcr_cdc_msg_to_host(struct smc_host_cdc_msg *local,
} }
static inline void smcd_cdc_msg_to_host(struct smc_host_cdc_msg *local, static inline void smcd_cdc_msg_to_host(struct smc_host_cdc_msg *local,
struct smcd_cdc_msg *peer) struct smcd_cdc_msg *peer,
struct smc_connection *conn)
{ {
union smc_host_cursor temp; union smc_host_cursor temp;
temp.wrap = peer->prod.wrap; temp.wrap = peer->prod.wrap;
temp.count = peer->prod.count; temp.count = peer->prod.count;
atomic64_set(&local->prod.acurs, atomic64_read(&temp.acurs)); smc_curs_copy(&local->prod, &temp, conn);
temp.wrap = peer->cons.wrap; temp.wrap = peer->cons.wrap;
temp.count = peer->cons.count; temp.count = peer->cons.count;
atomic64_set(&local->cons.acurs, atomic64_read(&temp.acurs)); smc_curs_copy(&local->cons, &temp, conn);
local->prod_flags = peer->cons.prod_flags; local->prod_flags = peer->cons.prod_flags;
local->conn_state_flags = peer->cons.conn_state_flags; local->conn_state_flags = peer->cons.conn_state_flags;
} }
...@@ -265,7 +266,7 @@ static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local, ...@@ -265,7 +266,7 @@ static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local,
struct smc_connection *conn) struct smc_connection *conn)
{ {
if (conn->lgr->is_smcd) if (conn->lgr->is_smcd)
smcd_cdc_msg_to_host(local, (struct smcd_cdc_msg *)peer); smcd_cdc_msg_to_host(local, (struct smcd_cdc_msg *)peer, conn);
else else
smcr_cdc_msg_to_host(local, peer, conn); smcr_cdc_msg_to_host(local, peer, conn);
} }
......
...@@ -405,8 +405,13 @@ static void smc_close_passive_work(struct work_struct *work) ...@@ -405,8 +405,13 @@ static void smc_close_passive_work(struct work_struct *work)
if (old_state != sk->sk_state) { if (old_state != sk->sk_state) {
sk->sk_state_change(sk); sk->sk_state_change(sk);
if ((sk->sk_state == SMC_CLOSED) && if ((sk->sk_state == SMC_CLOSED) &&
(sock_flag(sk, SOCK_DEAD) || !sk->sk_socket)) (sock_flag(sk, SOCK_DEAD) || !sk->sk_socket)) {
smc_conn_free(conn); smc_conn_free(conn);
if (smc->clcsock) {
sock_release(smc->clcsock);
smc->clcsock = NULL;
}
}
} }
release_sock(sk); release_sock(sk);
sock_put(sk); /* sock_hold done by schedulers of close_work */ sock_put(sk); /* sock_hold done by schedulers of close_work */
......
...@@ -118,7 +118,6 @@ static void __smc_lgr_unregister_conn(struct smc_connection *conn) ...@@ -118,7 +118,6 @@ static void __smc_lgr_unregister_conn(struct smc_connection *conn)
rb_erase(&conn->alert_node, &lgr->conns_all); rb_erase(&conn->alert_node, &lgr->conns_all);
lgr->conns_num--; lgr->conns_num--;
conn->alert_token_local = 0; conn->alert_token_local = 0;
conn->lgr = NULL;
sock_put(&smc->sk); /* sock_hold in smc_lgr_register_conn() */ sock_put(&smc->sk); /* sock_hold in smc_lgr_register_conn() */
} }
...@@ -331,8 +330,9 @@ void smc_conn_free(struct smc_connection *conn) ...@@ -331,8 +330,9 @@ void smc_conn_free(struct smc_connection *conn)
} else { } else {
smc_cdc_tx_dismiss_slots(conn); smc_cdc_tx_dismiss_slots(conn);
} }
smc_lgr_unregister_conn(conn); /* unsets conn->lgr */ smc_lgr_unregister_conn(conn);
smc_buf_unuse(conn, lgr); /* allow buffer reuse */ smc_buf_unuse(conn, lgr); /* allow buffer reuse */
conn->lgr = NULL;
if (!lgr->conns_num) if (!lgr->conns_num)
smc_lgr_schedule_free_work(lgr); smc_lgr_schedule_free_work(lgr);
...@@ -462,6 +462,7 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr) ...@@ -462,6 +462,7 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr)
sock_hold(&smc->sk); /* sock_put in close work */ sock_hold(&smc->sk); /* sock_put in close work */
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
__smc_lgr_unregister_conn(conn); __smc_lgr_unregister_conn(conn);
conn->lgr = NULL;
write_unlock_bh(&lgr->conns_lock); write_unlock_bh(&lgr->conns_lock);
if (!schedule_work(&conn->close_work)) if (!schedule_work(&conn->close_work))
sock_put(&smc->sk); sock_put(&smc->sk);
......
...@@ -38,6 +38,7 @@ static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) ...@@ -38,6 +38,7 @@ static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk)
{ {
struct smc_sock *smc = smc_sk(sk); struct smc_sock *smc = smc_sk(sk);
r->diag_family = sk->sk_family;
if (!smc->clcsock) if (!smc->clcsock)
return; return;
r->id.idiag_sport = htons(smc->clcsock->sk->sk_num); r->id.idiag_sport = htons(smc->clcsock->sk->sk_num);
...@@ -45,14 +46,12 @@ static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk) ...@@ -45,14 +46,12 @@ static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk)
r->id.idiag_if = smc->clcsock->sk->sk_bound_dev_if; r->id.idiag_if = smc->clcsock->sk->sk_bound_dev_if;
sock_diag_save_cookie(sk, r->id.idiag_cookie); sock_diag_save_cookie(sk, r->id.idiag_cookie);
if (sk->sk_protocol == SMCPROTO_SMC) { if (sk->sk_protocol == SMCPROTO_SMC) {
r->diag_family = PF_INET;
memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src));
memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst));
r->id.idiag_src[0] = smc->clcsock->sk->sk_rcv_saddr; r->id.idiag_src[0] = smc->clcsock->sk->sk_rcv_saddr;
r->id.idiag_dst[0] = smc->clcsock->sk->sk_daddr; r->id.idiag_dst[0] = smc->clcsock->sk->sk_daddr;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
} else if (sk->sk_protocol == SMCPROTO_SMC6) { } else if (sk->sk_protocol == SMCPROTO_SMC6) {
r->diag_family = PF_INET6;
memcpy(&r->id.idiag_src, &smc->clcsock->sk->sk_v6_rcv_saddr, memcpy(&r->id.idiag_src, &smc->clcsock->sk->sk_v6_rcv_saddr,
sizeof(smc->clcsock->sk->sk_v6_rcv_saddr)); sizeof(smc->clcsock->sk->sk_v6_rcv_saddr));
memcpy(&r->id.idiag_dst, &smc->clcsock->sk->sk_v6_daddr, memcpy(&r->id.idiag_dst, &smc->clcsock->sk->sk_v6_daddr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment