Commit b51fa1b1 authored by Stefan Raspl's avatar Stefan Raspl Committed by David S. Miller

smc: make smc_rx_wait_data() generic

Turn smc_rx_wait_data into a generic function that can be used at various
instances to wait on traffic to complete with varying criteria.
Signed-off-by: default avatarStefan Raspl <raspl@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com><
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c8b8ec8e
...@@ -1089,7 +1089,7 @@ static int smc_accept(struct socket *sock, struct socket *new_sock, ...@@ -1089,7 +1089,7 @@ static int smc_accept(struct socket *sock, struct socket *new_sock,
release_sock(clcsk); release_sock(clcsk);
} else if (!atomic_read(&smc_sk(nsk)->conn.bytes_to_rcv)) { } else if (!atomic_read(&smc_sk(nsk)->conn.bytes_to_rcv)) {
lock_sock(nsk); lock_sock(nsk);
smc_rx_wait_data(smc_sk(nsk), &timeo); smc_rx_wait(smc_sk(nsk), &timeo, smc_rx_data_available);
release_sock(nsk); release_sock(nsk);
} }
} }
......
...@@ -22,11 +22,10 @@ ...@@ -22,11 +22,10 @@
#include "smc_tx.h" /* smc_tx_consumer_update() */ #include "smc_tx.h" /* smc_tx_consumer_update() */
#include "smc_rx.h" #include "smc_rx.h"
/* callback implementation for sk.sk_data_ready() /* callback implementation to wakeup consumers blocked with smc_rx_wait().
* to wakeup rcvbuf consumers that blocked with smc_rx_wait_data().
* indirectly called by smc_cdc_msg_recv_action(). * indirectly called by smc_cdc_msg_recv_action().
*/ */
static void smc_rx_data_ready(struct sock *sk) static void smc_rx_wake_up(struct sock *sk)
{ {
struct socket_wq *wq; struct socket_wq *wq;
...@@ -47,25 +46,27 @@ static void smc_rx_data_ready(struct sock *sk) ...@@ -47,25 +46,27 @@ static void smc_rx_data_ready(struct sock *sk)
/* blocks rcvbuf consumer until >=len bytes available or timeout or interrupted /* blocks rcvbuf consumer until >=len bytes available or timeout or interrupted
* @smc smc socket * @smc smc socket
* @timeo pointer to max seconds to wait, pointer to value 0 for no timeout * @timeo pointer to max seconds to wait, pointer to value 0 for no timeout
* @fcrit add'l criterion to evaluate as function pointer
* Returns: * Returns:
* 1 if at least 1 byte available in rcvbuf or if socket error/shutdown. * 1 if at least 1 byte available in rcvbuf or if socket error/shutdown.
* 0 otherwise (nothing in rcvbuf nor timeout, e.g. interrupted). * 0 otherwise (nothing in rcvbuf nor timeout, e.g. interrupted).
*/ */
int smc_rx_wait_data(struct smc_sock *smc, long *timeo) int smc_rx_wait(struct smc_sock *smc, long *timeo,
int (*fcrit)(struct smc_connection *conn))
{ {
DEFINE_WAIT_FUNC(wait, woken_wake_function); DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct smc_connection *conn = &smc->conn; struct smc_connection *conn = &smc->conn;
struct sock *sk = &smc->sk; struct sock *sk = &smc->sk;
int rc; int rc;
if (atomic_read(&conn->bytes_to_rcv)) if (fcrit(conn))
return 1; return 1;
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
add_wait_queue(sk_sleep(sk), &wait); add_wait_queue(sk_sleep(sk), &wait);
rc = sk_wait_event(sk, timeo, rc = sk_wait_event(sk, timeo,
sk->sk_err || sk->sk_err ||
sk->sk_shutdown & RCV_SHUTDOWN || sk->sk_shutdown & RCV_SHUTDOWN ||
atomic_read(&conn->bytes_to_rcv) || fcrit(conn) ||
smc_cdc_rxed_any_close_or_senddone(conn), smc_cdc_rxed_any_close_or_senddone(conn),
&wait); &wait);
remove_wait_queue(sk_sleep(sk), &wait); remove_wait_queue(sk_sleep(sk), &wait);
...@@ -146,14 +147,14 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, size_t len, ...@@ -146,14 +147,14 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, size_t len,
return -EAGAIN; return -EAGAIN;
} }
if (!atomic_read(&conn->bytes_to_rcv)) { if (!smc_rx_data_available(conn)) {
smc_rx_wait_data(smc, &timeo); smc_rx_wait(smc, &timeo, smc_rx_data_available);
continue; continue;
} }
copy: copy:
/* initialize variables for 1st iteration of subsequent loop */ /* initialize variables for 1st iteration of subsequent loop */
/* could be just 1 byte, even after smc_rx_wait_data above */ /* could be just 1 byte, even after waiting on data above */
readable = atomic_read(&conn->bytes_to_rcv); readable = atomic_read(&conn->bytes_to_rcv);
/* not more than what user space asked for */ /* not more than what user space asked for */
copylen = min_t(size_t, read_remaining, readable); copylen = min_t(size_t, read_remaining, readable);
...@@ -213,5 +214,5 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, size_t len, ...@@ -213,5 +214,5 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, size_t len,
/* Initialize receive properties on connection establishment. NB: not __init! */ /* Initialize receive properties on connection establishment. NB: not __init! */
void smc_rx_init(struct smc_sock *smc) void smc_rx_init(struct smc_sock *smc)
{ {
smc->sk.sk_data_ready = smc_rx_data_ready; smc->sk.sk_data_ready = smc_rx_wake_up;
} }
...@@ -20,6 +20,12 @@ ...@@ -20,6 +20,12 @@
void smc_rx_init(struct smc_sock *smc); void smc_rx_init(struct smc_sock *smc);
int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, size_t len, int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, size_t len,
int flags); int flags);
int smc_rx_wait_data(struct smc_sock *smc, long *timeo); int smc_rx_wait(struct smc_sock *smc, long *timeo,
int (*fcrit)(struct smc_connection *conn));
static inline int smc_rx_data_available(struct smc_connection *conn)
{
return atomic_read(&conn->bytes_to_rcv);
}
#endif /* SMC_RX_H */ #endif /* SMC_RX_H */
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