diff options
Diffstat (limited to 'net/nfc/llcp/sock.c')
-rw-r--r-- | net/nfc/llcp/sock.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index c13e02ebdef9..3f339b19d140 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -27,6 +27,42 @@ | |||
27 | #include "../nfc.h" | 27 | #include "../nfc.h" |
28 | #include "llcp.h" | 28 | #include "llcp.h" |
29 | 29 | ||
30 | static int sock_wait_state(struct sock *sk, int state, unsigned long timeo) | ||
31 | { | ||
32 | DECLARE_WAITQUEUE(wait, current); | ||
33 | int err = 0; | ||
34 | |||
35 | pr_debug("sk %p", sk); | ||
36 | |||
37 | add_wait_queue(sk_sleep(sk), &wait); | ||
38 | set_current_state(TASK_INTERRUPTIBLE); | ||
39 | |||
40 | while (sk->sk_state != state) { | ||
41 | if (!timeo) { | ||
42 | err = -EINPROGRESS; | ||
43 | break; | ||
44 | } | ||
45 | |||
46 | if (signal_pending(current)) { | ||
47 | err = sock_intr_errno(timeo); | ||
48 | break; | ||
49 | } | ||
50 | |||
51 | release_sock(sk); | ||
52 | timeo = schedule_timeout(timeo); | ||
53 | lock_sock(sk); | ||
54 | set_current_state(TASK_INTERRUPTIBLE); | ||
55 | |||
56 | err = sock_error(sk); | ||
57 | if (err) | ||
58 | break; | ||
59 | } | ||
60 | |||
61 | __set_current_state(TASK_RUNNING); | ||
62 | remove_wait_queue(sk_sleep(sk), &wait); | ||
63 | return err; | ||
64 | } | ||
65 | |||
30 | static struct proto llcp_sock_proto = { | 66 | static struct proto llcp_sock_proto = { |
31 | .name = "NFC_LLCP", | 67 | .name = "NFC_LLCP", |
32 | .owner = THIS_MODULE, | 68 | .owner = THIS_MODULE, |
@@ -304,11 +340,24 @@ static unsigned int llcp_sock_poll(struct file *file, struct socket *sock, | |||
304 | mask |= POLLERR; | 340 | mask |= POLLERR; |
305 | 341 | ||
306 | if (!skb_queue_empty(&sk->sk_receive_queue)) | 342 | if (!skb_queue_empty(&sk->sk_receive_queue)) |
307 | mask |= POLLIN; | 343 | mask |= POLLIN | POLLRDNORM; |
308 | 344 | ||
309 | if (sk->sk_state == LLCP_CLOSED) | 345 | if (sk->sk_state == LLCP_CLOSED) |
310 | mask |= POLLHUP; | 346 | mask |= POLLHUP; |
311 | 347 | ||
348 | if (sk->sk_shutdown & RCV_SHUTDOWN) | ||
349 | mask |= POLLRDHUP | POLLIN | POLLRDNORM; | ||
350 | |||
351 | if (sk->sk_shutdown == SHUTDOWN_MASK) | ||
352 | mask |= POLLHUP; | ||
353 | |||
354 | if (sock_writeable(sk)) | ||
355 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; | ||
356 | else | ||
357 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | ||
358 | |||
359 | pr_debug("mask 0x%x\n", mask); | ||
360 | |||
312 | return mask; | 361 | return mask; |
313 | } | 362 | } |
314 | 363 | ||
@@ -462,9 +511,13 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
462 | if (ret) | 511 | if (ret) |
463 | goto put_dev; | 512 | goto put_dev; |
464 | 513 | ||
465 | sk->sk_state = LLCP_CONNECTED; | 514 | ret = sock_wait_state(sk, LLCP_CONNECTED, |
515 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | ||
516 | if (ret) | ||
517 | goto put_dev; | ||
466 | 518 | ||
467 | release_sock(sk); | 519 | release_sock(sk); |
520 | |||
468 | return 0; | 521 | return 0; |
469 | 522 | ||
470 | put_dev: | 523 | put_dev: |