diff options
| author | Patrick McHardy <kaber@trash.net> | 2010-05-10 12:39:28 -0400 |
|---|---|---|
| committer | Patrick McHardy <kaber@trash.net> | 2010-05-10 12:39:28 -0400 |
| commit | 1e4b1057121bc756b91758a434b504d2010f6088 (patch) | |
| tree | b016cf2c728289c7e36d9e4e488f30ab0bd0ae6e /net | |
| parent | 3b254c54ec46eb022cb26ee6ab37fae23f5f7d6a (diff) | |
| parent | 3ee943728fff536edaf8f59faa58aaa1aa7366e3 (diff) | |
Merge branch 'master' of /repos/git/net-next-2.6
Conflicts:
net/bridge/br_device.c
net/bridge/br_forward.c
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
139 files changed, 3662 insertions, 2480 deletions
diff --git a/net/atm/common.c b/net/atm/common.c index 97ed94aa0cbc..b43feb1a3995 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
| @@ -90,10 +90,13 @@ static void vcc_sock_destruct(struct sock *sk) | |||
| 90 | 90 | ||
| 91 | static void vcc_def_wakeup(struct sock *sk) | 91 | static void vcc_def_wakeup(struct sock *sk) |
| 92 | { | 92 | { |
| 93 | read_lock(&sk->sk_callback_lock); | 93 | struct socket_wq *wq; |
| 94 | if (sk_has_sleeper(sk)) | 94 | |
| 95 | wake_up(sk->sk_sleep); | 95 | rcu_read_lock(); |
| 96 | read_unlock(&sk->sk_callback_lock); | 96 | wq = rcu_dereference(sk->sk_wq); |
| 97 | if (wq_has_sleeper(wq)) | ||
| 98 | wake_up(&wq->wait); | ||
| 99 | rcu_read_unlock(); | ||
| 97 | } | 100 | } |
| 98 | 101 | ||
| 99 | static inline int vcc_writable(struct sock *sk) | 102 | static inline int vcc_writable(struct sock *sk) |
| @@ -106,16 +109,19 @@ static inline int vcc_writable(struct sock *sk) | |||
| 106 | 109 | ||
| 107 | static void vcc_write_space(struct sock *sk) | 110 | static void vcc_write_space(struct sock *sk) |
| 108 | { | 111 | { |
| 109 | read_lock(&sk->sk_callback_lock); | 112 | struct socket_wq *wq; |
| 113 | |||
| 114 | rcu_read_lock(); | ||
| 110 | 115 | ||
| 111 | if (vcc_writable(sk)) { | 116 | if (vcc_writable(sk)) { |
| 112 | if (sk_has_sleeper(sk)) | 117 | wq = rcu_dereference(sk->sk_wq); |
| 113 | wake_up_interruptible(sk->sk_sleep); | 118 | if (wq_has_sleeper(wq)) |
| 119 | wake_up_interruptible(&wq->wait); | ||
| 114 | 120 | ||
| 115 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 121 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
| 116 | } | 122 | } |
| 117 | 123 | ||
| 118 | read_unlock(&sk->sk_callback_lock); | 124 | rcu_read_unlock(); |
| 119 | } | 125 | } |
| 120 | 126 | ||
| 121 | static struct proto vcc_proto = { | 127 | static struct proto vcc_proto = { |
| @@ -549,7 +555,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, | |||
| 549 | } | 555 | } |
| 550 | 556 | ||
| 551 | eff = (size+3) & ~3; /* align to word boundary */ | 557 | eff = (size+3) & ~3; /* align to word boundary */ |
| 552 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 558 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 553 | error = 0; | 559 | error = 0; |
| 554 | while (!(skb = alloc_tx(vcc, eff))) { | 560 | while (!(skb = alloc_tx(vcc, eff))) { |
| 555 | if (m->msg_flags & MSG_DONTWAIT) { | 561 | if (m->msg_flags & MSG_DONTWAIT) { |
| @@ -568,9 +574,9 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, | |||
| 568 | send_sig(SIGPIPE, current, 0); | 574 | send_sig(SIGPIPE, current, 0); |
| 569 | break; | 575 | break; |
| 570 | } | 576 | } |
| 571 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 577 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 572 | } | 578 | } |
| 573 | finish_wait(sk->sk_sleep, &wait); | 579 | finish_wait(sk_sleep(sk), &wait); |
| 574 | if (error) | 580 | if (error) |
| 575 | goto out; | 581 | goto out; |
| 576 | skb->dev = NULL; /* for paths shared with net_device interfaces */ | 582 | skb->dev = NULL; /* for paths shared with net_device interfaces */ |
| @@ -595,7 +601,7 @@ unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
| 595 | struct atm_vcc *vcc; | 601 | struct atm_vcc *vcc; |
| 596 | unsigned int mask; | 602 | unsigned int mask; |
| 597 | 603 | ||
| 598 | sock_poll_wait(file, sk->sk_sleep, wait); | 604 | sock_poll_wait(file, sk_sleep(sk), wait); |
| 599 | mask = 0; | 605 | mask = 0; |
| 600 | 606 | ||
| 601 | vcc = ATM_SD(sock); | 607 | vcc = ATM_SD(sock); |
diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 6ba6e466ee54..509c8ac02b63 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c | |||
| @@ -131,7 +131,7 @@ static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb) | |||
| 131 | } | 131 | } |
| 132 | sk->sk_ack_backlog++; | 132 | sk->sk_ack_backlog++; |
| 133 | skb_queue_tail(&sk->sk_receive_queue, skb); | 133 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 134 | pr_debug("waking sk->sk_sleep 0x%p\n", sk->sk_sleep); | 134 | pr_debug("waking sk_sleep(sk) 0x%p\n", sk_sleep(sk)); |
| 135 | sk->sk_state_change(sk); | 135 | sk->sk_state_change(sk); |
| 136 | as_indicate_complete: | 136 | as_indicate_complete: |
| 137 | release_sock(sk); | 137 | release_sock(sk); |
diff --git a/net/atm/svc.c b/net/atm/svc.c index 3ba9a45a51ac..754ee4791d96 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c | |||
| @@ -49,14 +49,14 @@ static void svc_disconnect(struct atm_vcc *vcc) | |||
| 49 | 49 | ||
| 50 | pr_debug("%p\n", vcc); | 50 | pr_debug("%p\n", vcc); |
| 51 | if (test_bit(ATM_VF_REGIS, &vcc->flags)) { | 51 | if (test_bit(ATM_VF_REGIS, &vcc->flags)) { |
| 52 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 52 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
| 53 | sigd_enq(vcc, as_close, NULL, NULL, NULL); | 53 | sigd_enq(vcc, as_close, NULL, NULL, NULL); |
| 54 | while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { | 54 | while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { |
| 55 | schedule(); | 55 | schedule(); |
| 56 | prepare_to_wait(sk->sk_sleep, &wait, | 56 | prepare_to_wait(sk_sleep(sk), &wait, |
| 57 | TASK_UNINTERRUPTIBLE); | 57 | TASK_UNINTERRUPTIBLE); |
| 58 | } | 58 | } |
| 59 | finish_wait(sk->sk_sleep, &wait); | 59 | finish_wait(sk_sleep(sk), &wait); |
| 60 | } | 60 | } |
| 61 | /* beware - socket is still in use by atmsigd until the last | 61 | /* beware - socket is still in use by atmsigd until the last |
| 62 | as_indicate has been answered */ | 62 | as_indicate has been answered */ |
| @@ -125,13 +125,13 @@ static int svc_bind(struct socket *sock, struct sockaddr *sockaddr, | |||
| 125 | } | 125 | } |
| 126 | vcc->local = *addr; | 126 | vcc->local = *addr; |
| 127 | set_bit(ATM_VF_WAITING, &vcc->flags); | 127 | set_bit(ATM_VF_WAITING, &vcc->flags); |
| 128 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 128 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
| 129 | sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local); | 129 | sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local); |
| 130 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 130 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
| 131 | schedule(); | 131 | schedule(); |
| 132 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 132 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
| 133 | } | 133 | } |
| 134 | finish_wait(sk->sk_sleep, &wait); | 134 | finish_wait(sk_sleep(sk), &wait); |
| 135 | clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */ | 135 | clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */ |
| 136 | if (!sigd) { | 136 | if (!sigd) { |
| 137 | error = -EUNATCH; | 137 | error = -EUNATCH; |
| @@ -201,10 +201,10 @@ static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, | |||
| 201 | } | 201 | } |
| 202 | vcc->remote = *addr; | 202 | vcc->remote = *addr; |
| 203 | set_bit(ATM_VF_WAITING, &vcc->flags); | 203 | set_bit(ATM_VF_WAITING, &vcc->flags); |
| 204 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 204 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 205 | sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote); | 205 | sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote); |
| 206 | if (flags & O_NONBLOCK) { | 206 | if (flags & O_NONBLOCK) { |
| 207 | finish_wait(sk->sk_sleep, &wait); | 207 | finish_wait(sk_sleep(sk), &wait); |
| 208 | sock->state = SS_CONNECTING; | 208 | sock->state = SS_CONNECTING; |
| 209 | error = -EINPROGRESS; | 209 | error = -EINPROGRESS; |
| 210 | goto out; | 210 | goto out; |
| @@ -213,7 +213,7 @@ static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, | |||
| 213 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 213 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
| 214 | schedule(); | 214 | schedule(); |
| 215 | if (!signal_pending(current)) { | 215 | if (!signal_pending(current)) { |
| 216 | prepare_to_wait(sk->sk_sleep, &wait, | 216 | prepare_to_wait(sk_sleep(sk), &wait, |
| 217 | TASK_INTERRUPTIBLE); | 217 | TASK_INTERRUPTIBLE); |
| 218 | continue; | 218 | continue; |
| 219 | } | 219 | } |
| @@ -232,14 +232,14 @@ static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, | |||
| 232 | */ | 232 | */ |
| 233 | sigd_enq(vcc, as_close, NULL, NULL, NULL); | 233 | sigd_enq(vcc, as_close, NULL, NULL, NULL); |
| 234 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 234 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
| 235 | prepare_to_wait(sk->sk_sleep, &wait, | 235 | prepare_to_wait(sk_sleep(sk), &wait, |
| 236 | TASK_INTERRUPTIBLE); | 236 | TASK_INTERRUPTIBLE); |
| 237 | schedule(); | 237 | schedule(); |
| 238 | } | 238 | } |
| 239 | if (!sk->sk_err) | 239 | if (!sk->sk_err) |
| 240 | while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && | 240 | while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && |
| 241 | sigd) { | 241 | sigd) { |
| 242 | prepare_to_wait(sk->sk_sleep, &wait, | 242 | prepare_to_wait(sk_sleep(sk), &wait, |
| 243 | TASK_INTERRUPTIBLE); | 243 | TASK_INTERRUPTIBLE); |
| 244 | schedule(); | 244 | schedule(); |
| 245 | } | 245 | } |
| @@ -250,7 +250,7 @@ static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, | |||
| 250 | error = -EINTR; | 250 | error = -EINTR; |
| 251 | break; | 251 | break; |
| 252 | } | 252 | } |
| 253 | finish_wait(sk->sk_sleep, &wait); | 253 | finish_wait(sk_sleep(sk), &wait); |
| 254 | if (error) | 254 | if (error) |
| 255 | goto out; | 255 | goto out; |
| 256 | if (!sigd) { | 256 | if (!sigd) { |
| @@ -302,13 +302,13 @@ static int svc_listen(struct socket *sock, int backlog) | |||
| 302 | goto out; | 302 | goto out; |
| 303 | } | 303 | } |
| 304 | set_bit(ATM_VF_WAITING, &vcc->flags); | 304 | set_bit(ATM_VF_WAITING, &vcc->flags); |
| 305 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 305 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
| 306 | sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local); | 306 | sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local); |
| 307 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 307 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
| 308 | schedule(); | 308 | schedule(); |
| 309 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 309 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
| 310 | } | 310 | } |
| 311 | finish_wait(sk->sk_sleep, &wait); | 311 | finish_wait(sk_sleep(sk), &wait); |
| 312 | if (!sigd) { | 312 | if (!sigd) { |
| 313 | error = -EUNATCH; | 313 | error = -EUNATCH; |
| 314 | goto out; | 314 | goto out; |
| @@ -343,7 +343,7 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 343 | while (1) { | 343 | while (1) { |
| 344 | DEFINE_WAIT(wait); | 344 | DEFINE_WAIT(wait); |
| 345 | 345 | ||
| 346 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 346 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 347 | while (!(skb = skb_dequeue(&sk->sk_receive_queue)) && | 347 | while (!(skb = skb_dequeue(&sk->sk_receive_queue)) && |
| 348 | sigd) { | 348 | sigd) { |
| 349 | if (test_bit(ATM_VF_RELEASED, &old_vcc->flags)) | 349 | if (test_bit(ATM_VF_RELEASED, &old_vcc->flags)) |
| @@ -363,10 +363,10 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 363 | error = -ERESTARTSYS; | 363 | error = -ERESTARTSYS; |
| 364 | break; | 364 | break; |
| 365 | } | 365 | } |
| 366 | prepare_to_wait(sk->sk_sleep, &wait, | 366 | prepare_to_wait(sk_sleep(sk), &wait, |
| 367 | TASK_INTERRUPTIBLE); | 367 | TASK_INTERRUPTIBLE); |
| 368 | } | 368 | } |
| 369 | finish_wait(sk->sk_sleep, &wait); | 369 | finish_wait(sk_sleep(sk), &wait); |
| 370 | if (error) | 370 | if (error) |
| 371 | goto out; | 371 | goto out; |
| 372 | if (!skb) { | 372 | if (!skb) { |
| @@ -392,17 +392,17 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 392 | } | 392 | } |
| 393 | /* wait should be short, so we ignore the non-blocking flag */ | 393 | /* wait should be short, so we ignore the non-blocking flag */ |
| 394 | set_bit(ATM_VF_WAITING, &new_vcc->flags); | 394 | set_bit(ATM_VF_WAITING, &new_vcc->flags); |
| 395 | prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, | 395 | prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait, |
| 396 | TASK_UNINTERRUPTIBLE); | 396 | TASK_UNINTERRUPTIBLE); |
| 397 | sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL); | 397 | sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL); |
| 398 | while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) { | 398 | while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) { |
| 399 | release_sock(sk); | 399 | release_sock(sk); |
| 400 | schedule(); | 400 | schedule(); |
| 401 | lock_sock(sk); | 401 | lock_sock(sk); |
| 402 | prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, | 402 | prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait, |
| 403 | TASK_UNINTERRUPTIBLE); | 403 | TASK_UNINTERRUPTIBLE); |
| 404 | } | 404 | } |
| 405 | finish_wait(sk_atm(new_vcc)->sk_sleep, &wait); | 405 | finish_wait(sk_sleep(sk_atm(new_vcc)), &wait); |
| 406 | if (!sigd) { | 406 | if (!sigd) { |
| 407 | error = -EUNATCH; | 407 | error = -EUNATCH; |
| 408 | goto out; | 408 | goto out; |
| @@ -438,14 +438,14 @@ int svc_change_qos(struct atm_vcc *vcc, struct atm_qos *qos) | |||
| 438 | DEFINE_WAIT(wait); | 438 | DEFINE_WAIT(wait); |
| 439 | 439 | ||
| 440 | set_bit(ATM_VF_WAITING, &vcc->flags); | 440 | set_bit(ATM_VF_WAITING, &vcc->flags); |
| 441 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 441 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
| 442 | sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0); | 442 | sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0); |
| 443 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && | 443 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && |
| 444 | !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { | 444 | !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { |
| 445 | schedule(); | 445 | schedule(); |
| 446 | prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); | 446 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
| 447 | } | 447 | } |
| 448 | finish_wait(sk->sk_sleep, &wait); | 448 | finish_wait(sk_sleep(sk), &wait); |
| 449 | if (!sigd) | 449 | if (!sigd) |
| 450 | return -EUNATCH; | 450 | return -EUNATCH; |
| 451 | return -sk->sk_err; | 451 | return -sk->sk_err; |
| @@ -534,20 +534,20 @@ static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr, | |||
| 534 | 534 | ||
| 535 | lock_sock(sk); | 535 | lock_sock(sk); |
| 536 | set_bit(ATM_VF_WAITING, &vcc->flags); | 536 | set_bit(ATM_VF_WAITING, &vcc->flags); |
| 537 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 537 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 538 | sigd_enq(vcc, as_addparty, NULL, NULL, | 538 | sigd_enq(vcc, as_addparty, NULL, NULL, |
| 539 | (struct sockaddr_atmsvc *) sockaddr); | 539 | (struct sockaddr_atmsvc *) sockaddr); |
| 540 | if (flags & O_NONBLOCK) { | 540 | if (flags & O_NONBLOCK) { |
| 541 | finish_wait(sk->sk_sleep, &wait); | 541 | finish_wait(sk_sleep(sk), &wait); |
| 542 | error = -EINPROGRESS; | 542 | error = -EINPROGRESS; |
| 543 | goto out; | 543 | goto out; |
| 544 | } | 544 | } |
| 545 | pr_debug("added wait queue\n"); | 545 | pr_debug("added wait queue\n"); |
| 546 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 546 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
| 547 | schedule(); | 547 | schedule(); |
| 548 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 548 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 549 | } | 549 | } |
| 550 | finish_wait(sk->sk_sleep, &wait); | 550 | finish_wait(sk_sleep(sk), &wait); |
| 551 | error = xchg(&sk->sk_err_soft, 0); | 551 | error = xchg(&sk->sk_err_soft, 0); |
| 552 | out: | 552 | out: |
| 553 | release_sock(sk); | 553 | release_sock(sk); |
| @@ -563,13 +563,13 @@ static int svc_dropparty(struct socket *sock, int ep_ref) | |||
| 563 | 563 | ||
| 564 | lock_sock(sk); | 564 | lock_sock(sk); |
| 565 | set_bit(ATM_VF_WAITING, &vcc->flags); | 565 | set_bit(ATM_VF_WAITING, &vcc->flags); |
| 566 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 566 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 567 | sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref); | 567 | sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref); |
| 568 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 568 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
| 569 | schedule(); | 569 | schedule(); |
| 570 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 570 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 571 | } | 571 | } |
| 572 | finish_wait(sk->sk_sleep, &wait); | 572 | finish_wait(sk_sleep(sk), &wait); |
| 573 | if (!sigd) { | 573 | if (!sigd) { |
| 574 | error = -EUNATCH; | 574 | error = -EUNATCH; |
| 575 | goto out; | 575 | goto out; |
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 65c5801261f9..cfdfd7e2a172 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
| @@ -1281,7 +1281,7 @@ static int __must_check ax25_connect(struct socket *sock, | |||
| 1281 | DEFINE_WAIT(wait); | 1281 | DEFINE_WAIT(wait); |
| 1282 | 1282 | ||
| 1283 | for (;;) { | 1283 | for (;;) { |
| 1284 | prepare_to_wait(sk->sk_sleep, &wait, | 1284 | prepare_to_wait(sk_sleep(sk), &wait, |
| 1285 | TASK_INTERRUPTIBLE); | 1285 | TASK_INTERRUPTIBLE); |
| 1286 | if (sk->sk_state != TCP_SYN_SENT) | 1286 | if (sk->sk_state != TCP_SYN_SENT) |
| 1287 | break; | 1287 | break; |
| @@ -1294,7 +1294,7 @@ static int __must_check ax25_connect(struct socket *sock, | |||
| 1294 | err = -ERESTARTSYS; | 1294 | err = -ERESTARTSYS; |
| 1295 | break; | 1295 | break; |
| 1296 | } | 1296 | } |
| 1297 | finish_wait(sk->sk_sleep, &wait); | 1297 | finish_wait(sk_sleep(sk), &wait); |
| 1298 | 1298 | ||
| 1299 | if (err) | 1299 | if (err) |
| 1300 | goto out_release; | 1300 | goto out_release; |
| @@ -1346,7 +1346,7 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 1346 | * hooked into the SABM we saved | 1346 | * hooked into the SABM we saved |
| 1347 | */ | 1347 | */ |
| 1348 | for (;;) { | 1348 | for (;;) { |
| 1349 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1349 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 1350 | skb = skb_dequeue(&sk->sk_receive_queue); | 1350 | skb = skb_dequeue(&sk->sk_receive_queue); |
| 1351 | if (skb) | 1351 | if (skb) |
| 1352 | break; | 1352 | break; |
| @@ -1364,7 +1364,7 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 1364 | err = -ERESTARTSYS; | 1364 | err = -ERESTARTSYS; |
| 1365 | break; | 1365 | break; |
| 1366 | } | 1366 | } |
| 1367 | finish_wait(sk->sk_sleep, &wait); | 1367 | finish_wait(sk_sleep(sk), &wait); |
| 1368 | 1368 | ||
| 1369 | if (err) | 1369 | if (err) |
| 1370 | goto out; | 1370 | goto out; |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 404a8500fd03..421c45bd1b95 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
| @@ -288,7 +288,7 @@ unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *w | |||
| 288 | 288 | ||
| 289 | BT_DBG("sock %p, sk %p", sock, sk); | 289 | BT_DBG("sock %p, sk %p", sock, sk); |
| 290 | 290 | ||
| 291 | poll_wait(file, sk->sk_sleep, wait); | 291 | poll_wait(file, sk_sleep(sk), wait); |
| 292 | 292 | ||
| 293 | if (sk->sk_state == BT_LISTEN) | 293 | if (sk->sk_state == BT_LISTEN) |
| 294 | return bt_accept_poll(sk); | 294 | return bt_accept_poll(sk); |
| @@ -378,7 +378,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) | |||
| 378 | 378 | ||
| 379 | BT_DBG("sk %p", sk); | 379 | BT_DBG("sk %p", sk); |
| 380 | 380 | ||
| 381 | add_wait_queue(sk->sk_sleep, &wait); | 381 | add_wait_queue(sk_sleep(sk), &wait); |
| 382 | while (sk->sk_state != state) { | 382 | while (sk->sk_state != state) { |
| 383 | set_current_state(TASK_INTERRUPTIBLE); | 383 | set_current_state(TASK_INTERRUPTIBLE); |
| 384 | 384 | ||
| @@ -401,7 +401,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) | |||
| 401 | break; | 401 | break; |
| 402 | } | 402 | } |
| 403 | set_current_state(TASK_RUNNING); | 403 | set_current_state(TASK_RUNNING); |
| 404 | remove_wait_queue(sk->sk_sleep, &wait); | 404 | remove_wait_queue(sk_sleep(sk), &wait); |
| 405 | return err; | 405 | return err; |
| 406 | } | 406 | } |
| 407 | EXPORT_SYMBOL(bt_sock_wait_state); | 407 | EXPORT_SYMBOL(bt_sock_wait_state); |
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 8062dad6d10d..f10b41fb05a0 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
| @@ -474,7 +474,7 @@ static int bnep_session(void *arg) | |||
| 474 | set_user_nice(current, -15); | 474 | set_user_nice(current, -15); |
| 475 | 475 | ||
| 476 | init_waitqueue_entry(&wait, current); | 476 | init_waitqueue_entry(&wait, current); |
| 477 | add_wait_queue(sk->sk_sleep, &wait); | 477 | add_wait_queue(sk_sleep(sk), &wait); |
| 478 | while (!atomic_read(&s->killed)) { | 478 | while (!atomic_read(&s->killed)) { |
| 479 | set_current_state(TASK_INTERRUPTIBLE); | 479 | set_current_state(TASK_INTERRUPTIBLE); |
| 480 | 480 | ||
| @@ -496,7 +496,7 @@ static int bnep_session(void *arg) | |||
| 496 | schedule(); | 496 | schedule(); |
| 497 | } | 497 | } |
| 498 | set_current_state(TASK_RUNNING); | 498 | set_current_state(TASK_RUNNING); |
| 499 | remove_wait_queue(sk->sk_sleep, &wait); | 499 | remove_wait_queue(sk_sleep(sk), &wait); |
| 500 | 500 | ||
| 501 | /* Cleanup session */ | 501 | /* Cleanup session */ |
| 502 | down_write(&bnep_session_sem); | 502 | down_write(&bnep_session_sem); |
| @@ -507,7 +507,7 @@ static int bnep_session(void *arg) | |||
| 507 | /* Wakeup user-space polling for socket errors */ | 507 | /* Wakeup user-space polling for socket errors */ |
| 508 | s->sock->sk->sk_err = EUNATCH; | 508 | s->sock->sk->sk_err = EUNATCH; |
| 509 | 509 | ||
| 510 | wake_up_interruptible(s->sock->sk->sk_sleep); | 510 | wake_up_interruptible(sk_sleep(s->sock->sk)); |
| 511 | 511 | ||
| 512 | /* Release the socket */ | 512 | /* Release the socket */ |
| 513 | fput(s->sock->file); | 513 | fput(s->sock->file); |
| @@ -638,7 +638,7 @@ int bnep_del_connection(struct bnep_conndel_req *req) | |||
| 638 | 638 | ||
| 639 | /* Kill session thread */ | 639 | /* Kill session thread */ |
| 640 | atomic_inc(&s->killed); | 640 | atomic_inc(&s->killed); |
| 641 | wake_up_interruptible(s->sock->sk->sk_sleep); | 641 | wake_up_interruptible(sk_sleep(s->sock->sk)); |
| 642 | } else | 642 | } else |
| 643 | err = -ENOENT; | 643 | err = -ENOENT; |
| 644 | 644 | ||
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index d48b33f4d4ba..0faad5ce6dc4 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c | |||
| @@ -109,7 +109,7 @@ static void bnep_net_set_mc_list(struct net_device *dev) | |||
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | skb_queue_tail(&sk->sk_write_queue, skb); | 111 | skb_queue_tail(&sk->sk_write_queue, skb); |
| 112 | wake_up_interruptible(sk->sk_sleep); | 112 | wake_up_interruptible(sk_sleep(sk)); |
| 113 | #endif | 113 | #endif |
| 114 | } | 114 | } |
| 115 | 115 | ||
| @@ -193,11 +193,11 @@ static netdev_tx_t bnep_net_xmit(struct sk_buff *skb, | |||
| 193 | /* | 193 | /* |
| 194 | * We cannot send L2CAP packets from here as we are potentially in a bh. | 194 | * We cannot send L2CAP packets from here as we are potentially in a bh. |
| 195 | * So we have to queue them and wake up session thread which is sleeping | 195 | * So we have to queue them and wake up session thread which is sleeping |
| 196 | * on the sk->sk_sleep. | 196 | * on the sk_sleep(sk). |
| 197 | */ | 197 | */ |
| 198 | dev->trans_start = jiffies; | 198 | dev->trans_start = jiffies; |
| 199 | skb_queue_tail(&sk->sk_write_queue, skb); | 199 | skb_queue_tail(&sk->sk_write_queue, skb); |
| 200 | wake_up_interruptible(sk->sk_sleep); | 200 | wake_up_interruptible(sk_sleep(sk)); |
| 201 | 201 | ||
| 202 | if (skb_queue_len(&sk->sk_write_queue) >= BNEP_TX_QUEUE_LEN) { | 202 | if (skb_queue_len(&sk->sk_write_queue) >= BNEP_TX_QUEUE_LEN) { |
| 203 | BT_DBG("tx queue is full"); | 203 | BT_DBG("tx queue is full"); |
diff --git a/net/bluetooth/cmtp/cmtp.h b/net/bluetooth/cmtp/cmtp.h index e4663aa14d26..785e79e953c5 100644 --- a/net/bluetooth/cmtp/cmtp.h +++ b/net/bluetooth/cmtp/cmtp.h | |||
| @@ -125,7 +125,7 @@ static inline void cmtp_schedule(struct cmtp_session *session) | |||
| 125 | { | 125 | { |
| 126 | struct sock *sk = session->sock->sk; | 126 | struct sock *sk = session->sock->sk; |
| 127 | 127 | ||
| 128 | wake_up_interruptible(sk->sk_sleep); | 128 | wake_up_interruptible(sk_sleep(sk)); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | /* CMTP init defines */ | 131 | /* CMTP init defines */ |
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 0073ec8495da..d4c6af082d48 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
| @@ -284,7 +284,7 @@ static int cmtp_session(void *arg) | |||
| 284 | set_user_nice(current, -15); | 284 | set_user_nice(current, -15); |
| 285 | 285 | ||
| 286 | init_waitqueue_entry(&wait, current); | 286 | init_waitqueue_entry(&wait, current); |
| 287 | add_wait_queue(sk->sk_sleep, &wait); | 287 | add_wait_queue(sk_sleep(sk), &wait); |
| 288 | while (!atomic_read(&session->terminate)) { | 288 | while (!atomic_read(&session->terminate)) { |
| 289 | set_current_state(TASK_INTERRUPTIBLE); | 289 | set_current_state(TASK_INTERRUPTIBLE); |
| 290 | 290 | ||
| @@ -301,7 +301,7 @@ static int cmtp_session(void *arg) | |||
| 301 | schedule(); | 301 | schedule(); |
| 302 | } | 302 | } |
| 303 | set_current_state(TASK_RUNNING); | 303 | set_current_state(TASK_RUNNING); |
| 304 | remove_wait_queue(sk->sk_sleep, &wait); | 304 | remove_wait_queue(sk_sleep(sk), &wait); |
| 305 | 305 | ||
| 306 | down_write(&cmtp_session_sem); | 306 | down_write(&cmtp_session_sem); |
| 307 | 307 | ||
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 280529ad9274..bfe641b7dfaf 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
| @@ -561,8 +561,8 @@ static int hidp_session(void *arg) | |||
| 561 | 561 | ||
| 562 | init_waitqueue_entry(&ctrl_wait, current); | 562 | init_waitqueue_entry(&ctrl_wait, current); |
| 563 | init_waitqueue_entry(&intr_wait, current); | 563 | init_waitqueue_entry(&intr_wait, current); |
| 564 | add_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait); | 564 | add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait); |
| 565 | add_wait_queue(intr_sk->sk_sleep, &intr_wait); | 565 | add_wait_queue(sk_sleep(intr_sk), &intr_wait); |
| 566 | while (!atomic_read(&session->terminate)) { | 566 | while (!atomic_read(&session->terminate)) { |
| 567 | set_current_state(TASK_INTERRUPTIBLE); | 567 | set_current_state(TASK_INTERRUPTIBLE); |
| 568 | 568 | ||
| @@ -584,8 +584,8 @@ static int hidp_session(void *arg) | |||
| 584 | schedule(); | 584 | schedule(); |
| 585 | } | 585 | } |
| 586 | set_current_state(TASK_RUNNING); | 586 | set_current_state(TASK_RUNNING); |
| 587 | remove_wait_queue(intr_sk->sk_sleep, &intr_wait); | 587 | remove_wait_queue(sk_sleep(intr_sk), &intr_wait); |
| 588 | remove_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait); | 588 | remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait); |
| 589 | 589 | ||
| 590 | down_write(&hidp_session_sem); | 590 | down_write(&hidp_session_sem); |
| 591 | 591 | ||
| @@ -609,7 +609,7 @@ static int hidp_session(void *arg) | |||
| 609 | 609 | ||
| 610 | fput(session->intr_sock->file); | 610 | fput(session->intr_sock->file); |
| 611 | 611 | ||
| 612 | wait_event_timeout(*(ctrl_sk->sk_sleep), | 612 | wait_event_timeout(*(sk_sleep(ctrl_sk)), |
| 613 | (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500)); | 613 | (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500)); |
| 614 | 614 | ||
| 615 | fput(session->ctrl_sock->file); | 615 | fput(session->ctrl_sock->file); |
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index a4e215d50c10..8d934a19da0a 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h | |||
| @@ -164,8 +164,8 @@ static inline void hidp_schedule(struct hidp_session *session) | |||
| 164 | struct sock *ctrl_sk = session->ctrl_sock->sk; | 164 | struct sock *ctrl_sk = session->ctrl_sock->sk; |
| 165 | struct sock *intr_sk = session->intr_sock->sk; | 165 | struct sock *intr_sk = session->intr_sock->sk; |
| 166 | 166 | ||
| 167 | wake_up_interruptible(ctrl_sk->sk_sleep); | 167 | wake_up_interruptible(sk_sleep(ctrl_sk)); |
| 168 | wake_up_interruptible(intr_sk->sk_sleep); | 168 | wake_up_interruptible(sk_sleep(intr_sk)); |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | /* HIDP init defines */ | 171 | /* HIDP init defines */ |
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 99d68c34e4f1..864c76f4a678 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
| @@ -1147,7 +1147,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl | |||
| 1147 | BT_DBG("sk %p timeo %ld", sk, timeo); | 1147 | BT_DBG("sk %p timeo %ld", sk, timeo); |
| 1148 | 1148 | ||
| 1149 | /* Wait for an incoming connection. (wake-one). */ | 1149 | /* Wait for an incoming connection. (wake-one). */ |
| 1150 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 1150 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
| 1151 | while (!(nsk = bt_accept_dequeue(sk, newsock))) { | 1151 | while (!(nsk = bt_accept_dequeue(sk, newsock))) { |
| 1152 | set_current_state(TASK_INTERRUPTIBLE); | 1152 | set_current_state(TASK_INTERRUPTIBLE); |
| 1153 | if (!timeo) { | 1153 | if (!timeo) { |
| @@ -1170,7 +1170,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl | |||
| 1170 | } | 1170 | } |
| 1171 | } | 1171 | } |
| 1172 | set_current_state(TASK_RUNNING); | 1172 | set_current_state(TASK_RUNNING); |
| 1173 | remove_wait_queue(sk->sk_sleep, &wait); | 1173 | remove_wait_queue(sk_sleep(sk), &wait); |
| 1174 | 1174 | ||
| 1175 | if (err) | 1175 | if (err) |
| 1176 | goto done; | 1176 | goto done; |
| @@ -1626,7 +1626,10 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
| 1626 | /* Connectionless channel */ | 1626 | /* Connectionless channel */ |
| 1627 | if (sk->sk_type == SOCK_DGRAM) { | 1627 | if (sk->sk_type == SOCK_DGRAM) { |
| 1628 | skb = l2cap_create_connless_pdu(sk, msg, len); | 1628 | skb = l2cap_create_connless_pdu(sk, msg, len); |
| 1629 | err = l2cap_do_send(sk, skb); | 1629 | if (IS_ERR(skb)) |
| 1630 | err = PTR_ERR(skb); | ||
| 1631 | else | ||
| 1632 | err = l2cap_do_send(sk, skb); | ||
| 1630 | goto done; | 1633 | goto done; |
| 1631 | } | 1634 | } |
| 1632 | 1635 | ||
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 8ed3c37684fa..43fbf6b4b4bf 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
| @@ -503,7 +503,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f | |||
| 503 | BT_DBG("sk %p timeo %ld", sk, timeo); | 503 | BT_DBG("sk %p timeo %ld", sk, timeo); |
| 504 | 504 | ||
| 505 | /* Wait for an incoming connection. (wake-one). */ | 505 | /* Wait for an incoming connection. (wake-one). */ |
| 506 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 506 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
| 507 | while (!(nsk = bt_accept_dequeue(sk, newsock))) { | 507 | while (!(nsk = bt_accept_dequeue(sk, newsock))) { |
| 508 | set_current_state(TASK_INTERRUPTIBLE); | 508 | set_current_state(TASK_INTERRUPTIBLE); |
| 509 | if (!timeo) { | 509 | if (!timeo) { |
| @@ -526,7 +526,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f | |||
| 526 | } | 526 | } |
| 527 | } | 527 | } |
| 528 | set_current_state(TASK_RUNNING); | 528 | set_current_state(TASK_RUNNING); |
| 529 | remove_wait_queue(sk->sk_sleep, &wait); | 529 | remove_wait_queue(sk_sleep(sk), &wait); |
| 530 | 530 | ||
| 531 | if (err) | 531 | if (err) |
| 532 | goto done; | 532 | goto done; |
| @@ -621,7 +621,7 @@ static long rfcomm_sock_data_wait(struct sock *sk, long timeo) | |||
| 621 | { | 621 | { |
| 622 | DECLARE_WAITQUEUE(wait, current); | 622 | DECLARE_WAITQUEUE(wait, current); |
| 623 | 623 | ||
| 624 | add_wait_queue(sk->sk_sleep, &wait); | 624 | add_wait_queue(sk_sleep(sk), &wait); |
| 625 | for (;;) { | 625 | for (;;) { |
| 626 | set_current_state(TASK_INTERRUPTIBLE); | 626 | set_current_state(TASK_INTERRUPTIBLE); |
| 627 | 627 | ||
| @@ -640,7 +640,7 @@ static long rfcomm_sock_data_wait(struct sock *sk, long timeo) | |||
| 640 | } | 640 | } |
| 641 | 641 | ||
| 642 | __set_current_state(TASK_RUNNING); | 642 | __set_current_state(TASK_RUNNING); |
| 643 | remove_wait_queue(sk->sk_sleep, &wait); | 643 | remove_wait_queue(sk_sleep(sk), &wait); |
| 644 | return timeo; | 644 | return timeo; |
| 645 | } | 645 | } |
| 646 | 646 | ||
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index ca6b2ad1c3fc..b406d3eff53a 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
| @@ -567,7 +567,7 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag | |||
| 567 | BT_DBG("sk %p timeo %ld", sk, timeo); | 567 | BT_DBG("sk %p timeo %ld", sk, timeo); |
| 568 | 568 | ||
| 569 | /* Wait for an incoming connection. (wake-one). */ | 569 | /* Wait for an incoming connection. (wake-one). */ |
| 570 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 570 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
| 571 | while (!(ch = bt_accept_dequeue(sk, newsock))) { | 571 | while (!(ch = bt_accept_dequeue(sk, newsock))) { |
| 572 | set_current_state(TASK_INTERRUPTIBLE); | 572 | set_current_state(TASK_INTERRUPTIBLE); |
| 573 | if (!timeo) { | 573 | if (!timeo) { |
| @@ -590,7 +590,7 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag | |||
| 590 | } | 590 | } |
| 591 | } | 591 | } |
| 592 | set_current_state(TASK_RUNNING); | 592 | set_current_state(TASK_RUNNING); |
| 593 | remove_wait_queue(sk->sk_sleep, &wait); | 593 | remove_wait_queue(sk_sleep(sk), &wait); |
| 594 | 594 | ||
| 595 | if (err) | 595 | if (err) |
| 596 | goto done; | 596 | goto done; |
diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig index d115d5cea5b6..9190ae462cb4 100644 --- a/net/bridge/Kconfig +++ b/net/bridge/Kconfig | |||
| @@ -33,14 +33,14 @@ config BRIDGE | |||
| 33 | If unsure, say N. | 33 | If unsure, say N. |
| 34 | 34 | ||
| 35 | config BRIDGE_IGMP_SNOOPING | 35 | config BRIDGE_IGMP_SNOOPING |
| 36 | bool "IGMP snooping" | 36 | bool "IGMP/MLD snooping" |
| 37 | depends on BRIDGE | 37 | depends on BRIDGE |
| 38 | depends on INET | 38 | depends on INET |
| 39 | default y | 39 | default y |
| 40 | ---help--- | 40 | ---help--- |
| 41 | If you say Y here, then the Ethernet bridge will be able selectively | 41 | If you say Y here, then the Ethernet bridge will be able selectively |
| 42 | forward multicast traffic based on IGMP traffic received from each | 42 | forward multicast traffic based on IGMP/MLD traffic received from |
| 43 | port. | 43 | each port. |
| 44 | 44 | ||
| 45 | Say N to exclude this support and reduce the binary size. | 45 | Say N to exclude this support and reduce the binary size. |
| 46 | 46 | ||
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 007bde87415d..f15f9c4a0dd2 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
| @@ -13,9 +13,12 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
| 16 | #include <linux/netpoll.h> | ||
| 16 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
| 17 | #include <linux/ethtool.h> | 18 | #include <linux/ethtool.h> |
| 19 | #include <linux/list.h> | ||
| 18 | #include <linux/netfilter_bridge.h> | 20 | #include <linux/netfilter_bridge.h> |
| 21 | |||
| 19 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
| 20 | #include "br_private.h" | 23 | #include "br_private.h" |
| 21 | 24 | ||
| @@ -43,7 +46,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 43 | skb_reset_mac_header(skb); | 46 | skb_reset_mac_header(skb); |
| 44 | skb_pull(skb, ETH_HLEN); | 47 | skb_pull(skb, ETH_HLEN); |
| 45 | 48 | ||
| 46 | if (dest[0] & 1) { | 49 | if (is_multicast_ether_addr(dest)) { |
| 47 | if (br_multicast_rcv(br, NULL, skb)) | 50 | if (br_multicast_rcv(br, NULL, skb)) |
| 48 | goto out; | 51 | goto out; |
| 49 | 52 | ||
| @@ -195,6 +198,59 @@ static int br_set_tx_csum(struct net_device *dev, u32 data) | |||
| 195 | return 0; | 198 | return 0; |
| 196 | } | 199 | } |
| 197 | 200 | ||
| 201 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 202 | bool br_devices_support_netpoll(struct net_bridge *br) | ||
| 203 | { | ||
| 204 | struct net_bridge_port *p; | ||
| 205 | bool ret = true; | ||
| 206 | int count = 0; | ||
| 207 | unsigned long flags; | ||
| 208 | |||
| 209 | spin_lock_irqsave(&br->lock, flags); | ||
| 210 | list_for_each_entry(p, &br->port_list, list) { | ||
| 211 | count++; | ||
| 212 | if ((p->dev->priv_flags & IFF_DISABLE_NETPOLL) || | ||
| 213 | !p->dev->netdev_ops->ndo_poll_controller) | ||
| 214 | ret = false; | ||
| 215 | } | ||
| 216 | spin_unlock_irqrestore(&br->lock, flags); | ||
| 217 | return count != 0 && ret; | ||
| 218 | } | ||
| 219 | |||
| 220 | static void br_poll_controller(struct net_device *br_dev) | ||
| 221 | { | ||
| 222 | struct netpoll *np = br_dev->npinfo->netpoll; | ||
| 223 | |||
| 224 | if (np->real_dev != br_dev) | ||
| 225 | netpoll_poll_dev(np->real_dev); | ||
| 226 | } | ||
| 227 | |||
| 228 | void br_netpoll_cleanup(struct net_device *br_dev) | ||
| 229 | { | ||
| 230 | struct net_bridge *br = netdev_priv(br_dev); | ||
| 231 | struct net_bridge_port *p, *n; | ||
| 232 | const struct net_device_ops *ops; | ||
| 233 | |||
| 234 | br->dev->npinfo = NULL; | ||
| 235 | list_for_each_entry_safe(p, n, &br->port_list, list) { | ||
| 236 | if (p->dev) { | ||
| 237 | ops = p->dev->netdev_ops; | ||
| 238 | if (ops->ndo_netpoll_cleanup) | ||
| 239 | ops->ndo_netpoll_cleanup(p->dev); | ||
| 240 | else | ||
| 241 | p->dev->npinfo = NULL; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | #else | ||
| 247 | |||
| 248 | void br_netpoll_cleanup(struct net_device *br_dev) | ||
| 249 | { | ||
| 250 | } | ||
| 251 | |||
| 252 | #endif | ||
| 253 | |||
| 198 | static const struct ethtool_ops br_ethtool_ops = { | 254 | static const struct ethtool_ops br_ethtool_ops = { |
| 199 | .get_drvinfo = br_getinfo, | 255 | .get_drvinfo = br_getinfo, |
| 200 | .get_link = ethtool_op_get_link, | 256 | .get_link = ethtool_op_get_link, |
| @@ -218,6 +274,10 @@ static const struct net_device_ops br_netdev_ops = { | |||
| 218 | .ndo_set_multicast_list = br_dev_set_multicast_list, | 274 | .ndo_set_multicast_list = br_dev_set_multicast_list, |
| 219 | .ndo_change_mtu = br_change_mtu, | 275 | .ndo_change_mtu = br_change_mtu, |
| 220 | .ndo_do_ioctl = br_dev_ioctl, | 276 | .ndo_do_ioctl = br_dev_ioctl, |
| 277 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 278 | .ndo_netpoll_cleanup = br_netpoll_cleanup, | ||
| 279 | .ndo_poll_controller = br_poll_controller, | ||
| 280 | #endif | ||
| 221 | }; | 281 | }; |
| 222 | 282 | ||
| 223 | static void br_dev_free(struct net_device *dev) | 283 | static void br_dev_free(struct net_device *dev) |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 92fb3293a215..a98ef1393097 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
| 18 | #include <linux/netpoll.h> | ||
| 18 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
| 19 | #include <linux/if_vlan.h> | 20 | #include <linux/if_vlan.h> |
| 20 | #include <linux/netfilter_bridge.h> | 21 | #include <linux/netfilter_bridge.h> |
| @@ -50,7 +51,13 @@ int br_dev_queue_push_xmit(struct sk_buff *skb) | |||
| 50 | else { | 51 | else { |
| 51 | skb_push(skb, ETH_HLEN); | 52 | skb_push(skb, ETH_HLEN); |
| 52 | 53 | ||
| 53 | dev_queue_xmit(skb); | 54 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 55 | if (unlikely(skb->dev->priv_flags & IFF_IN_NETPOLL)) { | ||
| 56 | netpoll_send_skb(skb->dev->npinfo->netpoll, skb); | ||
| 57 | skb->dev->priv_flags &= ~IFF_IN_NETPOLL; | ||
| 58 | } else | ||
| 59 | #endif | ||
| 60 | dev_queue_xmit(skb); | ||
| 54 | } | 61 | } |
| 55 | } | 62 | } |
| 56 | 63 | ||
| @@ -66,9 +73,23 @@ int br_forward_finish(struct sk_buff *skb) | |||
| 66 | 73 | ||
| 67 | static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | 74 | static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) |
| 68 | { | 75 | { |
| 76 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 77 | struct net_bridge *br = to->br; | ||
| 78 | if (unlikely(br->dev->priv_flags & IFF_IN_NETPOLL)) { | ||
| 79 | struct netpoll *np; | ||
| 80 | to->dev->npinfo = skb->dev->npinfo; | ||
| 81 | np = skb->dev->npinfo->netpoll; | ||
| 82 | np->real_dev = np->dev = to->dev; | ||
| 83 | to->dev->priv_flags |= IFF_IN_NETPOLL; | ||
| 84 | } | ||
| 85 | #endif | ||
| 69 | skb->dev = to->dev; | 86 | skb->dev = to->dev; |
| 70 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, | 87 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, |
| 71 | br_forward_finish); | 88 | br_forward_finish); |
| 89 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 90 | if (skb->dev->npinfo) | ||
| 91 | skb->dev->npinfo->netpoll->dev = br->dev; | ||
| 92 | #endif | ||
| 72 | } | 93 | } |
| 73 | 94 | ||
| 74 | static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | 95 | static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) |
| @@ -208,17 +229,15 @@ static void br_multicast_flood(struct net_bridge_mdb_entry *mdst, | |||
| 208 | { | 229 | { |
| 209 | struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; | 230 | struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; |
| 210 | struct net_bridge *br = netdev_priv(dev); | 231 | struct net_bridge *br = netdev_priv(dev); |
| 211 | struct net_bridge_port *port; | 232 | struct net_bridge_port *prev = NULL; |
| 212 | struct net_bridge_port *lport, *rport; | ||
| 213 | struct net_bridge_port *prev; | ||
| 214 | struct net_bridge_port_group *p; | 233 | struct net_bridge_port_group *p; |
| 215 | struct hlist_node *rp; | 234 | struct hlist_node *rp; |
| 216 | 235 | ||
| 217 | prev = NULL; | 236 | rp = rcu_dereference(br->router_list.first); |
| 218 | 237 | p = mdst ? rcu_dereference(mdst->ports) : NULL; | |
| 219 | rp = br->router_list.first; | ||
| 220 | p = mdst ? mdst->ports : NULL; | ||
| 221 | while (p || rp) { | 238 | while (p || rp) { |
| 239 | struct net_bridge_port *port, *lport, *rport; | ||
| 240 | |||
| 222 | lport = p ? p->port : NULL; | 241 | lport = p ? p->port : NULL; |
| 223 | rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) : | 242 | rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) : |
| 224 | NULL; | 243 | NULL; |
| @@ -231,9 +250,9 @@ static void br_multicast_flood(struct net_bridge_mdb_entry *mdst, | |||
| 231 | goto out; | 250 | goto out; |
| 232 | 251 | ||
| 233 | if ((unsigned long)lport >= (unsigned long)port) | 252 | if ((unsigned long)lport >= (unsigned long)port) |
| 234 | p = p->next; | 253 | p = rcu_dereference(p->next); |
| 235 | if ((unsigned long)rport >= (unsigned long)port) | 254 | if ((unsigned long)rport >= (unsigned long)port) |
| 236 | rp = rp->next; | 255 | rp = rcu_dereference(rp->next); |
| 237 | } | 256 | } |
| 238 | 257 | ||
| 239 | if (!prev) | 258 | if (!prev) |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 521439333316..537bdd60d9b9 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
| 16 | #include <linux/netpoll.h> | ||
| 16 | #include <linux/ethtool.h> | 17 | #include <linux/ethtool.h> |
| 17 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
| 18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| @@ -153,6 +154,14 @@ static void del_nbp(struct net_bridge_port *p) | |||
| 153 | kobject_uevent(&p->kobj, KOBJ_REMOVE); | 154 | kobject_uevent(&p->kobj, KOBJ_REMOVE); |
| 154 | kobject_del(&p->kobj); | 155 | kobject_del(&p->kobj); |
| 155 | 156 | ||
| 157 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 158 | if (br_devices_support_netpoll(br)) | ||
| 159 | br->dev->priv_flags &= ~IFF_DISABLE_NETPOLL; | ||
| 160 | if (dev->netdev_ops->ndo_netpoll_cleanup) | ||
| 161 | dev->netdev_ops->ndo_netpoll_cleanup(dev); | ||
| 162 | else | ||
| 163 | dev->npinfo = NULL; | ||
| 164 | #endif | ||
| 156 | call_rcu(&p->rcu, destroy_nbp_rcu); | 165 | call_rcu(&p->rcu, destroy_nbp_rcu); |
| 157 | } | 166 | } |
| 158 | 167 | ||
| @@ -165,6 +174,8 @@ static void del_br(struct net_bridge *br, struct list_head *head) | |||
| 165 | del_nbp(p); | 174 | del_nbp(p); |
| 166 | } | 175 | } |
| 167 | 176 | ||
| 177 | br_netpoll_cleanup(br->dev); | ||
| 178 | |||
| 168 | del_timer_sync(&br->gc_timer); | 179 | del_timer_sync(&br->gc_timer); |
| 169 | 180 | ||
| 170 | br_sysfs_delbr(br->dev); | 181 | br_sysfs_delbr(br->dev); |
| @@ -444,6 +455,20 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 444 | 455 | ||
| 445 | kobject_uevent(&p->kobj, KOBJ_ADD); | 456 | kobject_uevent(&p->kobj, KOBJ_ADD); |
| 446 | 457 | ||
| 458 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 459 | if (br_devices_support_netpoll(br)) { | ||
| 460 | br->dev->priv_flags &= ~IFF_DISABLE_NETPOLL; | ||
| 461 | if (br->dev->npinfo) | ||
| 462 | dev->npinfo = br->dev->npinfo; | ||
| 463 | } else if (!(br->dev->priv_flags & IFF_DISABLE_NETPOLL)) { | ||
| 464 | br->dev->priv_flags |= IFF_DISABLE_NETPOLL; | ||
| 465 | printk(KERN_INFO "New device %s does not support netpoll\n", | ||
| 466 | dev->name); | ||
| 467 | printk(KERN_INFO "Disabling netpoll for %s\n", | ||
| 468 | br->dev->name); | ||
| 469 | } | ||
| 470 | #endif | ||
| 471 | |||
| 447 | return 0; | 472 | return 0; |
| 448 | err2: | 473 | err2: |
| 449 | br_fdb_delete_by_port(br, p, 1); | 474 | br_fdb_delete_by_port(br, p, 1); |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 8ccdb8ee3928..c8419e240316 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -24,51 +24,139 @@ | |||
| 24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | #include <linux/timer.h> | 25 | #include <linux/timer.h> |
| 26 | #include <net/ip.h> | 26 | #include <net/ip.h> |
| 27 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 28 | #include <net/ipv6.h> | ||
| 29 | #include <net/mld.h> | ||
| 30 | #include <net/addrconf.h> | ||
| 31 | #include <net/ip6_checksum.h> | ||
| 32 | #endif | ||
| 27 | 33 | ||
| 28 | #include "br_private.h" | 34 | #include "br_private.h" |
| 29 | 35 | ||
| 30 | static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb, __be32 ip) | 36 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 37 | static inline int ipv6_is_local_multicast(const struct in6_addr *addr) | ||
| 31 | { | 38 | { |
| 32 | return jhash_1word(mdb->secret, (u32)ip) & (mdb->max - 1); | 39 | if (ipv6_addr_is_multicast(addr) && |
| 40 | IPV6_ADDR_MC_SCOPE(addr) <= IPV6_ADDR_SCOPE_LINKLOCAL) | ||
| 41 | return 1; | ||
| 42 | return 0; | ||
| 43 | } | ||
| 44 | #endif | ||
| 45 | |||
| 46 | static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) | ||
| 47 | { | ||
| 48 | if (a->proto != b->proto) | ||
| 49 | return 0; | ||
| 50 | switch (a->proto) { | ||
| 51 | case htons(ETH_P_IP): | ||
| 52 | return a->u.ip4 == b->u.ip4; | ||
| 53 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 54 | case htons(ETH_P_IPV6): | ||
| 55 | return ipv6_addr_equal(&a->u.ip6, &b->u.ip6); | ||
| 56 | #endif | ||
| 57 | } | ||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | static inline int __br_ip4_hash(struct net_bridge_mdb_htable *mdb, __be32 ip) | ||
| 62 | { | ||
| 63 | return jhash_1word(mdb->secret, (__force u32)ip) & (mdb->max - 1); | ||
| 64 | } | ||
| 65 | |||
| 66 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 67 | static inline int __br_ip6_hash(struct net_bridge_mdb_htable *mdb, | ||
| 68 | const struct in6_addr *ip) | ||
| 69 | { | ||
| 70 | return jhash2((__force u32 *)ip->s6_addr32, 4, mdb->secret) & (mdb->max - 1); | ||
| 71 | } | ||
| 72 | #endif | ||
| 73 | |||
| 74 | static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb, | ||
| 75 | struct br_ip *ip) | ||
| 76 | { | ||
| 77 | switch (ip->proto) { | ||
| 78 | case htons(ETH_P_IP): | ||
| 79 | return __br_ip4_hash(mdb, ip->u.ip4); | ||
| 80 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 81 | case htons(ETH_P_IPV6): | ||
| 82 | return __br_ip6_hash(mdb, &ip->u.ip6); | ||
| 83 | #endif | ||
| 84 | } | ||
| 85 | return 0; | ||
| 33 | } | 86 | } |
| 34 | 87 | ||
| 35 | static struct net_bridge_mdb_entry *__br_mdb_ip_get( | 88 | static struct net_bridge_mdb_entry *__br_mdb_ip_get( |
| 36 | struct net_bridge_mdb_htable *mdb, __be32 dst, int hash) | 89 | struct net_bridge_mdb_htable *mdb, struct br_ip *dst, int hash) |
| 37 | { | 90 | { |
| 38 | struct net_bridge_mdb_entry *mp; | 91 | struct net_bridge_mdb_entry *mp; |
| 39 | struct hlist_node *p; | 92 | struct hlist_node *p; |
| 40 | 93 | ||
| 41 | hlist_for_each_entry_rcu(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { | 94 | hlist_for_each_entry_rcu(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { |
| 42 | if (dst == mp->addr) | 95 | if (br_ip_equal(&mp->addr, dst)) |
| 43 | return mp; | 96 | return mp; |
| 44 | } | 97 | } |
| 45 | 98 | ||
| 46 | return NULL; | 99 | return NULL; |
| 47 | } | 100 | } |
| 48 | 101 | ||
| 49 | static struct net_bridge_mdb_entry *br_mdb_ip_get( | 102 | static struct net_bridge_mdb_entry *br_mdb_ip4_get( |
| 50 | struct net_bridge_mdb_htable *mdb, __be32 dst) | 103 | struct net_bridge_mdb_htable *mdb, __be32 dst) |
| 51 | { | 104 | { |
| 52 | if (!mdb) | 105 | struct br_ip br_dst; |
| 53 | return NULL; | 106 | |
| 107 | br_dst.u.ip4 = dst; | ||
| 108 | br_dst.proto = htons(ETH_P_IP); | ||
| 109 | |||
| 110 | return __br_mdb_ip_get(mdb, &br_dst, __br_ip4_hash(mdb, dst)); | ||
| 111 | } | ||
| 112 | |||
| 113 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 114 | static struct net_bridge_mdb_entry *br_mdb_ip6_get( | ||
| 115 | struct net_bridge_mdb_htable *mdb, const struct in6_addr *dst) | ||
| 116 | { | ||
| 117 | struct br_ip br_dst; | ||
| 54 | 118 | ||
| 119 | ipv6_addr_copy(&br_dst.u.ip6, dst); | ||
| 120 | br_dst.proto = htons(ETH_P_IPV6); | ||
| 121 | |||
| 122 | return __br_mdb_ip_get(mdb, &br_dst, __br_ip6_hash(mdb, dst)); | ||
| 123 | } | ||
| 124 | #endif | ||
| 125 | |||
| 126 | static struct net_bridge_mdb_entry *br_mdb_ip_get( | ||
| 127 | struct net_bridge_mdb_htable *mdb, struct br_ip *dst) | ||
| 128 | { | ||
| 55 | return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst)); | 129 | return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst)); |
| 56 | } | 130 | } |
| 57 | 131 | ||
| 58 | struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, | 132 | struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, |
| 59 | struct sk_buff *skb) | 133 | struct sk_buff *skb) |
| 60 | { | 134 | { |
| 61 | if (br->multicast_disabled) | 135 | struct net_bridge_mdb_htable *mdb = br->mdb; |
| 136 | struct br_ip ip; | ||
| 137 | |||
| 138 | if (!mdb || br->multicast_disabled) | ||
| 139 | return NULL; | ||
| 140 | |||
| 141 | if (BR_INPUT_SKB_CB(skb)->igmp) | ||
| 62 | return NULL; | 142 | return NULL; |
| 63 | 143 | ||
| 144 | ip.proto = skb->protocol; | ||
| 145 | |||
| 64 | switch (skb->protocol) { | 146 | switch (skb->protocol) { |
| 65 | case htons(ETH_P_IP): | 147 | case htons(ETH_P_IP): |
| 66 | if (BR_INPUT_SKB_CB(skb)->igmp) | 148 | ip.u.ip4 = ip_hdr(skb)->daddr; |
| 67 | break; | 149 | break; |
| 68 | return br_mdb_ip_get(br->mdb, ip_hdr(skb)->daddr); | 150 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 151 | case htons(ETH_P_IPV6): | ||
| 152 | ipv6_addr_copy(&ip.u.ip6, &ipv6_hdr(skb)->daddr); | ||
| 153 | break; | ||
| 154 | #endif | ||
| 155 | default: | ||
| 156 | return NULL; | ||
| 69 | } | 157 | } |
| 70 | 158 | ||
| 71 | return NULL; | 159 | return br_mdb_ip_get(mdb, &ip); |
| 72 | } | 160 | } |
| 73 | 161 | ||
| 74 | static void br_mdb_free(struct rcu_head *head) | 162 | static void br_mdb_free(struct rcu_head *head) |
| @@ -95,7 +183,7 @@ static int br_mdb_copy(struct net_bridge_mdb_htable *new, | |||
| 95 | for (i = 0; i < old->max; i++) | 183 | for (i = 0; i < old->max; i++) |
| 96 | hlist_for_each_entry(mp, p, &old->mhash[i], hlist[old->ver]) | 184 | hlist_for_each_entry(mp, p, &old->mhash[i], hlist[old->ver]) |
| 97 | hlist_add_head(&mp->hlist[new->ver], | 185 | hlist_add_head(&mp->hlist[new->ver], |
| 98 | &new->mhash[br_ip_hash(new, mp->addr)]); | 186 | &new->mhash[br_ip_hash(new, &mp->addr)]); |
| 99 | 187 | ||
| 100 | if (!elasticity) | 188 | if (!elasticity) |
| 101 | return 0; | 189 | return 0; |
| @@ -163,7 +251,7 @@ static void br_multicast_del_pg(struct net_bridge *br, | |||
| 163 | struct net_bridge_port_group *p; | 251 | struct net_bridge_port_group *p; |
| 164 | struct net_bridge_port_group **pp; | 252 | struct net_bridge_port_group **pp; |
| 165 | 253 | ||
| 166 | mp = br_mdb_ip_get(mdb, pg->addr); | 254 | mp = br_mdb_ip_get(mdb, &pg->addr); |
| 167 | if (WARN_ON(!mp)) | 255 | if (WARN_ON(!mp)) |
| 168 | return; | 256 | return; |
| 169 | 257 | ||
| @@ -171,7 +259,7 @@ static void br_multicast_del_pg(struct net_bridge *br, | |||
| 171 | if (p != pg) | 259 | if (p != pg) |
| 172 | continue; | 260 | continue; |
| 173 | 261 | ||
| 174 | *pp = p->next; | 262 | rcu_assign_pointer(*pp, p->next); |
| 175 | hlist_del_init(&p->mglist); | 263 | hlist_del_init(&p->mglist); |
| 176 | del_timer(&p->timer); | 264 | del_timer(&p->timer); |
| 177 | del_timer(&p->query_timer); | 265 | del_timer(&p->query_timer); |
| @@ -249,8 +337,8 @@ out: | |||
| 249 | return 0; | 337 | return 0; |
| 250 | } | 338 | } |
| 251 | 339 | ||
| 252 | static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, | 340 | static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br, |
| 253 | __be32 group) | 341 | __be32 group) |
| 254 | { | 342 | { |
| 255 | struct sk_buff *skb; | 343 | struct sk_buff *skb; |
| 256 | struct igmphdr *ih; | 344 | struct igmphdr *ih; |
| @@ -314,12 +402,104 @@ out: | |||
| 314 | return skb; | 402 | return skb; |
| 315 | } | 403 | } |
| 316 | 404 | ||
| 405 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 406 | static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | ||
| 407 | struct in6_addr *group) | ||
| 408 | { | ||
| 409 | struct sk_buff *skb; | ||
| 410 | struct ipv6hdr *ip6h; | ||
| 411 | struct mld_msg *mldq; | ||
| 412 | struct ethhdr *eth; | ||
| 413 | u8 *hopopt; | ||
| 414 | unsigned long interval; | ||
| 415 | |||
| 416 | skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*eth) + sizeof(*ip6h) + | ||
| 417 | 8 + sizeof(*mldq)); | ||
| 418 | if (!skb) | ||
| 419 | goto out; | ||
| 420 | |||
| 421 | skb->protocol = htons(ETH_P_IPV6); | ||
| 422 | |||
| 423 | /* Ethernet header */ | ||
| 424 | skb_reset_mac_header(skb); | ||
| 425 | eth = eth_hdr(skb); | ||
| 426 | |||
| 427 | memcpy(eth->h_source, br->dev->dev_addr, 6); | ||
| 428 | ipv6_eth_mc_map(group, eth->h_dest); | ||
| 429 | eth->h_proto = htons(ETH_P_IPV6); | ||
| 430 | skb_put(skb, sizeof(*eth)); | ||
| 431 | |||
| 432 | /* IPv6 header + HbH option */ | ||
| 433 | skb_set_network_header(skb, skb->len); | ||
| 434 | ip6h = ipv6_hdr(skb); | ||
| 435 | |||
| 436 | *(__force __be32 *)ip6h = htonl(0x60000000); | ||
| 437 | ip6h->payload_len = 8 + sizeof(*mldq); | ||
| 438 | ip6h->nexthdr = IPPROTO_HOPOPTS; | ||
| 439 | ip6h->hop_limit = 1; | ||
| 440 | ipv6_addr_set(&ip6h->saddr, 0, 0, 0, 0); | ||
| 441 | ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1)); | ||
| 442 | |||
| 443 | hopopt = (u8 *)(ip6h + 1); | ||
| 444 | hopopt[0] = IPPROTO_ICMPV6; /* next hdr */ | ||
| 445 | hopopt[1] = 0; /* length of HbH */ | ||
| 446 | hopopt[2] = IPV6_TLV_ROUTERALERT; /* Router Alert */ | ||
| 447 | hopopt[3] = 2; /* Length of RA Option */ | ||
| 448 | hopopt[4] = 0; /* Type = 0x0000 (MLD) */ | ||
| 449 | hopopt[5] = 0; | ||
| 450 | hopopt[6] = IPV6_TLV_PAD0; /* Pad0 */ | ||
| 451 | hopopt[7] = IPV6_TLV_PAD0; /* Pad0 */ | ||
| 452 | |||
| 453 | skb_put(skb, sizeof(*ip6h) + 8); | ||
| 454 | |||
| 455 | /* ICMPv6 */ | ||
| 456 | skb_set_transport_header(skb, skb->len); | ||
| 457 | mldq = (struct mld_msg *) icmp6_hdr(skb); | ||
| 458 | |||
| 459 | interval = ipv6_addr_any(group) ? br->multicast_last_member_interval : | ||
| 460 | br->multicast_query_response_interval; | ||
| 461 | |||
| 462 | mldq->mld_type = ICMPV6_MGM_QUERY; | ||
| 463 | mldq->mld_code = 0; | ||
| 464 | mldq->mld_cksum = 0; | ||
| 465 | mldq->mld_maxdelay = htons((u16)jiffies_to_msecs(interval)); | ||
| 466 | mldq->mld_reserved = 0; | ||
| 467 | ipv6_addr_copy(&mldq->mld_mca, group); | ||
| 468 | |||
| 469 | /* checksum */ | ||
| 470 | mldq->mld_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, | ||
| 471 | sizeof(*mldq), IPPROTO_ICMPV6, | ||
| 472 | csum_partial(mldq, | ||
| 473 | sizeof(*mldq), 0)); | ||
| 474 | skb_put(skb, sizeof(*mldq)); | ||
| 475 | |||
| 476 | __skb_pull(skb, sizeof(*eth)); | ||
| 477 | |||
| 478 | out: | ||
| 479 | return skb; | ||
| 480 | } | ||
| 481 | #endif | ||
| 482 | |||
| 483 | static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, | ||
| 484 | struct br_ip *addr) | ||
| 485 | { | ||
| 486 | switch (addr->proto) { | ||
| 487 | case htons(ETH_P_IP): | ||
| 488 | return br_ip4_multicast_alloc_query(br, addr->u.ip4); | ||
| 489 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 490 | case htons(ETH_P_IPV6): | ||
| 491 | return br_ip6_multicast_alloc_query(br, &addr->u.ip6); | ||
| 492 | #endif | ||
| 493 | } | ||
| 494 | return NULL; | ||
| 495 | } | ||
| 496 | |||
| 317 | static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp) | 497 | static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp) |
| 318 | { | 498 | { |
| 319 | struct net_bridge *br = mp->br; | 499 | struct net_bridge *br = mp->br; |
| 320 | struct sk_buff *skb; | 500 | struct sk_buff *skb; |
| 321 | 501 | ||
| 322 | skb = br_multicast_alloc_query(br, mp->addr); | 502 | skb = br_multicast_alloc_query(br, &mp->addr); |
| 323 | if (!skb) | 503 | if (!skb) |
| 324 | goto timer; | 504 | goto timer; |
| 325 | 505 | ||
| @@ -353,7 +533,7 @@ static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg) | |||
| 353 | struct net_bridge *br = port->br; | 533 | struct net_bridge *br = port->br; |
| 354 | struct sk_buff *skb; | 534 | struct sk_buff *skb; |
| 355 | 535 | ||
| 356 | skb = br_multicast_alloc_query(br, pg->addr); | 536 | skb = br_multicast_alloc_query(br, &pg->addr); |
| 357 | if (!skb) | 537 | if (!skb) |
| 358 | goto timer; | 538 | goto timer; |
| 359 | 539 | ||
| @@ -383,8 +563,8 @@ out: | |||
| 383 | } | 563 | } |
| 384 | 564 | ||
| 385 | static struct net_bridge_mdb_entry *br_multicast_get_group( | 565 | static struct net_bridge_mdb_entry *br_multicast_get_group( |
| 386 | struct net_bridge *br, struct net_bridge_port *port, __be32 group, | 566 | struct net_bridge *br, struct net_bridge_port *port, |
| 387 | int hash) | 567 | struct br_ip *group, int hash) |
| 388 | { | 568 | { |
| 389 | struct net_bridge_mdb_htable *mdb = br->mdb; | 569 | struct net_bridge_mdb_htable *mdb = br->mdb; |
| 390 | struct net_bridge_mdb_entry *mp; | 570 | struct net_bridge_mdb_entry *mp; |
| @@ -396,9 +576,8 @@ static struct net_bridge_mdb_entry *br_multicast_get_group( | |||
| 396 | 576 | ||
| 397 | hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { | 577 | hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { |
| 398 | count++; | 578 | count++; |
| 399 | if (unlikely(group == mp->addr)) { | 579 | if (unlikely(br_ip_equal(group, &mp->addr))) |
| 400 | return mp; | 580 | return mp; |
| 401 | } | ||
| 402 | } | 581 | } |
| 403 | 582 | ||
| 404 | elasticity = 0; | 583 | elasticity = 0; |
| @@ -463,7 +642,8 @@ err: | |||
| 463 | } | 642 | } |
| 464 | 643 | ||
| 465 | static struct net_bridge_mdb_entry *br_multicast_new_group( | 644 | static struct net_bridge_mdb_entry *br_multicast_new_group( |
| 466 | struct net_bridge *br, struct net_bridge_port *port, __be32 group) | 645 | struct net_bridge *br, struct net_bridge_port *port, |
| 646 | struct br_ip *group) | ||
| 467 | { | 647 | { |
| 468 | struct net_bridge_mdb_htable *mdb = br->mdb; | 648 | struct net_bridge_mdb_htable *mdb = br->mdb; |
| 469 | struct net_bridge_mdb_entry *mp; | 649 | struct net_bridge_mdb_entry *mp; |
| @@ -496,7 +676,7 @@ rehash: | |||
| 496 | goto out; | 676 | goto out; |
| 497 | 677 | ||
| 498 | mp->br = br; | 678 | mp->br = br; |
| 499 | mp->addr = group; | 679 | mp->addr = *group; |
| 500 | setup_timer(&mp->timer, br_multicast_group_expired, | 680 | setup_timer(&mp->timer, br_multicast_group_expired, |
| 501 | (unsigned long)mp); | 681 | (unsigned long)mp); |
| 502 | setup_timer(&mp->query_timer, br_multicast_group_query_expired, | 682 | setup_timer(&mp->query_timer, br_multicast_group_query_expired, |
| @@ -510,7 +690,8 @@ out: | |||
| 510 | } | 690 | } |
| 511 | 691 | ||
| 512 | static int br_multicast_add_group(struct net_bridge *br, | 692 | static int br_multicast_add_group(struct net_bridge *br, |
| 513 | struct net_bridge_port *port, __be32 group) | 693 | struct net_bridge_port *port, |
| 694 | struct br_ip *group) | ||
| 514 | { | 695 | { |
| 515 | struct net_bridge_mdb_entry *mp; | 696 | struct net_bridge_mdb_entry *mp; |
| 516 | struct net_bridge_port_group *p; | 697 | struct net_bridge_port_group *p; |
| @@ -518,9 +699,6 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
| 518 | unsigned long now = jiffies; | 699 | unsigned long now = jiffies; |
| 519 | int err; | 700 | int err; |
| 520 | 701 | ||
| 521 | if (ipv4_is_local_multicast(group)) | ||
| 522 | return 0; | ||
| 523 | |||
| 524 | spin_lock(&br->multicast_lock); | 702 | spin_lock(&br->multicast_lock); |
| 525 | if (!netif_running(br->dev) || | 703 | if (!netif_running(br->dev) || |
| 526 | (port && port->state == BR_STATE_DISABLED)) | 704 | (port && port->state == BR_STATE_DISABLED)) |
| @@ -549,7 +727,7 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
| 549 | if (unlikely(!p)) | 727 | if (unlikely(!p)) |
| 550 | goto err; | 728 | goto err; |
| 551 | 729 | ||
| 552 | p->addr = group; | 730 | p->addr = *group; |
| 553 | p->port = port; | 731 | p->port = port; |
| 554 | p->next = *pp; | 732 | p->next = *pp; |
| 555 | hlist_add_head(&p->mglist, &port->mglist); | 733 | hlist_add_head(&p->mglist, &port->mglist); |
| @@ -570,6 +748,38 @@ err: | |||
| 570 | return err; | 748 | return err; |
| 571 | } | 749 | } |
| 572 | 750 | ||
| 751 | static int br_ip4_multicast_add_group(struct net_bridge *br, | ||
| 752 | struct net_bridge_port *port, | ||
| 753 | __be32 group) | ||
| 754 | { | ||
| 755 | struct br_ip br_group; | ||
| 756 | |||
| 757 | if (ipv4_is_local_multicast(group)) | ||
| 758 | return 0; | ||
| 759 | |||
| 760 | br_group.u.ip4 = group; | ||
| 761 | br_group.proto = htons(ETH_P_IP); | ||
| 762 | |||
| 763 | return br_multicast_add_group(br, port, &br_group); | ||
| 764 | } | ||
| 765 | |||
| 766 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 767 | static int br_ip6_multicast_add_group(struct net_bridge *br, | ||
| 768 | struct net_bridge_port *port, | ||
| 769 | const struct in6_addr *group) | ||
| 770 | { | ||
| 771 | struct br_ip br_group; | ||
| 772 | |||
| 773 | if (ipv6_is_local_multicast(group)) | ||
| 774 | return 0; | ||
| 775 | |||
| 776 | ipv6_addr_copy(&br_group.u.ip6, group); | ||
| 777 | br_group.proto = htons(ETH_P_IP); | ||
| 778 | |||
| 779 | return br_multicast_add_group(br, port, &br_group); | ||
| 780 | } | ||
| 781 | #endif | ||
| 782 | |||
| 573 | static void br_multicast_router_expired(unsigned long data) | 783 | static void br_multicast_router_expired(unsigned long data) |
| 574 | { | 784 | { |
| 575 | struct net_bridge_port *port = (void *)data; | 785 | struct net_bridge_port *port = (void *)data; |
| @@ -591,19 +801,15 @@ static void br_multicast_local_router_expired(unsigned long data) | |||
| 591 | { | 801 | { |
| 592 | } | 802 | } |
| 593 | 803 | ||
| 594 | static void br_multicast_send_query(struct net_bridge *br, | 804 | static void __br_multicast_send_query(struct net_bridge *br, |
| 595 | struct net_bridge_port *port, u32 sent) | 805 | struct net_bridge_port *port, |
| 806 | struct br_ip *ip) | ||
| 596 | { | 807 | { |
| 597 | unsigned long time; | ||
| 598 | struct sk_buff *skb; | 808 | struct sk_buff *skb; |
| 599 | 809 | ||
| 600 | if (!netif_running(br->dev) || br->multicast_disabled || | 810 | skb = br_multicast_alloc_query(br, ip); |
| 601 | timer_pending(&br->multicast_querier_timer)) | ||
| 602 | return; | ||
| 603 | |||
| 604 | skb = br_multicast_alloc_query(br, 0); | ||
| 605 | if (!skb) | 811 | if (!skb) |
| 606 | goto timer; | 812 | return; |
| 607 | 813 | ||
| 608 | if (port) { | 814 | if (port) { |
| 609 | __skb_push(skb, sizeof(struct ethhdr)); | 815 | __skb_push(skb, sizeof(struct ethhdr)); |
| @@ -612,8 +818,28 @@ static void br_multicast_send_query(struct net_bridge *br, | |||
| 612 | dev_queue_xmit); | 818 | dev_queue_xmit); |
| 613 | } else | 819 | } else |
| 614 | netif_rx(skb); | 820 | netif_rx(skb); |
| 821 | } | ||
| 822 | |||
| 823 | static void br_multicast_send_query(struct net_bridge *br, | ||
| 824 | struct net_bridge_port *port, u32 sent) | ||
| 825 | { | ||
| 826 | unsigned long time; | ||
| 827 | struct br_ip br_group; | ||
| 828 | |||
| 829 | if (!netif_running(br->dev) || br->multicast_disabled || | ||
| 830 | timer_pending(&br->multicast_querier_timer)) | ||
| 831 | return; | ||
| 832 | |||
| 833 | memset(&br_group.u, 0, sizeof(br_group.u)); | ||
| 834 | |||
| 835 | br_group.proto = htons(ETH_P_IP); | ||
| 836 | __br_multicast_send_query(br, port, &br_group); | ||
| 837 | |||
| 838 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 839 | br_group.proto = htons(ETH_P_IPV6); | ||
| 840 | __br_multicast_send_query(br, port, &br_group); | ||
| 841 | #endif | ||
| 615 | 842 | ||
| 616 | timer: | ||
| 617 | time = jiffies; | 843 | time = jiffies; |
| 618 | time += sent < br->multicast_startup_query_count ? | 844 | time += sent < br->multicast_startup_query_count ? |
| 619 | br->multicast_startup_query_interval : | 845 | br->multicast_startup_query_interval : |
| @@ -698,9 +924,9 @@ void br_multicast_disable_port(struct net_bridge_port *port) | |||
| 698 | spin_unlock(&br->multicast_lock); | 924 | spin_unlock(&br->multicast_lock); |
| 699 | } | 925 | } |
| 700 | 926 | ||
| 701 | static int br_multicast_igmp3_report(struct net_bridge *br, | 927 | static int br_ip4_multicast_igmp3_report(struct net_bridge *br, |
| 702 | struct net_bridge_port *port, | 928 | struct net_bridge_port *port, |
| 703 | struct sk_buff *skb) | 929 | struct sk_buff *skb) |
| 704 | { | 930 | { |
| 705 | struct igmpv3_report *ih; | 931 | struct igmpv3_report *ih; |
| 706 | struct igmpv3_grec *grec; | 932 | struct igmpv3_grec *grec; |
| @@ -727,7 +953,7 @@ static int br_multicast_igmp3_report(struct net_bridge *br, | |||
| 727 | group = grec->grec_mca; | 953 | group = grec->grec_mca; |
| 728 | type = grec->grec_type; | 954 | type = grec->grec_type; |
| 729 | 955 | ||
| 730 | len += grec->grec_nsrcs * 4; | 956 | len += ntohs(grec->grec_nsrcs) * 4; |
| 731 | if (!pskb_may_pull(skb, len)) | 957 | if (!pskb_may_pull(skb, len)) |
| 732 | return -EINVAL; | 958 | return -EINVAL; |
| 733 | 959 | ||
| @@ -745,7 +971,7 @@ static int br_multicast_igmp3_report(struct net_bridge *br, | |||
| 745 | continue; | 971 | continue; |
| 746 | } | 972 | } |
| 747 | 973 | ||
| 748 | err = br_multicast_add_group(br, port, group); | 974 | err = br_ip4_multicast_add_group(br, port, group); |
| 749 | if (err) | 975 | if (err) |
| 750 | break; | 976 | break; |
| 751 | } | 977 | } |
| @@ -753,24 +979,87 @@ static int br_multicast_igmp3_report(struct net_bridge *br, | |||
| 753 | return err; | 979 | return err; |
| 754 | } | 980 | } |
| 755 | 981 | ||
| 982 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 983 | static int br_ip6_multicast_mld2_report(struct net_bridge *br, | ||
| 984 | struct net_bridge_port *port, | ||
| 985 | struct sk_buff *skb) | ||
| 986 | { | ||
| 987 | struct icmp6hdr *icmp6h; | ||
| 988 | struct mld2_grec *grec; | ||
| 989 | int i; | ||
| 990 | int len; | ||
| 991 | int num; | ||
| 992 | int err = 0; | ||
| 993 | |||
| 994 | if (!pskb_may_pull(skb, sizeof(*icmp6h))) | ||
| 995 | return -EINVAL; | ||
| 996 | |||
| 997 | icmp6h = icmp6_hdr(skb); | ||
| 998 | num = ntohs(icmp6h->icmp6_dataun.un_data16[1]); | ||
| 999 | len = sizeof(*icmp6h); | ||
| 1000 | |||
| 1001 | for (i = 0; i < num; i++) { | ||
| 1002 | __be16 *nsrcs, _nsrcs; | ||
| 1003 | |||
| 1004 | nsrcs = skb_header_pointer(skb, | ||
| 1005 | len + offsetof(struct mld2_grec, | ||
| 1006 | grec_mca), | ||
| 1007 | sizeof(_nsrcs), &_nsrcs); | ||
| 1008 | if (!nsrcs) | ||
| 1009 | return -EINVAL; | ||
| 1010 | |||
| 1011 | if (!pskb_may_pull(skb, | ||
| 1012 | len + sizeof(*grec) + | ||
| 1013 | sizeof(struct in6_addr) * (*nsrcs))) | ||
| 1014 | return -EINVAL; | ||
| 1015 | |||
| 1016 | grec = (struct mld2_grec *)(skb->data + len); | ||
| 1017 | len += sizeof(*grec) + sizeof(struct in6_addr) * (*nsrcs); | ||
| 1018 | |||
| 1019 | /* We treat these as MLDv1 reports for now. */ | ||
| 1020 | switch (grec->grec_type) { | ||
| 1021 | case MLD2_MODE_IS_INCLUDE: | ||
| 1022 | case MLD2_MODE_IS_EXCLUDE: | ||
| 1023 | case MLD2_CHANGE_TO_INCLUDE: | ||
| 1024 | case MLD2_CHANGE_TO_EXCLUDE: | ||
| 1025 | case MLD2_ALLOW_NEW_SOURCES: | ||
| 1026 | case MLD2_BLOCK_OLD_SOURCES: | ||
| 1027 | break; | ||
| 1028 | |||
| 1029 | default: | ||
| 1030 | continue; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | err = br_ip6_multicast_add_group(br, port, &grec->grec_mca); | ||
| 1034 | if (!err) | ||
| 1035 | break; | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | return err; | ||
| 1039 | } | ||
| 1040 | #endif | ||
| 1041 | |||
| 1042 | /* | ||
| 1043 | * Add port to rotuer_list | ||
| 1044 | * list is maintained ordered by pointer value | ||
| 1045 | * and locked by br->multicast_lock and RCU | ||
| 1046 | */ | ||
| 756 | static void br_multicast_add_router(struct net_bridge *br, | 1047 | static void br_multicast_add_router(struct net_bridge *br, |
| 757 | struct net_bridge_port *port) | 1048 | struct net_bridge_port *port) |
| 758 | { | 1049 | { |
| 759 | struct hlist_node *p; | 1050 | struct net_bridge_port *p; |
| 760 | struct hlist_node **h; | 1051 | struct hlist_node *n, *slot = NULL; |
| 761 | 1052 | ||
| 762 | for (h = &br->router_list.first; | 1053 | hlist_for_each_entry(p, n, &br->router_list, rlist) { |
| 763 | (p = *h) && | 1054 | if ((unsigned long) port >= (unsigned long) p) |
| 764 | (unsigned long)container_of(p, struct net_bridge_port, rlist) > | 1055 | break; |
| 765 | (unsigned long)port; | 1056 | slot = n; |
| 766 | h = &p->next) | 1057 | } |
| 767 | ; | 1058 | |
| 768 | 1059 | if (slot) | |
| 769 | port->rlist.pprev = h; | 1060 | hlist_add_after_rcu(slot, &port->rlist); |
| 770 | port->rlist.next = p; | 1061 | else |
| 771 | rcu_assign_pointer(*h, &port->rlist); | 1062 | hlist_add_head_rcu(&port->rlist, &br->router_list); |
| 772 | if (p) | ||
| 773 | p->pprev = &port->rlist.next; | ||
| 774 | } | 1063 | } |
| 775 | 1064 | ||
| 776 | static void br_multicast_mark_router(struct net_bridge *br, | 1065 | static void br_multicast_mark_router(struct net_bridge *br, |
| @@ -800,7 +1089,7 @@ timer: | |||
| 800 | 1089 | ||
| 801 | static void br_multicast_query_received(struct net_bridge *br, | 1090 | static void br_multicast_query_received(struct net_bridge *br, |
| 802 | struct net_bridge_port *port, | 1091 | struct net_bridge_port *port, |
| 803 | __be32 saddr) | 1092 | int saddr) |
| 804 | { | 1093 | { |
| 805 | if (saddr) | 1094 | if (saddr) |
| 806 | mod_timer(&br->multicast_querier_timer, | 1095 | mod_timer(&br->multicast_querier_timer, |
| @@ -811,9 +1100,9 @@ static void br_multicast_query_received(struct net_bridge *br, | |||
| 811 | br_multicast_mark_router(br, port); | 1100 | br_multicast_mark_router(br, port); |
| 812 | } | 1101 | } |
| 813 | 1102 | ||
| 814 | static int br_multicast_query(struct net_bridge *br, | 1103 | static int br_ip4_multicast_query(struct net_bridge *br, |
| 815 | struct net_bridge_port *port, | 1104 | struct net_bridge_port *port, |
| 816 | struct sk_buff *skb) | 1105 | struct sk_buff *skb) |
| 817 | { | 1106 | { |
| 818 | struct iphdr *iph = ip_hdr(skb); | 1107 | struct iphdr *iph = ip_hdr(skb); |
| 819 | struct igmphdr *ih = igmp_hdr(skb); | 1108 | struct igmphdr *ih = igmp_hdr(skb); |
| @@ -831,7 +1120,7 @@ static int br_multicast_query(struct net_bridge *br, | |||
| 831 | (port && port->state == BR_STATE_DISABLED)) | 1120 | (port && port->state == BR_STATE_DISABLED)) |
| 832 | goto out; | 1121 | goto out; |
| 833 | 1122 | ||
| 834 | br_multicast_query_received(br, port, iph->saddr); | 1123 | br_multicast_query_received(br, port, !!iph->saddr); |
| 835 | 1124 | ||
| 836 | group = ih->group; | 1125 | group = ih->group; |
| 837 | 1126 | ||
| @@ -859,7 +1148,7 @@ static int br_multicast_query(struct net_bridge *br, | |||
| 859 | if (!group) | 1148 | if (!group) |
| 860 | goto out; | 1149 | goto out; |
| 861 | 1150 | ||
| 862 | mp = br_mdb_ip_get(br->mdb, group); | 1151 | mp = br_mdb_ip4_get(br->mdb, group); |
| 863 | if (!mp) | 1152 | if (!mp) |
| 864 | goto out; | 1153 | goto out; |
| 865 | 1154 | ||
| @@ -883,9 +1172,78 @@ out: | |||
| 883 | return err; | 1172 | return err; |
| 884 | } | 1173 | } |
| 885 | 1174 | ||
| 1175 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 1176 | static int br_ip6_multicast_query(struct net_bridge *br, | ||
| 1177 | struct net_bridge_port *port, | ||
| 1178 | struct sk_buff *skb) | ||
| 1179 | { | ||
| 1180 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | ||
| 1181 | struct mld_msg *mld = (struct mld_msg *) icmp6_hdr(skb); | ||
| 1182 | struct net_bridge_mdb_entry *mp; | ||
| 1183 | struct mld2_query *mld2q; | ||
| 1184 | struct net_bridge_port_group *p, **pp; | ||
| 1185 | unsigned long max_delay; | ||
| 1186 | unsigned long now = jiffies; | ||
| 1187 | struct in6_addr *group = NULL; | ||
| 1188 | int err = 0; | ||
| 1189 | |||
| 1190 | spin_lock(&br->multicast_lock); | ||
| 1191 | if (!netif_running(br->dev) || | ||
| 1192 | (port && port->state == BR_STATE_DISABLED)) | ||
| 1193 | goto out; | ||
| 1194 | |||
| 1195 | br_multicast_query_received(br, port, !ipv6_addr_any(&ip6h->saddr)); | ||
| 1196 | |||
| 1197 | if (skb->len == sizeof(*mld)) { | ||
| 1198 | if (!pskb_may_pull(skb, sizeof(*mld))) { | ||
| 1199 | err = -EINVAL; | ||
| 1200 | goto out; | ||
| 1201 | } | ||
| 1202 | mld = (struct mld_msg *) icmp6_hdr(skb); | ||
| 1203 | max_delay = msecs_to_jiffies(htons(mld->mld_maxdelay)); | ||
| 1204 | if (max_delay) | ||
| 1205 | group = &mld->mld_mca; | ||
| 1206 | } else if (skb->len >= sizeof(*mld2q)) { | ||
| 1207 | if (!pskb_may_pull(skb, sizeof(*mld2q))) { | ||
| 1208 | err = -EINVAL; | ||
| 1209 | goto out; | ||
| 1210 | } | ||
| 1211 | mld2q = (struct mld2_query *)icmp6_hdr(skb); | ||
| 1212 | if (!mld2q->mld2q_nsrcs) | ||
| 1213 | group = &mld2q->mld2q_mca; | ||
| 1214 | max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(mld2q->mld2q_mrc) : 1; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | if (!group) | ||
| 1218 | goto out; | ||
| 1219 | |||
| 1220 | mp = br_mdb_ip6_get(br->mdb, group); | ||
| 1221 | if (!mp) | ||
| 1222 | goto out; | ||
| 1223 | |||
| 1224 | max_delay *= br->multicast_last_member_count; | ||
| 1225 | if (!hlist_unhashed(&mp->mglist) && | ||
| 1226 | (timer_pending(&mp->timer) ? | ||
| 1227 | time_after(mp->timer.expires, now + max_delay) : | ||
| 1228 | try_to_del_timer_sync(&mp->timer) >= 0)) | ||
| 1229 | mod_timer(&mp->timer, now + max_delay); | ||
| 1230 | |||
| 1231 | for (pp = &mp->ports; (p = *pp); pp = &p->next) { | ||
| 1232 | if (timer_pending(&p->timer) ? | ||
| 1233 | time_after(p->timer.expires, now + max_delay) : | ||
| 1234 | try_to_del_timer_sync(&p->timer) >= 0) | ||
| 1235 | mod_timer(&mp->timer, now + max_delay); | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | out: | ||
| 1239 | spin_unlock(&br->multicast_lock); | ||
| 1240 | return err; | ||
| 1241 | } | ||
| 1242 | #endif | ||
| 1243 | |||
| 886 | static void br_multicast_leave_group(struct net_bridge *br, | 1244 | static void br_multicast_leave_group(struct net_bridge *br, |
| 887 | struct net_bridge_port *port, | 1245 | struct net_bridge_port *port, |
| 888 | __be32 group) | 1246 | struct br_ip *group) |
| 889 | { | 1247 | { |
| 890 | struct net_bridge_mdb_htable *mdb; | 1248 | struct net_bridge_mdb_htable *mdb; |
| 891 | struct net_bridge_mdb_entry *mp; | 1249 | struct net_bridge_mdb_entry *mp; |
| @@ -893,9 +1251,6 @@ static void br_multicast_leave_group(struct net_bridge *br, | |||
| 893 | unsigned long now; | 1251 | unsigned long now; |
| 894 | unsigned long time; | 1252 | unsigned long time; |
| 895 | 1253 | ||
| 896 | if (ipv4_is_local_multicast(group)) | ||
| 897 | return; | ||
| 898 | |||
| 899 | spin_lock(&br->multicast_lock); | 1254 | spin_lock(&br->multicast_lock); |
| 900 | if (!netif_running(br->dev) || | 1255 | if (!netif_running(br->dev) || |
| 901 | (port && port->state == BR_STATE_DISABLED) || | 1256 | (port && port->state == BR_STATE_DISABLED) || |
| @@ -946,6 +1301,38 @@ out: | |||
| 946 | spin_unlock(&br->multicast_lock); | 1301 | spin_unlock(&br->multicast_lock); |
| 947 | } | 1302 | } |
| 948 | 1303 | ||
| 1304 | static void br_ip4_multicast_leave_group(struct net_bridge *br, | ||
| 1305 | struct net_bridge_port *port, | ||
| 1306 | __be32 group) | ||
| 1307 | { | ||
| 1308 | struct br_ip br_group; | ||
| 1309 | |||
| 1310 | if (ipv4_is_local_multicast(group)) | ||
| 1311 | return; | ||
| 1312 | |||
| 1313 | br_group.u.ip4 = group; | ||
| 1314 | br_group.proto = htons(ETH_P_IP); | ||
| 1315 | |||
| 1316 | br_multicast_leave_group(br, port, &br_group); | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 1320 | static void br_ip6_multicast_leave_group(struct net_bridge *br, | ||
| 1321 | struct net_bridge_port *port, | ||
| 1322 | const struct in6_addr *group) | ||
| 1323 | { | ||
| 1324 | struct br_ip br_group; | ||
| 1325 | |||
| 1326 | if (ipv6_is_local_multicast(group)) | ||
| 1327 | return; | ||
| 1328 | |||
| 1329 | ipv6_addr_copy(&br_group.u.ip6, group); | ||
| 1330 | br_group.proto = htons(ETH_P_IPV6); | ||
| 1331 | |||
| 1332 | br_multicast_leave_group(br, port, &br_group); | ||
| 1333 | } | ||
| 1334 | #endif | ||
| 1335 | |||
| 949 | static int br_multicast_ipv4_rcv(struct net_bridge *br, | 1336 | static int br_multicast_ipv4_rcv(struct net_bridge *br, |
| 950 | struct net_bridge_port *port, | 1337 | struct net_bridge_port *port, |
| 951 | struct sk_buff *skb) | 1338 | struct sk_buff *skb) |
| @@ -957,9 +1344,6 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
| 957 | unsigned offset; | 1344 | unsigned offset; |
| 958 | int err; | 1345 | int err; |
| 959 | 1346 | ||
| 960 | BR_INPUT_SKB_CB(skb)->igmp = 0; | ||
| 961 | BR_INPUT_SKB_CB(skb)->mrouters_only = 0; | ||
| 962 | |||
| 963 | /* We treat OOM as packet loss for now. */ | 1347 | /* We treat OOM as packet loss for now. */ |
| 964 | if (!pskb_may_pull(skb, sizeof(*iph))) | 1348 | if (!pskb_may_pull(skb, sizeof(*iph))) |
| 965 | return -EINVAL; | 1349 | return -EINVAL; |
| @@ -1023,16 +1407,16 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
| 1023 | case IGMP_HOST_MEMBERSHIP_REPORT: | 1407 | case IGMP_HOST_MEMBERSHIP_REPORT: |
| 1024 | case IGMPV2_HOST_MEMBERSHIP_REPORT: | 1408 | case IGMPV2_HOST_MEMBERSHIP_REPORT: |
| 1025 | BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; | 1409 | BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; |
| 1026 | err = br_multicast_add_group(br, port, ih->group); | 1410 | err = br_ip4_multicast_add_group(br, port, ih->group); |
| 1027 | break; | 1411 | break; |
| 1028 | case IGMPV3_HOST_MEMBERSHIP_REPORT: | 1412 | case IGMPV3_HOST_MEMBERSHIP_REPORT: |
| 1029 | err = br_multicast_igmp3_report(br, port, skb2); | 1413 | err = br_ip4_multicast_igmp3_report(br, port, skb2); |
| 1030 | break; | 1414 | break; |
| 1031 | case IGMP_HOST_MEMBERSHIP_QUERY: | 1415 | case IGMP_HOST_MEMBERSHIP_QUERY: |
| 1032 | err = br_multicast_query(br, port, skb2); | 1416 | err = br_ip4_multicast_query(br, port, skb2); |
| 1033 | break; | 1417 | break; |
| 1034 | case IGMP_HOST_LEAVE_MESSAGE: | 1418 | case IGMP_HOST_LEAVE_MESSAGE: |
| 1035 | br_multicast_leave_group(br, port, ih->group); | 1419 | br_ip4_multicast_leave_group(br, port, ih->group); |
| 1036 | break; | 1420 | break; |
| 1037 | } | 1421 | } |
| 1038 | 1422 | ||
| @@ -1044,15 +1428,139 @@ err_out: | |||
| 1044 | return err; | 1428 | return err; |
| 1045 | } | 1429 | } |
| 1046 | 1430 | ||
| 1431 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 1432 | static int br_multicast_ipv6_rcv(struct net_bridge *br, | ||
| 1433 | struct net_bridge_port *port, | ||
| 1434 | struct sk_buff *skb) | ||
| 1435 | { | ||
| 1436 | struct sk_buff *skb2 = skb; | ||
| 1437 | struct ipv6hdr *ip6h; | ||
| 1438 | struct icmp6hdr *icmp6h; | ||
| 1439 | u8 nexthdr; | ||
| 1440 | unsigned len; | ||
| 1441 | unsigned offset; | ||
| 1442 | int err; | ||
| 1443 | |||
| 1444 | if (!pskb_may_pull(skb, sizeof(*ip6h))) | ||
| 1445 | return -EINVAL; | ||
| 1446 | |||
| 1447 | ip6h = ipv6_hdr(skb); | ||
| 1448 | |||
| 1449 | /* | ||
| 1450 | * We're interested in MLD messages only. | ||
| 1451 | * - Version is 6 | ||
| 1452 | * - MLD has always Router Alert hop-by-hop option | ||
| 1453 | * - But we do not support jumbrograms. | ||
| 1454 | */ | ||
| 1455 | if (ip6h->version != 6 || | ||
| 1456 | ip6h->nexthdr != IPPROTO_HOPOPTS || | ||
| 1457 | ip6h->payload_len == 0) | ||
| 1458 | return 0; | ||
| 1459 | |||
| 1460 | len = ntohs(ip6h->payload_len); | ||
| 1461 | if (skb->len < len) | ||
| 1462 | return -EINVAL; | ||
| 1463 | |||
| 1464 | nexthdr = ip6h->nexthdr; | ||
| 1465 | offset = ipv6_skip_exthdr(skb, sizeof(*ip6h), &nexthdr); | ||
| 1466 | |||
| 1467 | if (offset < 0 || nexthdr != IPPROTO_ICMPV6) | ||
| 1468 | return 0; | ||
| 1469 | |||
| 1470 | /* Okay, we found ICMPv6 header */ | ||
| 1471 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
| 1472 | if (!skb2) | ||
| 1473 | return -ENOMEM; | ||
| 1474 | |||
| 1475 | len -= offset - skb_network_offset(skb2); | ||
| 1476 | |||
| 1477 | __skb_pull(skb2, offset); | ||
| 1478 | skb_reset_transport_header(skb2); | ||
| 1479 | |||
| 1480 | err = -EINVAL; | ||
| 1481 | if (!pskb_may_pull(skb2, sizeof(*icmp6h))) | ||
| 1482 | goto out; | ||
| 1483 | |||
| 1484 | icmp6h = icmp6_hdr(skb2); | ||
| 1485 | |||
| 1486 | switch (icmp6h->icmp6_type) { | ||
| 1487 | case ICMPV6_MGM_QUERY: | ||
| 1488 | case ICMPV6_MGM_REPORT: | ||
| 1489 | case ICMPV6_MGM_REDUCTION: | ||
| 1490 | case ICMPV6_MLD2_REPORT: | ||
| 1491 | break; | ||
| 1492 | default: | ||
| 1493 | err = 0; | ||
| 1494 | goto out; | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | /* Okay, we found MLD message. Check further. */ | ||
| 1498 | if (skb2->len > len) { | ||
| 1499 | err = pskb_trim_rcsum(skb2, len); | ||
| 1500 | if (err) | ||
| 1501 | goto out; | ||
| 1502 | } | ||
| 1503 | |||
| 1504 | switch (skb2->ip_summed) { | ||
| 1505 | case CHECKSUM_COMPLETE: | ||
| 1506 | if (!csum_fold(skb2->csum)) | ||
| 1507 | break; | ||
| 1508 | /*FALLTHROUGH*/ | ||
| 1509 | case CHECKSUM_NONE: | ||
| 1510 | skb2->csum = 0; | ||
| 1511 | if (skb_checksum_complete(skb2)) | ||
| 1512 | goto out; | ||
| 1513 | } | ||
| 1514 | |||
| 1515 | err = 0; | ||
| 1516 | |||
| 1517 | BR_INPUT_SKB_CB(skb)->igmp = 1; | ||
| 1518 | |||
| 1519 | switch (icmp6h->icmp6_type) { | ||
| 1520 | case ICMPV6_MGM_REPORT: | ||
| 1521 | { | ||
| 1522 | struct mld_msg *mld = (struct mld_msg *)icmp6h; | ||
| 1523 | BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; | ||
| 1524 | err = br_ip6_multicast_add_group(br, port, &mld->mld_mca); | ||
| 1525 | break; | ||
| 1526 | } | ||
| 1527 | case ICMPV6_MLD2_REPORT: | ||
| 1528 | err = br_ip6_multicast_mld2_report(br, port, skb2); | ||
| 1529 | break; | ||
| 1530 | case ICMPV6_MGM_QUERY: | ||
| 1531 | err = br_ip6_multicast_query(br, port, skb2); | ||
| 1532 | break; | ||
| 1533 | case ICMPV6_MGM_REDUCTION: | ||
| 1534 | { | ||
| 1535 | struct mld_msg *mld = (struct mld_msg *)icmp6h; | ||
| 1536 | br_ip6_multicast_leave_group(br, port, &mld->mld_mca); | ||
| 1537 | } | ||
| 1538 | } | ||
| 1539 | |||
| 1540 | out: | ||
| 1541 | __skb_push(skb2, offset); | ||
| 1542 | if (skb2 != skb) | ||
| 1543 | kfree_skb(skb2); | ||
| 1544 | return err; | ||
| 1545 | } | ||
| 1546 | #endif | ||
| 1547 | |||
| 1047 | int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, | 1548 | int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, |
| 1048 | struct sk_buff *skb) | 1549 | struct sk_buff *skb) |
| 1049 | { | 1550 | { |
| 1551 | BR_INPUT_SKB_CB(skb)->igmp = 0; | ||
| 1552 | BR_INPUT_SKB_CB(skb)->mrouters_only = 0; | ||
| 1553 | |||
| 1050 | if (br->multicast_disabled) | 1554 | if (br->multicast_disabled) |
| 1051 | return 0; | 1555 | return 0; |
| 1052 | 1556 | ||
| 1053 | switch (skb->protocol) { | 1557 | switch (skb->protocol) { |
| 1054 | case htons(ETH_P_IP): | 1558 | case htons(ETH_P_IP): |
| 1055 | return br_multicast_ipv4_rcv(br, port, skb); | 1559 | return br_multicast_ipv4_rcv(br, port, skb); |
| 1560 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 1561 | case htons(ETH_P_IPV6): | ||
| 1562 | return br_multicast_ipv6_rcv(br, port, skb); | ||
| 1563 | #endif | ||
| 1056 | } | 1564 | } |
| 1057 | 1565 | ||
| 1058 | return 0; | 1566 | return 0; |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 791d4ab0fd4d..3d2d3fe0a97e 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -45,6 +45,17 @@ struct mac_addr | |||
| 45 | unsigned char addr[6]; | 45 | unsigned char addr[6]; |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | struct br_ip | ||
| 49 | { | ||
| 50 | union { | ||
| 51 | __be32 ip4; | ||
| 52 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 53 | struct in6_addr ip6; | ||
| 54 | #endif | ||
| 55 | } u; | ||
| 56 | __be16 proto; | ||
| 57 | }; | ||
| 58 | |||
| 48 | struct net_bridge_fdb_entry | 59 | struct net_bridge_fdb_entry |
| 49 | { | 60 | { |
| 50 | struct hlist_node hlist; | 61 | struct hlist_node hlist; |
| @@ -64,7 +75,7 @@ struct net_bridge_port_group { | |||
| 64 | struct rcu_head rcu; | 75 | struct rcu_head rcu; |
| 65 | struct timer_list timer; | 76 | struct timer_list timer; |
| 66 | struct timer_list query_timer; | 77 | struct timer_list query_timer; |
| 67 | __be32 addr; | 78 | struct br_ip addr; |
| 68 | u32 queries_sent; | 79 | u32 queries_sent; |
| 69 | }; | 80 | }; |
| 70 | 81 | ||
| @@ -77,7 +88,7 @@ struct net_bridge_mdb_entry | |||
| 77 | struct rcu_head rcu; | 88 | struct rcu_head rcu; |
| 78 | struct timer_list timer; | 89 | struct timer_list timer; |
| 79 | struct timer_list query_timer; | 90 | struct timer_list query_timer; |
| 80 | __be32 addr; | 91 | struct br_ip addr; |
| 81 | u32 queries_sent; | 92 | u32 queries_sent; |
| 82 | }; | 93 | }; |
| 83 | 94 | ||
| @@ -130,19 +141,20 @@ struct net_bridge_port | |||
| 130 | #endif | 141 | #endif |
| 131 | }; | 142 | }; |
| 132 | 143 | ||
| 144 | struct br_cpu_netstats { | ||
| 145 | unsigned long rx_packets; | ||
| 146 | unsigned long rx_bytes; | ||
| 147 | unsigned long tx_packets; | ||
| 148 | unsigned long tx_bytes; | ||
| 149 | }; | ||
| 150 | |||
| 133 | struct net_bridge | 151 | struct net_bridge |
| 134 | { | 152 | { |
| 135 | spinlock_t lock; | 153 | spinlock_t lock; |
| 136 | struct list_head port_list; | 154 | struct list_head port_list; |
| 137 | struct net_device *dev; | 155 | struct net_device *dev; |
| 138 | 156 | ||
| 139 | struct br_cpu_netstats __percpu { | 157 | struct br_cpu_netstats __percpu *stats; |
| 140 | unsigned long rx_packets; | ||
| 141 | unsigned long rx_bytes; | ||
| 142 | unsigned long tx_packets; | ||
| 143 | unsigned long tx_bytes; | ||
| 144 | } *stats; | ||
| 145 | |||
| 146 | spinlock_t hash_lock; | 158 | spinlock_t hash_lock; |
| 147 | struct hlist_head hash[BR_HASH_SIZE]; | 159 | struct hlist_head hash[BR_HASH_SIZE]; |
| 148 | unsigned long feature_mask; | 160 | unsigned long feature_mask; |
| @@ -241,6 +253,8 @@ static inline int br_is_root_bridge(const struct net_bridge *br) | |||
| 241 | extern void br_dev_setup(struct net_device *dev); | 253 | extern void br_dev_setup(struct net_device *dev); |
| 242 | extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, | 254 | extern netdev_tx_t br_dev_xmit(struct sk_buff *skb, |
| 243 | struct net_device *dev); | 255 | struct net_device *dev); |
| 256 | extern bool br_devices_support_netpoll(struct net_bridge *br); | ||
| 257 | extern void br_netpoll_cleanup(struct net_device *br_dev); | ||
| 244 | 258 | ||
| 245 | /* br_fdb.c */ | 259 | /* br_fdb.c */ |
| 246 | extern int br_fdb_init(void); | 260 | extern int br_fdb_init(void); |
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index e84837e1bc86..024fd5bb2d39 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c | |||
| @@ -247,10 +247,10 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, | |||
| 247 | 247 | ||
| 248 | switch (caifdev->link_select) { | 248 | switch (caifdev->link_select) { |
| 249 | case CAIF_LINK_HIGH_BANDW: | 249 | case CAIF_LINK_HIGH_BANDW: |
| 250 | pref = CFPHYPREF_LOW_LAT; | 250 | pref = CFPHYPREF_HIGH_BW; |
| 251 | break; | 251 | break; |
| 252 | case CAIF_LINK_LOW_LATENCY: | 252 | case CAIF_LINK_LOW_LATENCY: |
| 253 | pref = CFPHYPREF_HIGH_BW; | 253 | pref = CFPHYPREF_LOW_LAT; |
| 254 | break; | 254 | break; |
| 255 | default: | 255 | default: |
| 256 | pref = CFPHYPREF_HIGH_BW; | 256 | pref = CFPHYPREF_HIGH_BW; |
| @@ -330,23 +330,28 @@ int caif_connect_client(struct caif_connect_request *conn_req, | |||
| 330 | struct cflayer *client_layer) | 330 | struct cflayer *client_layer) |
| 331 | { | 331 | { |
| 332 | struct cfctrl_link_param param; | 332 | struct cfctrl_link_param param; |
| 333 | if (connect_req_to_link_param(get_caif_conf(), conn_req, ¶m) == 0) | 333 | int ret; |
| 334 | /* Hook up the adaptation layer. */ | 334 | ret = connect_req_to_link_param(get_caif_conf(), conn_req, ¶m); |
| 335 | return cfcnfg_add_adaptation_layer(get_caif_conf(), | 335 | if (ret) |
| 336 | return ret; | ||
| 337 | /* Hook up the adaptation layer. */ | ||
| 338 | return cfcnfg_add_adaptation_layer(get_caif_conf(), | ||
| 336 | ¶m, client_layer); | 339 | ¶m, client_layer); |
| 337 | |||
| 338 | return -EINVAL; | ||
| 339 | |||
| 340 | caif_assert(0); | ||
| 341 | } | 340 | } |
| 342 | EXPORT_SYMBOL(caif_connect_client); | 341 | EXPORT_SYMBOL(caif_connect_client); |
| 343 | 342 | ||
| 344 | int caif_disconnect_client(struct cflayer *adap_layer) | 343 | int caif_disconnect_client(struct cflayer *adap_layer) |
| 345 | { | 344 | { |
| 346 | return cfcnfg_del_adapt_layer(get_caif_conf(), adap_layer); | 345 | return cfcnfg_disconn_adapt_layer(get_caif_conf(), adap_layer); |
| 347 | } | 346 | } |
| 348 | EXPORT_SYMBOL(caif_disconnect_client); | 347 | EXPORT_SYMBOL(caif_disconnect_client); |
| 349 | 348 | ||
| 349 | void caif_release_client(struct cflayer *adap_layer) | ||
| 350 | { | ||
| 351 | cfcnfg_release_adap_layer(adap_layer); | ||
| 352 | } | ||
| 353 | EXPORT_SYMBOL(caif_release_client); | ||
| 354 | |||
| 350 | /* Per-namespace Caif devices handling */ | 355 | /* Per-namespace Caif devices handling */ |
| 351 | static int caif_init_net(struct net *net) | 356 | static int caif_init_net(struct net *net) |
| 352 | { | 357 | { |
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index cdf62b9fefac..c3a70c5c893a 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) ST-Ericsson AB 2010 | 2 | * Copyright (C) ST-Ericsson AB 2010 |
| 3 | * Author: Sjur Brendeland sjur.brandeland@stericsson.com | 3 | * Author: Sjur Brendeland sjur.brandeland@stericsson.com |
| 4 | * Per Sigmond per.sigmond@stericsson.com | ||
| 5 | * License terms: GNU General Public License (GPL) version 2 | 4 | * License terms: GNU General Public License (GPL) version 2 |
| 6 | */ | 5 | */ |
| 7 | 6 | ||
| @@ -16,91 +15,52 @@ | |||
| 16 | #include <linux/poll.h> | 15 | #include <linux/poll.h> |
| 17 | #include <linux/tcp.h> | 16 | #include <linux/tcp.h> |
| 18 | #include <linux/uaccess.h> | 17 | #include <linux/uaccess.h> |
| 19 | #include <asm/atomic.h> | 18 | #include <linux/mutex.h> |
| 20 | 19 | #include <linux/debugfs.h> | |
| 21 | #include <linux/caif/caif_socket.h> | 20 | #include <linux/caif/caif_socket.h> |
| 21 | #include <asm/atomic.h> | ||
| 22 | #include <net/sock.h> | ||
| 23 | #include <net/tcp_states.h> | ||
| 22 | #include <net/caif/caif_layer.h> | 24 | #include <net/caif/caif_layer.h> |
| 23 | #include <net/caif/caif_dev.h> | 25 | #include <net/caif/caif_dev.h> |
| 24 | #include <net/caif/cfpkt.h> | 26 | #include <net/caif/cfpkt.h> |
| 25 | 27 | ||
| 26 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
| 29 | MODULE_ALIAS_NETPROTO(AF_CAIF); | ||
| 30 | |||
| 31 | #define CAIF_DEF_SNDBUF (CAIF_MAX_PAYLOAD_SIZE*10) | ||
| 32 | #define CAIF_DEF_RCVBUF (CAIF_MAX_PAYLOAD_SIZE*100) | ||
| 33 | |||
| 34 | /* | ||
| 35 | * CAIF state is re-using the TCP socket states. | ||
| 36 | * caif_states stored in sk_state reflect the state as reported by | ||
| 37 | * the CAIF stack, while sk_socket->state is the state of the socket. | ||
| 38 | */ | ||
| 39 | enum caif_states { | ||
| 40 | CAIF_CONNECTED = TCP_ESTABLISHED, | ||
| 41 | CAIF_CONNECTING = TCP_SYN_SENT, | ||
| 42 | CAIF_DISCONNECTED = TCP_CLOSE | ||
| 43 | }; | ||
| 44 | |||
| 45 | #define TX_FLOW_ON_BIT 1 | ||
| 46 | #define RX_FLOW_ON_BIT 2 | ||
| 27 | 47 | ||
| 28 | #define CHNL_SKT_READ_QUEUE_HIGH 200 | ||
| 29 | #define CHNL_SKT_READ_QUEUE_LOW 100 | ||
| 30 | |||
| 31 | static int caif_sockbuf_size = 40000; | ||
| 32 | static atomic_t caif_nr_socks = ATOMIC_INIT(0); | ||
| 33 | |||
| 34 | #define CONN_STATE_OPEN_BIT 1 | ||
| 35 | #define CONN_STATE_PENDING_BIT 2 | ||
| 36 | #define CONN_STATE_PEND_DESTROY_BIT 3 | ||
| 37 | #define CONN_REMOTE_SHUTDOWN_BIT 4 | ||
| 38 | |||
| 39 | #define TX_FLOW_ON_BIT 1 | ||
| 40 | #define RX_FLOW_ON_BIT 2 | ||
| 41 | |||
| 42 | #define STATE_IS_OPEN(cf_sk) test_bit(CONN_STATE_OPEN_BIT,\ | ||
| 43 | (void *) &(cf_sk)->conn_state) | ||
| 44 | #define STATE_IS_REMOTE_SHUTDOWN(cf_sk) test_bit(CONN_REMOTE_SHUTDOWN_BIT,\ | ||
| 45 | (void *) &(cf_sk)->conn_state) | ||
| 46 | #define STATE_IS_PENDING(cf_sk) test_bit(CONN_STATE_PENDING_BIT,\ | ||
| 47 | (void *) &(cf_sk)->conn_state) | ||
| 48 | #define STATE_IS_PENDING_DESTROY(cf_sk) test_bit(CONN_STATE_PEND_DESTROY_BIT,\ | ||
| 49 | (void *) &(cf_sk)->conn_state) | ||
| 50 | |||
| 51 | #define SET_STATE_PENDING_DESTROY(cf_sk) set_bit(CONN_STATE_PEND_DESTROY_BIT,\ | ||
| 52 | (void *) &(cf_sk)->conn_state) | ||
| 53 | #define SET_STATE_OPEN(cf_sk) set_bit(CONN_STATE_OPEN_BIT,\ | ||
| 54 | (void *) &(cf_sk)->conn_state) | ||
| 55 | #define SET_STATE_CLOSED(cf_sk) clear_bit(CONN_STATE_OPEN_BIT,\ | ||
| 56 | (void *) &(cf_sk)->conn_state) | ||
| 57 | #define SET_PENDING_ON(cf_sk) set_bit(CONN_STATE_PENDING_BIT,\ | ||
| 58 | (void *) &(cf_sk)->conn_state) | ||
| 59 | #define SET_PENDING_OFF(cf_sk) clear_bit(CONN_STATE_PENDING_BIT,\ | ||
| 60 | (void *) &(cf_sk)->conn_state) | ||
| 61 | #define SET_REMOTE_SHUTDOWN(cf_sk) set_bit(CONN_REMOTE_SHUTDOWN_BIT,\ | ||
| 62 | (void *) &(cf_sk)->conn_state) | ||
| 63 | |||
| 64 | #define SET_REMOTE_SHUTDOWN_OFF(dev) clear_bit(CONN_REMOTE_SHUTDOWN_BIT,\ | ||
| 65 | (void *) &(dev)->conn_state) | ||
| 66 | #define RX_FLOW_IS_ON(cf_sk) test_bit(RX_FLOW_ON_BIT,\ | ||
| 67 | (void *) &(cf_sk)->flow_state) | ||
| 68 | #define TX_FLOW_IS_ON(cf_sk) test_bit(TX_FLOW_ON_BIT,\ | ||
| 69 | (void *) &(cf_sk)->flow_state) | ||
| 70 | |||
| 71 | #define SET_RX_FLOW_OFF(cf_sk) clear_bit(RX_FLOW_ON_BIT,\ | ||
| 72 | (void *) &(cf_sk)->flow_state) | ||
| 73 | #define SET_RX_FLOW_ON(cf_sk) set_bit(RX_FLOW_ON_BIT,\ | ||
| 74 | (void *) &(cf_sk)->flow_state) | ||
| 75 | #define SET_TX_FLOW_OFF(cf_sk) clear_bit(TX_FLOW_ON_BIT,\ | ||
| 76 | (void *) &(cf_sk)->flow_state) | ||
| 77 | #define SET_TX_FLOW_ON(cf_sk) set_bit(TX_FLOW_ON_BIT,\ | ||
| 78 | (void *) &(cf_sk)->flow_state) | ||
| 79 | |||
| 80 | #define SKT_READ_FLAG 0x01 | ||
| 81 | #define SKT_WRITE_FLAG 0x02 | ||
| 82 | static struct dentry *debugfsdir; | 48 | static struct dentry *debugfsdir; |
| 83 | #include <linux/debugfs.h> | ||
| 84 | 49 | ||
| 85 | #ifdef CONFIG_DEBUG_FS | 50 | #ifdef CONFIG_DEBUG_FS |
| 86 | struct debug_fs_counter { | 51 | struct debug_fs_counter { |
| 87 | atomic_t num_open; | 52 | atomic_t caif_nr_socks; |
| 88 | atomic_t num_close; | 53 | atomic_t num_connect_req; |
| 89 | atomic_t num_init; | 54 | atomic_t num_connect_resp; |
| 90 | atomic_t num_init_resp; | 55 | atomic_t num_connect_fail_resp; |
| 91 | atomic_t num_init_fail_resp; | 56 | atomic_t num_disconnect; |
| 92 | atomic_t num_deinit; | ||
| 93 | atomic_t num_deinit_resp; | ||
| 94 | atomic_t num_remote_shutdown_ind; | 57 | atomic_t num_remote_shutdown_ind; |
| 95 | atomic_t num_tx_flow_off_ind; | 58 | atomic_t num_tx_flow_off_ind; |
| 96 | atomic_t num_tx_flow_on_ind; | 59 | atomic_t num_tx_flow_on_ind; |
| 97 | atomic_t num_rx_flow_off; | 60 | atomic_t num_rx_flow_off; |
| 98 | atomic_t num_rx_flow_on; | 61 | atomic_t num_rx_flow_on; |
| 99 | atomic_t skb_in_use; | ||
| 100 | atomic_t skb_alloc; | ||
| 101 | atomic_t skb_free; | ||
| 102 | }; | 62 | }; |
| 103 | static struct debug_fs_counter cnt; | 63 | struct debug_fs_counter cnt; |
| 104 | #define dbfs_atomic_inc(v) atomic_inc(v) | 64 | #define dbfs_atomic_inc(v) atomic_inc(v) |
| 105 | #define dbfs_atomic_dec(v) atomic_dec(v) | 65 | #define dbfs_atomic_dec(v) atomic_dec(v) |
| 106 | #else | 66 | #else |
| @@ -108,624 +68,666 @@ static struct debug_fs_counter cnt; | |||
| 108 | #define dbfs_atomic_dec(v) | 68 | #define dbfs_atomic_dec(v) |
| 109 | #endif | 69 | #endif |
| 110 | 70 | ||
| 111 | /* The AF_CAIF socket */ | ||
| 112 | struct caifsock { | 71 | struct caifsock { |
| 113 | /* NOTE: sk has to be the first member */ | 72 | struct sock sk; /* must be first member */ |
| 114 | struct sock sk; | ||
| 115 | struct cflayer layer; | 73 | struct cflayer layer; |
| 116 | char name[CAIF_LAYER_NAME_SZ]; | 74 | char name[CAIF_LAYER_NAME_SZ]; /* Used for debugging */ |
| 117 | u32 conn_state; | ||
| 118 | u32 flow_state; | 75 | u32 flow_state; |
| 119 | struct cfpktq *pktq; | ||
| 120 | int file_mode; | ||
| 121 | struct caif_connect_request conn_req; | 76 | struct caif_connect_request conn_req; |
| 122 | int read_queue_len; | 77 | struct mutex readlock; |
| 123 | /* protect updates of read_queue_len */ | ||
| 124 | spinlock_t read_queue_len_lock; | ||
| 125 | struct dentry *debugfs_socket_dir; | 78 | struct dentry *debugfs_socket_dir; |
| 126 | }; | 79 | }; |
| 127 | 80 | ||
| 128 | static void drain_queue(struct caifsock *cf_sk); | 81 | static int rx_flow_is_on(struct caifsock *cf_sk) |
| 82 | { | ||
| 83 | return test_bit(RX_FLOW_ON_BIT, | ||
| 84 | (void *) &cf_sk->flow_state); | ||
| 85 | } | ||
| 86 | |||
| 87 | static int tx_flow_is_on(struct caifsock *cf_sk) | ||
| 88 | { | ||
| 89 | return test_bit(TX_FLOW_ON_BIT, | ||
| 90 | (void *) &cf_sk->flow_state); | ||
| 91 | } | ||
| 129 | 92 | ||
| 130 | /* Packet Receive Callback function called from CAIF Stack */ | 93 | static void set_rx_flow_off(struct caifsock *cf_sk) |
| 131 | static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt) | ||
| 132 | { | 94 | { |
| 133 | struct caifsock *cf_sk; | 95 | clear_bit(RX_FLOW_ON_BIT, |
| 134 | int read_queue_high; | 96 | (void *) &cf_sk->flow_state); |
| 135 | cf_sk = container_of(layr, struct caifsock, layer); | 97 | } |
| 136 | 98 | ||
| 137 | if (!STATE_IS_OPEN(cf_sk)) { | 99 | static void set_rx_flow_on(struct caifsock *cf_sk) |
| 138 | /*FIXME: This should be allowed finally!*/ | 100 | { |
| 139 | pr_debug("CAIF: %s(): called after close request\n", __func__); | 101 | set_bit(RX_FLOW_ON_BIT, |
| 140 | cfpkt_destroy(pkt); | 102 | (void *) &cf_sk->flow_state); |
| 141 | return 0; | 103 | } |
| 142 | } | ||
| 143 | /* NOTE: This function may be called in Tasklet context! */ | ||
| 144 | 104 | ||
| 145 | /* The queue has its own lock */ | 105 | static void set_tx_flow_off(struct caifsock *cf_sk) |
| 146 | cfpkt_queue(cf_sk->pktq, pkt, 0); | 106 | { |
| 107 | clear_bit(TX_FLOW_ON_BIT, | ||
| 108 | (void *) &cf_sk->flow_state); | ||
| 109 | } | ||
| 147 | 110 | ||
| 148 | spin_lock(&cf_sk->read_queue_len_lock); | 111 | static void set_tx_flow_on(struct caifsock *cf_sk) |
| 149 | cf_sk->read_queue_len++; | 112 | { |
| 113 | set_bit(TX_FLOW_ON_BIT, | ||
| 114 | (void *) &cf_sk->flow_state); | ||
| 115 | } | ||
| 150 | 116 | ||
| 151 | read_queue_high = (cf_sk->read_queue_len > CHNL_SKT_READ_QUEUE_HIGH); | 117 | static void caif_read_lock(struct sock *sk) |
| 152 | spin_unlock(&cf_sk->read_queue_len_lock); | 118 | { |
| 119 | struct caifsock *cf_sk; | ||
| 120 | cf_sk = container_of(sk, struct caifsock, sk); | ||
| 121 | mutex_lock(&cf_sk->readlock); | ||
| 122 | } | ||
| 153 | 123 | ||
| 154 | if (RX_FLOW_IS_ON(cf_sk) && read_queue_high) { | 124 | static void caif_read_unlock(struct sock *sk) |
| 155 | dbfs_atomic_inc(&cnt.num_rx_flow_off); | 125 | { |
| 156 | SET_RX_FLOW_OFF(cf_sk); | 126 | struct caifsock *cf_sk; |
| 127 | cf_sk = container_of(sk, struct caifsock, sk); | ||
| 128 | mutex_unlock(&cf_sk->readlock); | ||
| 129 | } | ||
| 157 | 130 | ||
| 158 | /* Send flow off (NOTE: must not sleep) */ | 131 | int sk_rcvbuf_lowwater(struct caifsock *cf_sk) |
| 159 | pr_debug("CAIF: %s():" | 132 | { |
| 160 | " sending flow OFF (queue len = %d)\n", | 133 | /* A quarter of full buffer is used a low water mark */ |
| 161 | __func__, | 134 | return cf_sk->sk.sk_rcvbuf / 4; |
| 162 | cf_sk->read_queue_len); | 135 | } |
| 163 | caif_assert(cf_sk->layer.dn); | ||
| 164 | caif_assert(cf_sk->layer.dn->ctrlcmd); | ||
| 165 | 136 | ||
| 166 | (void) cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, | 137 | void caif_flow_ctrl(struct sock *sk, int mode) |
| 167 | CAIF_MODEMCMD_FLOW_OFF_REQ); | 138 | { |
| 168 | } | 139 | struct caifsock *cf_sk; |
| 140 | cf_sk = container_of(sk, struct caifsock, sk); | ||
| 141 | if (cf_sk->layer.dn) | ||
| 142 | cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, mode); | ||
| 143 | } | ||
| 169 | 144 | ||
| 170 | /* Signal reader that data is available. */ | 145 | /* |
| 146 | * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are | ||
| 147 | * not dropped, but CAIF is sending flow off instead. | ||
| 148 | */ | ||
| 149 | int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | ||
| 150 | { | ||
| 151 | int err; | ||
| 152 | int skb_len; | ||
| 153 | unsigned long flags; | ||
| 154 | struct sk_buff_head *list = &sk->sk_receive_queue; | ||
| 155 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
| 171 | 156 | ||
| 172 | wake_up_interruptible(cf_sk->sk.sk_sleep); | 157 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= |
| 158 | (unsigned)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { | ||
| 159 | trace_printk("CAIF: %s():" | ||
| 160 | " sending flow OFF (queue len = %d %d)\n", | ||
| 161 | __func__, | ||
| 162 | atomic_read(&cf_sk->sk.sk_rmem_alloc), | ||
| 163 | sk_rcvbuf_lowwater(cf_sk)); | ||
| 164 | set_rx_flow_off(cf_sk); | ||
| 165 | if (cf_sk->layer.dn) | ||
| 166 | cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, | ||
| 167 | CAIF_MODEMCMD_FLOW_OFF_REQ); | ||
| 168 | } | ||
| 173 | 169 | ||
| 170 | err = sk_filter(sk, skb); | ||
| 171 | if (err) | ||
| 172 | return err; | ||
| 173 | if (!sk_rmem_schedule(sk, skb->truesize) && rx_flow_is_on(cf_sk)) { | ||
| 174 | set_rx_flow_off(cf_sk); | ||
| 175 | trace_printk("CAIF: %s():" | ||
| 176 | " sending flow OFF due to rmem_schedule\n", | ||
| 177 | __func__); | ||
| 178 | if (cf_sk->layer.dn) | ||
| 179 | cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, | ||
| 180 | CAIF_MODEMCMD_FLOW_OFF_REQ); | ||
| 181 | } | ||
| 182 | skb->dev = NULL; | ||
| 183 | skb_set_owner_r(skb, sk); | ||
| 184 | /* Cache the SKB length before we tack it onto the receive | ||
| 185 | * queue. Once it is added it no longer belongs to us and | ||
| 186 | * may be freed by other threads of control pulling packets | ||
| 187 | * from the queue. | ||
| 188 | */ | ||
| 189 | skb_len = skb->len; | ||
| 190 | spin_lock_irqsave(&list->lock, flags); | ||
| 191 | if (!sock_flag(sk, SOCK_DEAD)) | ||
| 192 | __skb_queue_tail(list, skb); | ||
| 193 | spin_unlock_irqrestore(&list->lock, flags); | ||
| 194 | |||
| 195 | if (!sock_flag(sk, SOCK_DEAD)) | ||
| 196 | sk->sk_data_ready(sk, skb_len); | ||
| 197 | else | ||
| 198 | kfree_skb(skb); | ||
| 174 | return 0; | 199 | return 0; |
| 175 | } | 200 | } |
| 176 | 201 | ||
| 177 | /* Packet Flow Control Callback function called from CAIF */ | 202 | /* Packet Receive Callback function called from CAIF Stack */ |
| 178 | static void caif_sktflowctrl_cb(struct cflayer *layr, | 203 | static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt) |
| 179 | enum caif_ctrlcmd flow, | ||
| 180 | int phyid) | ||
| 181 | { | 204 | { |
| 182 | struct caifsock *cf_sk; | 205 | struct caifsock *cf_sk; |
| 183 | 206 | struct sk_buff *skb; | |
| 184 | /* NOTE: This function may be called in Tasklet context! */ | ||
| 185 | pr_debug("CAIF: %s(): flowctrl func called: %s.\n", | ||
| 186 | __func__, | ||
| 187 | flow == CAIF_CTRLCMD_FLOW_ON_IND ? "ON" : | ||
| 188 | flow == CAIF_CTRLCMD_FLOW_OFF_IND ? "OFF" : | ||
| 189 | flow == CAIF_CTRLCMD_INIT_RSP ? "INIT_RSP" : | ||
| 190 | flow == CAIF_CTRLCMD_DEINIT_RSP ? "DEINIT_RSP" : | ||
| 191 | flow == CAIF_CTRLCMD_INIT_FAIL_RSP ? "INIT_FAIL_RSP" : | ||
| 192 | flow == | ||
| 193 | CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND ? "REMOTE_SHUTDOWN" : | ||
| 194 | "UKNOWN CTRL COMMAND"); | ||
| 195 | |||
| 196 | if (layr == NULL) | ||
| 197 | return; | ||
| 198 | 207 | ||
| 199 | cf_sk = container_of(layr, struct caifsock, layer); | 208 | cf_sk = container_of(layr, struct caifsock, layer); |
| 209 | skb = cfpkt_tonative(pkt); | ||
| 210 | |||
| 211 | if (unlikely(cf_sk->sk.sk_state != CAIF_CONNECTED)) { | ||
| 212 | cfpkt_destroy(pkt); | ||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | caif_queue_rcv_skb(&cf_sk->sk, skb); | ||
| 216 | return 0; | ||
| 217 | } | ||
| 200 | 218 | ||
| 219 | /* Packet Control Callback function called from CAIF */ | ||
| 220 | static void caif_ctrl_cb(struct cflayer *layr, | ||
| 221 | enum caif_ctrlcmd flow, | ||
| 222 | int phyid) | ||
| 223 | { | ||
| 224 | struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); | ||
| 201 | switch (flow) { | 225 | switch (flow) { |
| 202 | case CAIF_CTRLCMD_FLOW_ON_IND: | 226 | case CAIF_CTRLCMD_FLOW_ON_IND: |
| 227 | /* OK from modem to start sending again */ | ||
| 203 | dbfs_atomic_inc(&cnt.num_tx_flow_on_ind); | 228 | dbfs_atomic_inc(&cnt.num_tx_flow_on_ind); |
| 204 | /* Signal reader that data is available. */ | 229 | set_tx_flow_on(cf_sk); |
| 205 | SET_TX_FLOW_ON(cf_sk); | 230 | cf_sk->sk.sk_state_change(&cf_sk->sk); |
| 206 | wake_up_interruptible(cf_sk->sk.sk_sleep); | ||
| 207 | break; | 231 | break; |
| 208 | 232 | ||
| 209 | case CAIF_CTRLCMD_FLOW_OFF_IND: | 233 | case CAIF_CTRLCMD_FLOW_OFF_IND: |
| 234 | /* Modem asks us to shut up */ | ||
| 210 | dbfs_atomic_inc(&cnt.num_tx_flow_off_ind); | 235 | dbfs_atomic_inc(&cnt.num_tx_flow_off_ind); |
| 211 | SET_TX_FLOW_OFF(cf_sk); | 236 | set_tx_flow_off(cf_sk); |
| 237 | cf_sk->sk.sk_state_change(&cf_sk->sk); | ||
| 212 | break; | 238 | break; |
| 213 | 239 | ||
| 214 | case CAIF_CTRLCMD_INIT_RSP: | 240 | case CAIF_CTRLCMD_INIT_RSP: |
| 215 | dbfs_atomic_inc(&cnt.num_init_resp); | 241 | /* We're now connected */ |
| 216 | /* Signal reader that data is available. */ | 242 | dbfs_atomic_inc(&cnt.num_connect_resp); |
| 217 | caif_assert(STATE_IS_OPEN(cf_sk)); | 243 | cf_sk->sk.sk_state = CAIF_CONNECTED; |
| 218 | SET_PENDING_OFF(cf_sk); | 244 | set_tx_flow_on(cf_sk); |
| 219 | SET_TX_FLOW_ON(cf_sk); | 245 | cf_sk->sk.sk_state_change(&cf_sk->sk); |
| 220 | wake_up_interruptible(cf_sk->sk.sk_sleep); | ||
| 221 | break; | 246 | break; |
| 222 | 247 | ||
| 223 | case CAIF_CTRLCMD_DEINIT_RSP: | 248 | case CAIF_CTRLCMD_DEINIT_RSP: |
| 224 | dbfs_atomic_inc(&cnt.num_deinit_resp); | 249 | /* We're now disconnected */ |
| 225 | caif_assert(!STATE_IS_OPEN(cf_sk)); | 250 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; |
| 226 | SET_PENDING_OFF(cf_sk); | 251 | cf_sk->sk.sk_state_change(&cf_sk->sk); |
| 227 | if (!STATE_IS_PENDING_DESTROY(cf_sk)) { | 252 | cfcnfg_release_adap_layer(&cf_sk->layer); |
| 228 | if (cf_sk->sk.sk_sleep != NULL) | ||
| 229 | wake_up_interruptible(cf_sk->sk.sk_sleep); | ||
| 230 | } | ||
| 231 | dbfs_atomic_inc(&cnt.num_deinit); | ||
| 232 | sock_put(&cf_sk->sk); | ||
| 233 | break; | 253 | break; |
| 234 | 254 | ||
| 235 | case CAIF_CTRLCMD_INIT_FAIL_RSP: | 255 | case CAIF_CTRLCMD_INIT_FAIL_RSP: |
| 236 | dbfs_atomic_inc(&cnt.num_init_fail_resp); | 256 | /* Connect request failed */ |
| 237 | caif_assert(STATE_IS_OPEN(cf_sk)); | 257 | dbfs_atomic_inc(&cnt.num_connect_fail_resp); |
| 238 | SET_STATE_CLOSED(cf_sk); | 258 | cf_sk->sk.sk_err = ECONNREFUSED; |
| 239 | SET_PENDING_OFF(cf_sk); | 259 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; |
| 240 | SET_TX_FLOW_OFF(cf_sk); | 260 | cf_sk->sk.sk_shutdown = SHUTDOWN_MASK; |
| 241 | wake_up_interruptible(cf_sk->sk.sk_sleep); | 261 | /* |
| 262 | * Socket "standards" seems to require POLLOUT to | ||
| 263 | * be set at connect failure. | ||
| 264 | */ | ||
| 265 | set_tx_flow_on(cf_sk); | ||
| 266 | cf_sk->sk.sk_state_change(&cf_sk->sk); | ||
| 242 | break; | 267 | break; |
| 243 | 268 | ||
| 244 | case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: | 269 | case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: |
| 270 | /* Modem has closed this connection, or device is down. */ | ||
| 245 | dbfs_atomic_inc(&cnt.num_remote_shutdown_ind); | 271 | dbfs_atomic_inc(&cnt.num_remote_shutdown_ind); |
| 246 | SET_REMOTE_SHUTDOWN(cf_sk); | 272 | cf_sk->sk.sk_shutdown = SHUTDOWN_MASK; |
| 247 | /* Use sk_shutdown to indicate remote shutdown indication */ | 273 | cf_sk->sk.sk_err = ECONNRESET; |
| 248 | cf_sk->sk.sk_shutdown |= RCV_SHUTDOWN; | 274 | set_rx_flow_on(cf_sk); |
| 249 | cf_sk->file_mode = 0; | 275 | cf_sk->sk.sk_error_report(&cf_sk->sk); |
| 250 | wake_up_interruptible(cf_sk->sk.sk_sleep); | ||
| 251 | break; | 276 | break; |
| 252 | 277 | ||
| 253 | default: | 278 | default: |
| 254 | pr_debug("CAIF: %s(): Unexpected flow command %d\n", | 279 | pr_debug("CAIF: %s(): Unexpected flow command %d\n", |
| 255 | __func__, flow); | 280 | __func__, flow); |
| 256 | } | 281 | } |
| 257 | } | 282 | } |
| 258 | 283 | ||
| 259 | static void skb_destructor(struct sk_buff *skb) | 284 | static void caif_check_flow_release(struct sock *sk) |
| 260 | { | 285 | { |
| 261 | dbfs_atomic_inc(&cnt.skb_free); | 286 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
| 262 | dbfs_atomic_dec(&cnt.skb_in_use); | ||
| 263 | } | ||
| 264 | 287 | ||
| 288 | if (cf_sk->layer.dn == NULL || cf_sk->layer.dn->modemcmd == NULL) | ||
| 289 | return; | ||
| 290 | if (rx_flow_is_on(cf_sk)) | ||
| 291 | return; | ||
| 265 | 292 | ||
| 266 | static int caif_recvmsg(struct kiocb *iocb, struct socket *sock, | 293 | if (atomic_read(&sk->sk_rmem_alloc) <= sk_rcvbuf_lowwater(cf_sk)) { |
| 294 | dbfs_atomic_inc(&cnt.num_rx_flow_on); | ||
| 295 | set_rx_flow_on(cf_sk); | ||
| 296 | cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, | ||
| 297 | CAIF_MODEMCMD_FLOW_ON_REQ); | ||
| 298 | } | ||
| 299 | } | ||
| 300 | /* | ||
| 301 | * Copied from sock.c:sock_queue_rcv_skb(), and added check that user buffer | ||
| 302 | * has sufficient size. | ||
| 303 | */ | ||
| 304 | |||
| 305 | static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
| 267 | struct msghdr *m, size_t buf_len, int flags) | 306 | struct msghdr *m, size_t buf_len, int flags) |
| 268 | 307 | ||
| 269 | { | 308 | { |
| 270 | struct sock *sk = sock->sk; | 309 | struct sock *sk = sock->sk; |
| 271 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
| 272 | struct cfpkt *pkt = NULL; | ||
| 273 | size_t len; | ||
| 274 | int result; | ||
| 275 | struct sk_buff *skb; | 310 | struct sk_buff *skb; |
| 276 | ssize_t ret = -EIO; | 311 | int ret = 0; |
| 277 | int read_queue_low; | 312 | int len; |
| 278 | |||
| 279 | if (cf_sk == NULL) { | ||
| 280 | pr_debug("CAIF: %s(): private_data not set!\n", | ||
| 281 | __func__); | ||
| 282 | ret = -EBADFD; | ||
| 283 | goto read_error; | ||
| 284 | } | ||
| 285 | |||
| 286 | /* Don't do multiple iovec entries yet */ | ||
| 287 | if (m->msg_iovlen != 1) | ||
| 288 | return -EOPNOTSUPP; | ||
| 289 | 313 | ||
| 290 | if (unlikely(!buf_len)) | 314 | if (unlikely(!buf_len)) |
| 291 | return -EINVAL; | 315 | return -EINVAL; |
| 292 | 316 | ||
| 293 | lock_sock(&(cf_sk->sk)); | 317 | skb = skb_recv_datagram(sk, flags, 0 , &ret); |
| 294 | 318 | if (!skb) | |
| 295 | caif_assert(cf_sk->pktq); | ||
| 296 | |||
| 297 | if (!STATE_IS_OPEN(cf_sk)) { | ||
| 298 | /* Socket is closed or closing. */ | ||
| 299 | if (!STATE_IS_PENDING(cf_sk)) { | ||
| 300 | pr_debug("CAIF: %s(): socket is closed (by remote)\n", | ||
| 301 | __func__); | ||
| 302 | ret = -EPIPE; | ||
| 303 | } else { | ||
| 304 | pr_debug("CAIF: %s(): socket is closing..\n", __func__); | ||
| 305 | ret = -EBADF; | ||
| 306 | } | ||
| 307 | goto read_error; | 319 | goto read_error; |
| 308 | } | ||
| 309 | /* Socket is open or opening. */ | ||
| 310 | if (STATE_IS_PENDING(cf_sk)) { | ||
| 311 | pr_debug("CAIF: %s(): socket is opening...\n", __func__); | ||
| 312 | |||
| 313 | if (flags & MSG_DONTWAIT) { | ||
| 314 | /* We can't block. */ | ||
| 315 | pr_debug("CAIF: %s():state pending and MSG_DONTWAIT\n", | ||
| 316 | __func__); | ||
| 317 | ret = -EAGAIN; | ||
| 318 | goto read_error; | ||
| 319 | } | ||
| 320 | 320 | ||
| 321 | len = skb->len; | ||
| 322 | |||
| 323 | if (skb && skb->len > buf_len && !(flags & MSG_PEEK)) { | ||
| 324 | len = buf_len; | ||
| 321 | /* | 325 | /* |
| 322 | * Blocking mode; state is pending and we need to wait | 326 | * Push skb back on receive queue if buffer too small. |
| 323 | * for its conclusion. | 327 | * This has a built-in race where multi-threaded receive |
| 328 | * may get packet in wrong order, but multiple read does | ||
| 329 | * not really guarantee ordered delivery anyway. | ||
| 330 | * Let's optimize for speed without taking locks. | ||
| 324 | */ | 331 | */ |
| 325 | release_sock(&cf_sk->sk); | ||
| 326 | |||
| 327 | result = | ||
| 328 | wait_event_interruptible(*cf_sk->sk.sk_sleep, | ||
| 329 | !STATE_IS_PENDING(cf_sk)); | ||
| 330 | 332 | ||
| 331 | lock_sock(&(cf_sk->sk)); | 333 | skb_queue_head(&sk->sk_receive_queue, skb); |
| 332 | 334 | ret = -EMSGSIZE; | |
| 333 | if (result == -ERESTARTSYS) { | 335 | goto read_error; |
| 334 | pr_debug("CAIF: %s(): wait_event_interruptible" | ||
| 335 | " woken by a signal (1)", __func__); | ||
| 336 | ret = -ERESTARTSYS; | ||
| 337 | goto read_error; | ||
| 338 | } | ||
| 339 | } | 336 | } |
| 340 | 337 | ||
| 341 | if (STATE_IS_REMOTE_SHUTDOWN(cf_sk) || | 338 | ret = skb_copy_datagram_iovec(skb, 0, m->msg_iov, len); |
| 342 | !STATE_IS_OPEN(cf_sk) || | 339 | if (ret) |
| 343 | STATE_IS_PENDING(cf_sk)) { | ||
| 344 | |||
| 345 | pr_debug("CAIF: %s(): socket closed\n", | ||
| 346 | __func__); | ||
| 347 | ret = -ESHUTDOWN; | ||
| 348 | goto read_error; | 340 | goto read_error; |
| 349 | } | ||
| 350 | 341 | ||
| 351 | /* | 342 | skb_free_datagram(sk, skb); |
| 352 | * Block if we don't have any received buffers. | ||
| 353 | * The queue has its own lock. | ||
| 354 | */ | ||
| 355 | while ((pkt = cfpkt_qpeek(cf_sk->pktq)) == NULL) { | ||
| 356 | 343 | ||
| 357 | if (flags & MSG_DONTWAIT) { | 344 | caif_check_flow_release(sk); |
| 358 | pr_debug("CAIF: %s(): MSG_DONTWAIT\n", __func__); | ||
| 359 | ret = -EAGAIN; | ||
| 360 | goto read_error; | ||
| 361 | } | ||
| 362 | trace_printk("CAIF: %s() wait_event\n", __func__); | ||
| 363 | 345 | ||
| 364 | /* Let writers in. */ | 346 | return len; |
| 365 | release_sock(&cf_sk->sk); | ||
| 366 | 347 | ||
| 367 | /* Block reader until data arrives or socket is closed. */ | 348 | read_error: |
| 368 | if (wait_event_interruptible(*cf_sk->sk.sk_sleep, | 349 | return ret; |
| 369 | cfpkt_qpeek(cf_sk->pktq) | 350 | } |
| 370 | || STATE_IS_REMOTE_SHUTDOWN(cf_sk) | ||
| 371 | || !STATE_IS_OPEN(cf_sk)) == | ||
| 372 | -ERESTARTSYS) { | ||
| 373 | pr_debug("CAIF: %s():" | ||
| 374 | " wait_event_interruptible woken by " | ||
| 375 | "a signal, signal_pending(current) = %d\n", | ||
| 376 | __func__, | ||
| 377 | signal_pending(current)); | ||
| 378 | return -ERESTARTSYS; | ||
| 379 | } | ||
| 380 | 351 | ||
| 381 | trace_printk("CAIF: %s() awake\n", __func__); | ||
| 382 | if (STATE_IS_REMOTE_SHUTDOWN(cf_sk)) { | ||
| 383 | pr_debug("CAIF: %s(): " | ||
| 384 | "received remote_shutdown indication\n", | ||
| 385 | __func__); | ||
| 386 | ret = -ESHUTDOWN; | ||
| 387 | goto read_error_no_unlock; | ||
| 388 | } | ||
| 389 | 352 | ||
| 390 | /* I want to be alone on cf_sk (except status and queue). */ | 353 | /* Copied from unix_stream_wait_data, identical except for lock call. */ |
| 391 | lock_sock(&(cf_sk->sk)); | 354 | static long caif_stream_data_wait(struct sock *sk, long timeo) |
| 355 | { | ||
| 356 | DEFINE_WAIT(wait); | ||
| 357 | lock_sock(sk); | ||
| 358 | |||
| 359 | for (;;) { | ||
| 360 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
| 361 | |||
| 362 | if (!skb_queue_empty(&sk->sk_receive_queue) || | ||
| 363 | sk->sk_err || | ||
| 364 | sk->sk_state != CAIF_CONNECTED || | ||
| 365 | sock_flag(sk, SOCK_DEAD) || | ||
| 366 | (sk->sk_shutdown & RCV_SHUTDOWN) || | ||
| 367 | signal_pending(current) || | ||
| 368 | !timeo) | ||
| 369 | break; | ||
| 392 | 370 | ||
| 393 | if (!STATE_IS_OPEN(cf_sk)) { | 371 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
| 394 | /* Someone closed the link, report error. */ | 372 | release_sock(sk); |
| 395 | pr_debug("CAIF: %s(): remote end shutdown!\n", | 373 | timeo = schedule_timeout(timeo); |
| 396 | __func__); | 374 | lock_sock(sk); |
| 397 | ret = -EPIPE; | 375 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
| 398 | goto read_error; | ||
| 399 | } | ||
| 400 | } | 376 | } |
| 401 | 377 | ||
| 402 | /* The queue has its own lock. */ | 378 | finish_wait(sk_sleep(sk), &wait); |
| 403 | len = cfpkt_getlen(pkt); | 379 | release_sock(sk); |
| 404 | 380 | return timeo; | |
| 405 | /* Check max length that can be copied. */ | 381 | } |
| 406 | if (len <= buf_len) | ||
| 407 | pkt = cfpkt_dequeue(cf_sk->pktq); | ||
| 408 | else { | ||
| 409 | pr_debug("CAIF: %s(): user buffer too small (%ld,%ld)\n", | ||
| 410 | __func__, (long) len, (long) buf_len); | ||
| 411 | if (sock->type == SOCK_SEQPACKET) { | ||
| 412 | ret = -EMSGSIZE; | ||
| 413 | goto read_error; | ||
| 414 | } | ||
| 415 | len = buf_len; | ||
| 416 | } | ||
| 417 | 382 | ||
| 418 | 383 | ||
| 419 | spin_lock(&cf_sk->read_queue_len_lock); | 384 | /* |
| 420 | cf_sk->read_queue_len--; | 385 | * Copied from unix_stream_recvmsg, but removed credit checks, |
| 421 | read_queue_low = (cf_sk->read_queue_len < CHNL_SKT_READ_QUEUE_LOW); | 386 | * changed locking calls, changed address handling. |
| 422 | spin_unlock(&cf_sk->read_queue_len_lock); | 387 | */ |
| 388 | static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
| 389 | struct msghdr *msg, size_t size, | ||
| 390 | int flags) | ||
| 391 | { | ||
| 392 | struct sock *sk = sock->sk; | ||
| 393 | int copied = 0; | ||
| 394 | int target; | ||
| 395 | int err = 0; | ||
| 396 | long timeo; | ||
| 423 | 397 | ||
| 424 | if (!RX_FLOW_IS_ON(cf_sk) && read_queue_low) { | 398 | err = -EOPNOTSUPP; |
| 425 | dbfs_atomic_inc(&cnt.num_rx_flow_on); | 399 | if (flags&MSG_OOB) |
| 426 | SET_RX_FLOW_ON(cf_sk); | 400 | goto out; |
| 427 | 401 | ||
| 428 | /* Send flow on. */ | 402 | msg->msg_namelen = 0; |
| 429 | pr_debug("CAIF: %s(): sending flow ON (queue len = %d)\n", | ||
| 430 | __func__, cf_sk->read_queue_len); | ||
| 431 | caif_assert(cf_sk->layer.dn); | ||
| 432 | caif_assert(cf_sk->layer.dn->ctrlcmd); | ||
| 433 | (void) cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, | ||
| 434 | CAIF_MODEMCMD_FLOW_ON_REQ); | ||
| 435 | 403 | ||
| 436 | caif_assert(cf_sk->read_queue_len >= 0); | 404 | /* |
| 437 | } | 405 | * Lock the socket to prevent queue disordering |
| 406 | * while sleeps in memcpy_tomsg | ||
| 407 | */ | ||
| 408 | err = -EAGAIN; | ||
| 409 | if (sk->sk_state == CAIF_CONNECTING) | ||
| 410 | goto out; | ||
| 438 | 411 | ||
| 439 | skb = cfpkt_tonative(pkt); | 412 | caif_read_lock(sk); |
| 440 | result = skb_copy_datagram_iovec(skb, 0, m->msg_iov, len); | 413 | target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); |
| 441 | skb_pull(skb, len); | 414 | timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT); |
| 442 | 415 | ||
| 443 | if (result) { | 416 | do { |
| 444 | pr_debug("CAIF: %s(): copy to_iovec failed\n", __func__); | 417 | int chunk; |
| 445 | cfpkt_destroy(pkt); | 418 | struct sk_buff *skb; |
| 446 | ret = -EFAULT; | ||
| 447 | goto read_error; | ||
| 448 | } | ||
| 449 | 419 | ||
| 450 | /* Free packet and remove from queue */ | 420 | lock_sock(sk); |
| 451 | if (skb->len == 0) | 421 | skb = skb_dequeue(&sk->sk_receive_queue); |
| 452 | skb_free_datagram(sk, skb); | 422 | caif_check_flow_release(sk); |
| 453 | 423 | ||
| 454 | /* Let the others in. */ | 424 | if (skb == NULL) { |
| 455 | release_sock(&cf_sk->sk); | 425 | if (copied >= target) |
| 456 | return len; | 426 | goto unlock; |
| 427 | /* | ||
| 428 | * POSIX 1003.1g mandates this order. | ||
| 429 | */ | ||
| 430 | err = sock_error(sk); | ||
| 431 | if (err) | ||
| 432 | goto unlock; | ||
| 433 | err = -ECONNRESET; | ||
| 434 | if (sk->sk_shutdown & RCV_SHUTDOWN) | ||
| 435 | goto unlock; | ||
| 457 | 436 | ||
| 458 | read_error: | 437 | err = -EPIPE; |
| 459 | release_sock(&cf_sk->sk); | 438 | if (sk->sk_state != CAIF_CONNECTED) |
| 460 | read_error_no_unlock: | 439 | goto unlock; |
| 461 | return ret; | 440 | if (sock_flag(sk, SOCK_DEAD)) |
| 462 | } | 441 | goto unlock; |
| 463 | 442 | ||
| 464 | /* Send a signal as a consequence of sendmsg, sendto or caif_sendmsg. */ | 443 | release_sock(sk); |
| 465 | static int caif_sendmsg(struct kiocb *kiocb, struct socket *sock, | ||
| 466 | struct msghdr *msg, size_t len) | ||
| 467 | { | ||
| 468 | 444 | ||
| 469 | struct sock *sk = sock->sk; | 445 | err = -EAGAIN; |
| 470 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | 446 | if (!timeo) |
| 471 | size_t payload_size = msg->msg_iov->iov_len; | 447 | break; |
| 472 | struct cfpkt *pkt = NULL; | ||
| 473 | struct caif_payload_info info; | ||
| 474 | unsigned char *txbuf; | ||
| 475 | ssize_t ret = -EIO; | ||
| 476 | int result; | ||
| 477 | struct sk_buff *skb; | ||
| 478 | caif_assert(msg->msg_iovlen == 1); | ||
| 479 | 448 | ||
| 480 | if (cf_sk == NULL) { | 449 | caif_read_unlock(sk); |
| 481 | pr_debug("CAIF: %s(): private_data not set!\n", | ||
| 482 | __func__); | ||
| 483 | ret = -EBADFD; | ||
| 484 | goto write_error_no_unlock; | ||
| 485 | } | ||
| 486 | 450 | ||
| 487 | if (unlikely(msg->msg_iov->iov_base == NULL)) { | 451 | timeo = caif_stream_data_wait(sk, timeo); |
| 488 | pr_warning("CAIF: %s(): Buffer is NULL.\n", __func__); | ||
| 489 | ret = -EINVAL; | ||
| 490 | goto write_error_no_unlock; | ||
| 491 | } | ||
| 492 | 452 | ||
| 493 | if (payload_size > CAIF_MAX_PAYLOAD_SIZE) { | 453 | if (signal_pending(current)) { |
| 494 | pr_debug("CAIF: %s(): buffer too long\n", __func__); | 454 | err = sock_intr_errno(timeo); |
| 495 | if (sock->type == SOCK_SEQPACKET) { | 455 | goto out; |
| 496 | ret = -EINVAL; | 456 | } |
| 497 | goto write_error_no_unlock; | 457 | caif_read_lock(sk); |
| 458 | continue; | ||
| 459 | unlock: | ||
| 460 | release_sock(sk); | ||
| 461 | break; | ||
| 498 | } | 462 | } |
| 499 | payload_size = CAIF_MAX_PAYLOAD_SIZE; | 463 | release_sock(sk); |
| 500 | } | 464 | chunk = min_t(unsigned int, skb->len, size); |
| 465 | if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { | ||
| 466 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
| 467 | if (copied == 0) | ||
| 468 | copied = -EFAULT; | ||
| 469 | break; | ||
| 470 | } | ||
| 471 | copied += chunk; | ||
| 472 | size -= chunk; | ||
| 501 | 473 | ||
| 502 | /* I want to be alone on cf_sk (except status and queue) */ | 474 | /* Mark read part of skb as used */ |
| 503 | lock_sock(&(cf_sk->sk)); | 475 | if (!(flags & MSG_PEEK)) { |
| 476 | skb_pull(skb, chunk); | ||
| 504 | 477 | ||
| 505 | caif_assert(cf_sk->pktq); | 478 | /* put the skb back if we didn't use it up. */ |
| 479 | if (skb->len) { | ||
| 480 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
| 481 | break; | ||
| 482 | } | ||
| 483 | kfree_skb(skb); | ||
| 506 | 484 | ||
| 507 | if (!STATE_IS_OPEN(cf_sk)) { | ||
| 508 | /* Socket is closed or closing */ | ||
| 509 | if (!STATE_IS_PENDING(cf_sk)) { | ||
| 510 | pr_debug("CAIF: %s(): socket is closed (by remote)\n", | ||
| 511 | __func__); | ||
| 512 | ret = -EPIPE; | ||
| 513 | } else { | 485 | } else { |
| 514 | pr_debug("CAIF: %s(): socket is closing...\n", | 486 | /* |
| 515 | __func__); | 487 | * It is questionable, see note in unix_dgram_recvmsg. |
| 516 | ret = -EBADF; | 488 | */ |
| 517 | } | 489 | /* put message back and return */ |
| 518 | goto write_error; | 490 | skb_queue_head(&sk->sk_receive_queue, skb); |
| 519 | } | 491 | break; |
| 520 | |||
| 521 | /* Socket is open or opening */ | ||
| 522 | if (STATE_IS_PENDING(cf_sk)) { | ||
| 523 | pr_debug("CAIF: %s(): socket is opening...\n", __func__); | ||
| 524 | |||
| 525 | if (msg->msg_flags & MSG_DONTWAIT) { | ||
| 526 | /* We can't block */ | ||
| 527 | trace_printk("CAIF: %s():state pending:" | ||
| 528 | "state=MSG_DONTWAIT\n", __func__); | ||
| 529 | ret = -EAGAIN; | ||
| 530 | goto write_error; | ||
| 531 | } | 492 | } |
| 532 | /* Let readers in */ | 493 | } while (size); |
| 533 | release_sock(&cf_sk->sk); | 494 | caif_read_unlock(sk); |
| 534 | |||
| 535 | /* | ||
| 536 | * Blocking mode; state is pending and we need to wait | ||
| 537 | * for its conclusion. | ||
| 538 | */ | ||
| 539 | result = | ||
| 540 | wait_event_interruptible(*cf_sk->sk.sk_sleep, | ||
| 541 | !STATE_IS_PENDING(cf_sk)); | ||
| 542 | /* I want to be alone on cf_sk (except status and queue) */ | ||
| 543 | lock_sock(&(cf_sk->sk)); | ||
| 544 | 495 | ||
| 545 | if (result == -ERESTARTSYS) { | 496 | out: |
| 546 | pr_debug("CAIF: %s(): wait_event_interruptible" | 497 | return copied ? : err; |
| 547 | " woken by a signal (1)", __func__); | 498 | } |
| 548 | ret = -ERESTARTSYS; | ||
| 549 | goto write_error; | ||
| 550 | } | ||
| 551 | } | ||
| 552 | if (STATE_IS_REMOTE_SHUTDOWN(cf_sk) || | ||
| 553 | !STATE_IS_OPEN(cf_sk) || | ||
| 554 | STATE_IS_PENDING(cf_sk)) { | ||
| 555 | 499 | ||
| 556 | pr_debug("CAIF: %s(): socket closed\n", | 500 | /* |
| 557 | __func__); | 501 | * Copied from sock.c:sock_wait_for_wmem, but change to wait for |
| 558 | ret = -ESHUTDOWN; | 502 | * CAIF flow-on and sock_writable. |
| 559 | goto write_error; | 503 | */ |
| 504 | static long caif_wait_for_flow_on(struct caifsock *cf_sk, | ||
| 505 | int wait_writeable, long timeo, int *err) | ||
| 506 | { | ||
| 507 | struct sock *sk = &cf_sk->sk; | ||
| 508 | DEFINE_WAIT(wait); | ||
| 509 | for (;;) { | ||
| 510 | *err = 0; | ||
| 511 | if (tx_flow_is_on(cf_sk) && | ||
| 512 | (!wait_writeable || sock_writeable(&cf_sk->sk))) | ||
| 513 | break; | ||
| 514 | *err = -ETIMEDOUT; | ||
| 515 | if (!timeo) | ||
| 516 | break; | ||
| 517 | *err = -ERESTARTSYS; | ||
| 518 | if (signal_pending(current)) | ||
| 519 | break; | ||
| 520 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
| 521 | *err = -ECONNRESET; | ||
| 522 | if (sk->sk_shutdown & SHUTDOWN_MASK) | ||
| 523 | break; | ||
| 524 | *err = -sk->sk_err; | ||
| 525 | if (sk->sk_err) | ||
| 526 | break; | ||
| 527 | *err = -EPIPE; | ||
| 528 | if (cf_sk->sk.sk_state != CAIF_CONNECTED) | ||
| 529 | break; | ||
| 530 | timeo = schedule_timeout(timeo); | ||
| 560 | } | 531 | } |
| 532 | finish_wait(sk_sleep(sk), &wait); | ||
| 533 | return timeo; | ||
| 534 | } | ||
| 561 | 535 | ||
| 562 | if (!TX_FLOW_IS_ON(cf_sk)) { | 536 | /* |
| 537 | * Transmit a SKB. The device may temporarily request re-transmission | ||
| 538 | * by returning EAGAIN. | ||
| 539 | */ | ||
| 540 | static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk, | ||
| 541 | int noblock, long timeo) | ||
| 542 | { | ||
| 543 | struct cfpkt *pkt; | ||
| 544 | int ret, loopcnt = 0; | ||
| 563 | 545 | ||
| 564 | /* Flow is off. Check non-block flag */ | 546 | pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb); |
| 565 | if (msg->msg_flags & MSG_DONTWAIT) { | 547 | memset(cfpkt_info(pkt), 0, sizeof(struct caif_payload_info)); |
| 566 | trace_printk("CAIF: %s(): MSG_DONTWAIT and tx flow off", | 548 | do { |
| 567 | __func__); | ||
| 568 | ret = -EAGAIN; | ||
| 569 | goto write_error; | ||
| 570 | } | ||
| 571 | 549 | ||
| 572 | /* release lock before waiting */ | 550 | ret = -ETIMEDOUT; |
| 573 | release_sock(&cf_sk->sk); | ||
| 574 | 551 | ||
| 575 | /* Wait until flow is on or socket is closed */ | 552 | /* Slight paranoia, probably not needed. */ |
| 576 | if (wait_event_interruptible(*cf_sk->sk.sk_sleep, | 553 | if (unlikely(loopcnt++ > 1000)) { |
| 577 | TX_FLOW_IS_ON(cf_sk) | 554 | pr_warning("CAIF: %s(): transmit retries failed," |
| 578 | || !STATE_IS_OPEN(cf_sk) | 555 | " error = %d\n", __func__, ret); |
| 579 | || STATE_IS_REMOTE_SHUTDOWN(cf_sk) | 556 | break; |
| 580 | ) == -ERESTARTSYS) { | ||
| 581 | pr_debug("CAIF: %s():" | ||
| 582 | " wait_event_interruptible woken by a signal", | ||
| 583 | __func__); | ||
| 584 | ret = -ERESTARTSYS; | ||
| 585 | goto write_error_no_unlock; | ||
| 586 | } | 557 | } |
| 587 | 558 | ||
| 588 | /* I want to be alone on cf_sk (except status and queue) */ | 559 | if (cf_sk->layer.dn != NULL) |
| 589 | lock_sock(&(cf_sk->sk)); | 560 | ret = cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt); |
| 590 | 561 | if (likely(ret >= 0)) | |
| 591 | if (!STATE_IS_OPEN(cf_sk)) { | 562 | break; |
| 592 | /* someone closed the link, report error */ | 563 | /* if transmit return -EAGAIN, then retry */ |
| 593 | pr_debug("CAIF: %s(): remote end shutdown!\n", | 564 | if (noblock && ret == -EAGAIN) |
| 594 | __func__); | 565 | break; |
| 595 | ret = -EPIPE; | 566 | timeo = caif_wait_for_flow_on(cf_sk, 0, timeo, &ret); |
| 596 | goto write_error; | 567 | if (signal_pending(current)) { |
| 568 | ret = sock_intr_errno(timeo); | ||
| 569 | break; | ||
| 597 | } | 570 | } |
| 598 | 571 | if (ret) | |
| 599 | if (STATE_IS_REMOTE_SHUTDOWN(cf_sk)) { | 572 | break; |
| 600 | pr_debug("CAIF: %s(): " | 573 | if (cf_sk->sk.sk_state != CAIF_CONNECTED || |
| 601 | "received remote_shutdown indication\n", | 574 | sock_flag(&cf_sk->sk, SOCK_DEAD) || |
| 602 | __func__); | 575 | (cf_sk->sk.sk_shutdown & RCV_SHUTDOWN)) { |
| 603 | ret = -ESHUTDOWN; | 576 | ret = -EPIPE; |
| 604 | goto write_error; | 577 | cf_sk->sk.sk_err = EPIPE; |
| 578 | break; | ||
| 605 | } | 579 | } |
| 606 | } | 580 | } while (ret == -EAGAIN); |
| 581 | return ret; | ||
| 582 | } | ||
| 607 | 583 | ||
| 608 | pkt = cfpkt_create(payload_size); | 584 | /* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */ |
| 609 | skb = (struct sk_buff *)pkt; | 585 | static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock, |
| 610 | skb->destructor = skb_destructor; | 586 | struct msghdr *msg, size_t len) |
| 611 | skb->sk = sk; | 587 | { |
| 612 | dbfs_atomic_inc(&cnt.skb_alloc); | 588 | struct sock *sk = sock->sk; |
| 613 | dbfs_atomic_inc(&cnt.skb_in_use); | 589 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
| 614 | if (cfpkt_raw_append(pkt, (void **) &txbuf, payload_size) < 0) { | 590 | int buffer_size; |
| 615 | pr_debug("CAIF: %s(): cfpkt_raw_append failed\n", __func__); | 591 | int ret = 0; |
| 616 | cfpkt_destroy(pkt); | 592 | struct sk_buff *skb = NULL; |
| 617 | ret = -EINVAL; | 593 | int noblock; |
| 618 | goto write_error; | 594 | long timeo; |
| 619 | } | 595 | caif_assert(cf_sk); |
| 596 | ret = sock_error(sk); | ||
| 597 | if (ret) | ||
| 598 | goto err; | ||
| 599 | |||
| 600 | ret = -EOPNOTSUPP; | ||
| 601 | if (msg->msg_flags&MSG_OOB) | ||
| 602 | goto err; | ||
| 603 | |||
| 604 | ret = -EOPNOTSUPP; | ||
| 605 | if (msg->msg_namelen) | ||
| 606 | goto err; | ||
| 607 | |||
| 608 | ret = -EINVAL; | ||
| 609 | if (unlikely(msg->msg_iov->iov_base == NULL)) | ||
| 610 | goto err; | ||
| 611 | noblock = msg->msg_flags & MSG_DONTWAIT; | ||
| 612 | |||
| 613 | buffer_size = len + CAIF_NEEDED_HEADROOM + CAIF_NEEDED_TAILROOM; | ||
| 614 | |||
| 615 | ret = -EMSGSIZE; | ||
| 616 | if (buffer_size > CAIF_MAX_PAYLOAD_SIZE) | ||
| 617 | goto err; | ||
| 618 | |||
| 619 | timeo = sock_sndtimeo(sk, noblock); | ||
| 620 | timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk), | ||
| 621 | 1, timeo, &ret); | ||
| 622 | |||
| 623 | ret = -EPIPE; | ||
| 624 | if (cf_sk->sk.sk_state != CAIF_CONNECTED || | ||
| 625 | sock_flag(sk, SOCK_DEAD) || | ||
| 626 | (sk->sk_shutdown & RCV_SHUTDOWN)) | ||
| 627 | goto err; | ||
| 628 | |||
| 629 | ret = -ENOMEM; | ||
| 630 | skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret); | ||
| 631 | if (!skb) | ||
| 632 | goto err; | ||
| 633 | skb_reserve(skb, CAIF_NEEDED_HEADROOM); | ||
| 634 | |||
| 635 | ret = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | ||
| 636 | |||
| 637 | if (ret) | ||
| 638 | goto err; | ||
| 639 | ret = transmit_skb(skb, cf_sk, noblock, timeo); | ||
| 640 | if (ret < 0) | ||
| 641 | goto err; | ||
| 642 | return len; | ||
| 643 | err: | ||
| 644 | kfree_skb(skb); | ||
| 645 | return ret; | ||
| 646 | } | ||
| 620 | 647 | ||
| 621 | /* Copy data into buffer. */ | 648 | /* |
| 622 | if (copy_from_user(txbuf, msg->msg_iov->iov_base, payload_size)) { | 649 | * Copied from unix_stream_sendmsg and adapted to CAIF: |
| 623 | pr_debug("CAIF: %s(): copy_from_user returned non zero.\n", | 650 | * Changed removed permission handling and added waiting for flow on |
| 624 | __func__); | 651 | * and other minor adaptations. |
| 625 | cfpkt_destroy(pkt); | 652 | */ |
| 626 | ret = -EINVAL; | 653 | static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, |
| 627 | goto write_error; | 654 | struct msghdr *msg, size_t len) |
| 628 | } | 655 | { |
| 629 | memset(&info, 0, sizeof(info)); | 656 | struct sock *sk = sock->sk; |
| 657 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
| 658 | int err, size; | ||
| 659 | struct sk_buff *skb; | ||
| 660 | int sent = 0; | ||
| 661 | long timeo; | ||
| 630 | 662 | ||
| 631 | /* Send the packet down the stack. */ | 663 | err = -EOPNOTSUPP; |
| 632 | caif_assert(cf_sk->layer.dn); | ||
| 633 | caif_assert(cf_sk->layer.dn->transmit); | ||
| 634 | 664 | ||
| 635 | do { | 665 | if (unlikely(msg->msg_flags&MSG_OOB)) |
| 636 | ret = cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt); | 666 | goto out_err; |
| 637 | 667 | ||
| 638 | if (likely((ret >= 0) || (ret != -EAGAIN))) | 668 | if (unlikely(msg->msg_namelen)) |
| 639 | break; | 669 | goto out_err; |
| 640 | 670 | ||
| 641 | /* EAGAIN - retry */ | 671 | timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); |
| 642 | if (msg->msg_flags & MSG_DONTWAIT) { | 672 | timeo = caif_wait_for_flow_on(cf_sk, 1, timeo, &err); |
| 643 | pr_debug("CAIF: %s(): NONBLOCK and transmit failed," | ||
| 644 | " error = %ld\n", __func__, (long) ret); | ||
| 645 | ret = -EAGAIN; | ||
| 646 | goto write_error; | ||
| 647 | } | ||
| 648 | 673 | ||
| 649 | /* Let readers in */ | 674 | if (unlikely(sk->sk_shutdown & SEND_SHUTDOWN)) |
| 650 | release_sock(&cf_sk->sk); | 675 | goto pipe_err; |
| 651 | 676 | ||
| 652 | /* Wait until flow is on or socket is closed */ | 677 | while (sent < len) { |
| 653 | if (wait_event_interruptible(*cf_sk->sk.sk_sleep, | ||
| 654 | TX_FLOW_IS_ON(cf_sk) | ||
| 655 | || !STATE_IS_OPEN(cf_sk) | ||
| 656 | || STATE_IS_REMOTE_SHUTDOWN(cf_sk) | ||
| 657 | ) == -ERESTARTSYS) { | ||
| 658 | pr_debug("CAIF: %s(): wait_event_interruptible" | ||
| 659 | " woken by a signal", __func__); | ||
| 660 | ret = -ERESTARTSYS; | ||
| 661 | goto write_error_no_unlock; | ||
| 662 | } | ||
| 663 | 678 | ||
| 664 | /* I want to be alone on cf_sk (except status and queue) */ | 679 | size = len-sent; |
| 665 | lock_sock(&(cf_sk->sk)); | ||
| 666 | 680 | ||
| 667 | } while (ret == -EAGAIN); | 681 | if (size > CAIF_MAX_PAYLOAD_SIZE) |
| 682 | size = CAIF_MAX_PAYLOAD_SIZE; | ||
| 668 | 683 | ||
| 669 | if (ret < 0) { | 684 | /* If size is more than half of sndbuf, chop up message */ |
| 670 | cfpkt_destroy(pkt); | 685 | if (size > ((sk->sk_sndbuf >> 1) - 64)) |
| 671 | pr_debug("CAIF: %s(): transmit failed, error = %ld\n", | 686 | size = (sk->sk_sndbuf >> 1) - 64; |
| 672 | __func__, (long) ret); | ||
| 673 | 687 | ||
| 674 | goto write_error; | 688 | if (size > SKB_MAX_ALLOC) |
| 675 | } | 689 | size = SKB_MAX_ALLOC; |
| 676 | 690 | ||
| 677 | release_sock(&cf_sk->sk); | 691 | skb = sock_alloc_send_skb(sk, |
| 678 | return payload_size; | 692 | size + CAIF_NEEDED_HEADROOM |
| 693 | + CAIF_NEEDED_TAILROOM, | ||
| 694 | msg->msg_flags&MSG_DONTWAIT, | ||
| 695 | &err); | ||
| 696 | if (skb == NULL) | ||
| 697 | goto out_err; | ||
| 679 | 698 | ||
| 680 | write_error: | 699 | skb_reserve(skb, CAIF_NEEDED_HEADROOM); |
| 681 | release_sock(&cf_sk->sk); | 700 | /* |
| 682 | write_error_no_unlock: | 701 | * If you pass two values to the sock_alloc_send_skb |
| 683 | return ret; | 702 | * it tries to grab the large buffer with GFP_NOFS |
| 684 | } | 703 | * (which can fail easily), and if it fails grab the |
| 704 | * fallback size buffer which is under a page and will | ||
| 705 | * succeed. [Alan] | ||
| 706 | */ | ||
| 707 | size = min_t(int, size, skb_tailroom(skb)); | ||
| 685 | 708 | ||
| 686 | static unsigned int caif_poll(struct file *file, struct socket *sock, | 709 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); |
| 687 | poll_table *wait) | 710 | if (err) { |
| 688 | { | 711 | kfree_skb(skb); |
| 689 | struct sock *sk = sock->sk; | 712 | goto out_err; |
| 690 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | 713 | } |
| 691 | u32 mask = 0; | 714 | err = transmit_skb(skb, cf_sk, |
| 692 | poll_wait(file, sk->sk_sleep, wait); | 715 | msg->msg_flags&MSG_DONTWAIT, timeo); |
| 693 | lock_sock(&(cf_sk->sk)); | 716 | if (err < 0) { |
| 694 | if (!STATE_IS_OPEN(cf_sk)) { | 717 | kfree_skb(skb); |
| 695 | if (!STATE_IS_PENDING(cf_sk)) | 718 | goto pipe_err; |
| 696 | mask |= POLLHUP; | 719 | } |
| 697 | } else { | 720 | sent += size; |
| 698 | if (cfpkt_qpeek(cf_sk->pktq) != NULL) | ||
| 699 | mask |= (POLLIN | POLLRDNORM); | ||
| 700 | if (TX_FLOW_IS_ON(cf_sk)) | ||
| 701 | mask |= (POLLOUT | POLLWRNORM); | ||
| 702 | } | 721 | } |
| 703 | release_sock(&cf_sk->sk); | ||
| 704 | trace_printk("CAIF: %s(): poll mask=0x%04x\n", | ||
| 705 | __func__, mask); | ||
| 706 | return mask; | ||
| 707 | } | ||
| 708 | |||
| 709 | static void drain_queue(struct caifsock *cf_sk) | ||
| 710 | { | ||
| 711 | struct cfpkt *pkt = NULL; | ||
| 712 | |||
| 713 | /* Empty the queue */ | ||
| 714 | do { | ||
| 715 | /* The queue has its own lock */ | ||
| 716 | if (!cf_sk->pktq) | ||
| 717 | break; | ||
| 718 | |||
| 719 | pkt = cfpkt_dequeue(cf_sk->pktq); | ||
| 720 | if (!pkt) | ||
| 721 | break; | ||
| 722 | pr_debug("CAIF: %s(): freeing packet from read queue\n", | ||
| 723 | __func__); | ||
| 724 | cfpkt_destroy(pkt); | ||
| 725 | 722 | ||
| 726 | } while (1); | 723 | return sent; |
| 727 | 724 | ||
| 728 | cf_sk->read_queue_len = 0; | 725 | pipe_err: |
| 726 | if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL)) | ||
| 727 | send_sig(SIGPIPE, current, 0); | ||
| 728 | err = -EPIPE; | ||
| 729 | out_err: | ||
| 730 | return sent ? : err; | ||
| 729 | } | 731 | } |
| 730 | 732 | ||
| 731 | static int setsockopt(struct socket *sock, | 733 | static int setsockopt(struct socket *sock, |
| @@ -736,19 +738,13 @@ static int setsockopt(struct socket *sock, | |||
| 736 | int prio, linksel; | 738 | int prio, linksel; |
| 737 | struct ifreq ifreq; | 739 | struct ifreq ifreq; |
| 738 | 740 | ||
| 739 | if (STATE_IS_OPEN(cf_sk)) { | 741 | if (cf_sk->sk.sk_socket->state != SS_UNCONNECTED) |
| 740 | pr_debug("CAIF: %s(): setsockopt " | ||
| 741 | "cannot be done on a connected socket\n", | ||
| 742 | __func__); | ||
| 743 | return -ENOPROTOOPT; | 742 | return -ENOPROTOOPT; |
| 744 | } | 743 | |
| 745 | switch (opt) { | 744 | switch (opt) { |
| 746 | case CAIFSO_LINK_SELECT: | 745 | case CAIFSO_LINK_SELECT: |
| 747 | if (ol < sizeof(int)) { | 746 | if (ol < sizeof(int)) |
| 748 | pr_debug("CAIF: %s(): setsockopt" | ||
| 749 | " CAIFSO_CHANNEL_CONFIG bad size\n", __func__); | ||
| 750 | return -EINVAL; | 747 | return -EINVAL; |
| 751 | } | ||
| 752 | if (lvl != SOL_CAIF) | 748 | if (lvl != SOL_CAIF) |
| 753 | goto bad_sol; | 749 | goto bad_sol; |
| 754 | if (copy_from_user(&linksel, ov, sizeof(int))) | 750 | if (copy_from_user(&linksel, ov, sizeof(int))) |
| @@ -761,28 +757,20 @@ static int setsockopt(struct socket *sock, | |||
| 761 | case SO_PRIORITY: | 757 | case SO_PRIORITY: |
| 762 | if (lvl != SOL_SOCKET) | 758 | if (lvl != SOL_SOCKET) |
| 763 | goto bad_sol; | 759 | goto bad_sol; |
| 764 | if (ol < sizeof(int)) { | 760 | if (ol < sizeof(int)) |
| 765 | pr_debug("CAIF: %s(): setsockopt" | ||
| 766 | " SO_PRIORITY bad size\n", __func__); | ||
| 767 | return -EINVAL; | 761 | return -EINVAL; |
| 768 | } | ||
| 769 | if (copy_from_user(&prio, ov, sizeof(int))) | 762 | if (copy_from_user(&prio, ov, sizeof(int))) |
| 770 | return -EINVAL; | 763 | return -EINVAL; |
| 771 | lock_sock(&(cf_sk->sk)); | 764 | lock_sock(&(cf_sk->sk)); |
| 772 | cf_sk->conn_req.priority = prio; | 765 | cf_sk->conn_req.priority = prio; |
| 773 | pr_debug("CAIF: %s(): Setting sockopt priority=%d\n", __func__, | ||
| 774 | cf_sk->conn_req.priority); | ||
| 775 | release_sock(&cf_sk->sk); | 766 | release_sock(&cf_sk->sk); |
| 776 | return 0; | 767 | return 0; |
| 777 | 768 | ||
| 778 | case SO_BINDTODEVICE: | 769 | case SO_BINDTODEVICE: |
| 779 | if (lvl != SOL_SOCKET) | 770 | if (lvl != SOL_SOCKET) |
| 780 | goto bad_sol; | 771 | goto bad_sol; |
| 781 | if (ol < sizeof(struct ifreq)) { | 772 | if (ol < sizeof(struct ifreq)) |
| 782 | pr_debug("CAIF: %s(): setsockopt" | ||
| 783 | " SO_PRIORITY bad size\n", __func__); | ||
| 784 | return -EINVAL; | 773 | return -EINVAL; |
| 785 | } | ||
| 786 | if (copy_from_user(&ifreq, ov, sizeof(ifreq))) | 774 | if (copy_from_user(&ifreq, ov, sizeof(ifreq))) |
| 787 | return -EFAULT; | 775 | return -EFAULT; |
| 788 | lock_sock(&(cf_sk->sk)); | 776 | lock_sock(&(cf_sk->sk)); |
| @@ -798,359 +786,275 @@ static int setsockopt(struct socket *sock, | |||
| 798 | goto bad_sol; | 786 | goto bad_sol; |
| 799 | if (cf_sk->sk.sk_protocol != CAIFPROTO_UTIL) | 787 | if (cf_sk->sk.sk_protocol != CAIFPROTO_UTIL) |
| 800 | return -ENOPROTOOPT; | 788 | return -ENOPROTOOPT; |
| 801 | if (ol > sizeof(cf_sk->conn_req.param.data)) | ||
| 802 | goto req_param_bad_size; | ||
| 803 | |||
| 804 | lock_sock(&(cf_sk->sk)); | 789 | lock_sock(&(cf_sk->sk)); |
| 805 | cf_sk->conn_req.param.size = ol; | 790 | cf_sk->conn_req.param.size = ol; |
| 806 | if (copy_from_user(&cf_sk->conn_req.param.data, ov, ol)) { | 791 | if (ol > sizeof(cf_sk->conn_req.param.data) || |
| 792 | copy_from_user(&cf_sk->conn_req.param.data, ov, ol)) { | ||
| 807 | release_sock(&cf_sk->sk); | 793 | release_sock(&cf_sk->sk); |
| 808 | req_param_bad_size: | ||
| 809 | pr_debug("CAIF: %s(): setsockopt" | ||
| 810 | " CAIFSO_CHANNEL_CONFIG bad size\n", __func__); | ||
| 811 | return -EINVAL; | 794 | return -EINVAL; |
| 812 | } | 795 | } |
| 813 | |||
| 814 | release_sock(&cf_sk->sk); | 796 | release_sock(&cf_sk->sk); |
| 815 | return 0; | 797 | return 0; |
| 816 | 798 | ||
| 817 | default: | 799 | default: |
| 818 | pr_debug("CAIF: %s(): unhandled option %d\n", __func__, opt); | 800 | return -ENOPROTOOPT; |
| 819 | return -EINVAL; | ||
| 820 | } | 801 | } |
| 821 | 802 | ||
| 822 | return 0; | 803 | return 0; |
| 823 | bad_sol: | 804 | bad_sol: |
| 824 | pr_debug("CAIF: %s(): setsockopt bad level\n", __func__); | ||
| 825 | return -ENOPROTOOPT; | 805 | return -ENOPROTOOPT; |
| 826 | 806 | ||
| 827 | } | 807 | } |
| 828 | 808 | ||
| 829 | static int caif_connect(struct socket *sock, struct sockaddr *uservaddr, | 809 | /* |
| 830 | int sockaddr_len, int flags) | 810 | * caif_connect() - Connect a CAIF Socket |
| 811 | * Copied and modified af_irda.c:irda_connect(). | ||
| 812 | * | ||
| 813 | * Note : by consulting "errno", the user space caller may learn the cause | ||
| 814 | * of the failure. Most of them are visible in the function, others may come | ||
| 815 | * from subroutines called and are listed here : | ||
| 816 | * o -EAFNOSUPPORT: bad socket family or type. | ||
| 817 | * o -ESOCKTNOSUPPORT: bad socket type or protocol | ||
| 818 | * o -EINVAL: bad socket address, or CAIF link type | ||
| 819 | * o -ECONNREFUSED: remote end refused the connection. | ||
| 820 | * o -EINPROGRESS: connect request sent but timed out (or non-blocking) | ||
| 821 | * o -EISCONN: already connected. | ||
| 822 | * o -ETIMEDOUT: Connection timed out (send timeout) | ||
| 823 | * o -ENODEV: No link layer to send request | ||
| 824 | * o -ECONNRESET: Received Shutdown indication or lost link layer | ||
| 825 | * o -ENOMEM: Out of memory | ||
| 826 | * | ||
| 827 | * State Strategy: | ||
| 828 | * o sk_state: holds the CAIF_* protocol state, it's updated by | ||
| 829 | * caif_ctrl_cb. | ||
| 830 | * o sock->state: holds the SS_* socket state and is updated by connect and | ||
| 831 | * disconnect. | ||
| 832 | */ | ||
| 833 | static int caif_connect(struct socket *sock, struct sockaddr *uaddr, | ||
| 834 | int addr_len, int flags) | ||
| 831 | { | 835 | { |
| 832 | struct caifsock *cf_sk = NULL; | ||
| 833 | int result = -1; | ||
| 834 | int mode = 0; | ||
| 835 | int ret = -EIO; | ||
| 836 | struct sock *sk = sock->sk; | 836 | struct sock *sk = sock->sk; |
| 837 | BUG_ON(sk == NULL); | 837 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
| 838 | 838 | long timeo; | |
| 839 | cf_sk = container_of(sk, struct caifsock, sk); | 839 | int err; |
| 840 | 840 | lock_sock(sk); | |
| 841 | trace_printk("CAIF: %s(): cf_sk=%p OPEN=%d, TX_FLOW=%d, RX_FLOW=%d\n", | ||
| 842 | __func__, cf_sk, | ||
| 843 | STATE_IS_OPEN(cf_sk), | ||
| 844 | TX_FLOW_IS_ON(cf_sk), RX_FLOW_IS_ON(cf_sk)); | ||
| 845 | |||
| 846 | 841 | ||
| 847 | if (sock->type == SOCK_SEQPACKET || sock->type == SOCK_STREAM) | 842 | err = -EAFNOSUPPORT; |
| 848 | sock->state = SS_CONNECTING; | 843 | if (uaddr->sa_family != AF_CAIF) |
| 849 | else | ||
| 850 | goto out; | 844 | goto out; |
| 851 | 845 | ||
| 852 | /* I want to be alone on cf_sk (except status and queue) */ | 846 | err = -ESOCKTNOSUPPORT; |
| 853 | lock_sock(&(cf_sk->sk)); | 847 | if (unlikely(!(sk->sk_type == SOCK_STREAM && |
| 854 | 848 | cf_sk->sk.sk_protocol == CAIFPROTO_AT) && | |
| 855 | if (sockaddr_len != sizeof(struct sockaddr_caif)) { | 849 | sk->sk_type != SOCK_SEQPACKET)) |
| 856 | pr_debug("CAIF: %s(): Bad address len (%ld,%lu)\n", | 850 | goto out; |
| 857 | __func__, (long) sockaddr_len, | 851 | switch (sock->state) { |
| 858 | (long unsigned) sizeof(struct sockaddr_caif)); | 852 | case SS_UNCONNECTED: |
| 859 | ret = -EINVAL; | 853 | /* Normal case, a fresh connect */ |
| 860 | goto open_error; | 854 | caif_assert(sk->sk_state == CAIF_DISCONNECTED); |
| 855 | break; | ||
| 856 | case SS_CONNECTING: | ||
| 857 | switch (sk->sk_state) { | ||
| 858 | case CAIF_CONNECTED: | ||
| 859 | sock->state = SS_CONNECTED; | ||
| 860 | err = -EISCONN; | ||
| 861 | goto out; | ||
| 862 | case CAIF_DISCONNECTED: | ||
| 863 | /* Reconnect allowed */ | ||
| 864 | break; | ||
| 865 | case CAIF_CONNECTING: | ||
| 866 | err = -EALREADY; | ||
| 867 | if (flags & O_NONBLOCK) | ||
| 868 | goto out; | ||
| 869 | goto wait_connect; | ||
| 870 | } | ||
| 871 | break; | ||
| 872 | case SS_CONNECTED: | ||
| 873 | caif_assert(sk->sk_state == CAIF_CONNECTED || | ||
| 874 | sk->sk_state == CAIF_DISCONNECTED); | ||
| 875 | if (sk->sk_shutdown & SHUTDOWN_MASK) { | ||
| 876 | /* Allow re-connect after SHUTDOWN_IND */ | ||
| 877 | caif_disconnect_client(&cf_sk->layer); | ||
| 878 | break; | ||
| 879 | } | ||
| 880 | /* No reconnect on a seqpacket socket */ | ||
| 881 | err = -EISCONN; | ||
| 882 | goto out; | ||
| 883 | case SS_DISCONNECTING: | ||
| 884 | case SS_FREE: | ||
| 885 | caif_assert(1); /*Should never happen */ | ||
| 886 | break; | ||
| 861 | } | 887 | } |
| 888 | sk->sk_state = CAIF_DISCONNECTED; | ||
| 889 | sock->state = SS_UNCONNECTED; | ||
| 890 | sk_stream_kill_queues(&cf_sk->sk); | ||
| 862 | 891 | ||
| 863 | if (uservaddr->sa_family != AF_CAIF) { | 892 | err = -EINVAL; |
| 864 | pr_debug("CAIF: %s(): Bad address family (%d)\n", | 893 | if (addr_len != sizeof(struct sockaddr_caif) || |
| 865 | __func__, uservaddr->sa_family); | 894 | !uaddr) |
| 866 | ret = -EAFNOSUPPORT; | 895 | goto out; |
| 867 | goto open_error; | ||
| 868 | } | ||
| 869 | 896 | ||
| 870 | memcpy(&cf_sk->conn_req.sockaddr, uservaddr, | 897 | memcpy(&cf_sk->conn_req.sockaddr, uaddr, |
| 871 | sizeof(struct sockaddr_caif)); | 898 | sizeof(struct sockaddr_caif)); |
| 872 | 899 | ||
| 873 | dbfs_atomic_inc(&cnt.num_open); | 900 | /* Move to connecting socket, start sending Connect Requests */ |
| 874 | mode = SKT_READ_FLAG | SKT_WRITE_FLAG; | 901 | sock->state = SS_CONNECTING; |
| 875 | 902 | sk->sk_state = CAIF_CONNECTING; | |
| 876 | /* If socket is not open, make sure socket is in fully closed state */ | 903 | |
| 877 | if (!STATE_IS_OPEN(cf_sk)) { | 904 | dbfs_atomic_inc(&cnt.num_connect_req); |
| 878 | /* Has link close response been received (if we ever sent it)?*/ | 905 | cf_sk->layer.receive = caif_sktrecv_cb; |
| 879 | if (STATE_IS_PENDING(cf_sk)) { | 906 | err = caif_connect_client(&cf_sk->conn_req, |
| 880 | /* | 907 | &cf_sk->layer); |
| 881 | * Still waiting for close response from remote. | 908 | if (err < 0) { |
| 882 | * If opened non-blocking, report "would block" | 909 | cf_sk->sk.sk_socket->state = SS_UNCONNECTED; |
| 883 | */ | 910 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; |
| 884 | if (flags & O_NONBLOCK) { | 911 | goto out; |
| 885 | pr_debug("CAIF: %s(): O_NONBLOCK" | ||
| 886 | " && close pending\n", __func__); | ||
| 887 | ret = -EAGAIN; | ||
| 888 | goto open_error; | ||
| 889 | } | ||
| 890 | |||
| 891 | pr_debug("CAIF: %s(): Wait for close response" | ||
| 892 | " from remote...\n", __func__); | ||
| 893 | |||
| 894 | release_sock(&cf_sk->sk); | ||
| 895 | |||
| 896 | /* | ||
| 897 | * Blocking mode; close is pending and we need to wait | ||
| 898 | * for its conclusion. | ||
| 899 | */ | ||
| 900 | result = | ||
| 901 | wait_event_interruptible(*cf_sk->sk.sk_sleep, | ||
| 902 | !STATE_IS_PENDING(cf_sk)); | ||
| 903 | |||
| 904 | lock_sock(&(cf_sk->sk)); | ||
| 905 | if (result == -ERESTARTSYS) { | ||
| 906 | pr_debug("CAIF: %s(): wait_event_interruptible" | ||
| 907 | "woken by a signal (1)", __func__); | ||
| 908 | ret = -ERESTARTSYS; | ||
| 909 | goto open_error; | ||
| 910 | } | ||
| 911 | } | ||
| 912 | } | 912 | } |
| 913 | 913 | ||
| 914 | /* socket is now either closed, pending open or open */ | 914 | err = -EINPROGRESS; |
| 915 | if (STATE_IS_OPEN(cf_sk) && !STATE_IS_PENDING(cf_sk)) { | 915 | wait_connect: |
| 916 | /* Open */ | ||
| 917 | pr_debug("CAIF: %s(): Socket is already opened (cf_sk=%p)" | ||
| 918 | " check access f_flags = 0x%x file_mode = 0x%x\n", | ||
| 919 | __func__, cf_sk, mode, cf_sk->file_mode); | ||
| 920 | |||
| 921 | } else { | ||
| 922 | /* We are closed or pending open. | ||
| 923 | * If closed: send link setup | ||
| 924 | * If pending open: link setup already sent (we could have been | ||
| 925 | * interrupted by a signal last time) | ||
| 926 | */ | ||
| 927 | if (!STATE_IS_OPEN(cf_sk)) { | ||
| 928 | /* First opening of file; connect lower layers: */ | ||
| 929 | /* Drain queue (very unlikely) */ | ||
| 930 | drain_queue(cf_sk); | ||
| 931 | |||
| 932 | cf_sk->layer.receive = caif_sktrecv_cb; | ||
| 933 | SET_STATE_OPEN(cf_sk); | ||
| 934 | SET_PENDING_ON(cf_sk); | ||
| 935 | |||
| 936 | /* Register this channel. */ | ||
| 937 | result = | ||
| 938 | caif_connect_client(&cf_sk->conn_req, | ||
| 939 | &cf_sk->layer); | ||
| 940 | if (result < 0) { | ||
| 941 | pr_debug("CAIF: %s(): can't register channel\n", | ||
| 942 | __func__); | ||
| 943 | ret = -EIO; | ||
| 944 | SET_STATE_CLOSED(cf_sk); | ||
| 945 | SET_PENDING_OFF(cf_sk); | ||
| 946 | goto open_error; | ||
| 947 | } | ||
| 948 | dbfs_atomic_inc(&cnt.num_init); | ||
| 949 | } | ||
| 950 | |||
| 951 | /* If opened non-blocking, report "success". | ||
| 952 | */ | ||
| 953 | if (flags & O_NONBLOCK) { | ||
| 954 | pr_debug("CAIF: %s(): O_NONBLOCK success\n", | ||
| 955 | __func__); | ||
| 956 | ret = -EINPROGRESS; | ||
| 957 | cf_sk->sk.sk_err = -EINPROGRESS; | ||
| 958 | goto open_error; | ||
| 959 | } | ||
| 960 | |||
| 961 | trace_printk("CAIF: %s(): Wait for connect response\n", | ||
| 962 | __func__); | ||
| 963 | 916 | ||
| 964 | /* release lock before waiting */ | 917 | if (sk->sk_state != CAIF_CONNECTED && (flags & O_NONBLOCK)) |
| 965 | release_sock(&cf_sk->sk); | 918 | goto out; |
| 966 | |||
| 967 | result = | ||
| 968 | wait_event_interruptible(*cf_sk->sk.sk_sleep, | ||
| 969 | !STATE_IS_PENDING(cf_sk)); | ||
| 970 | |||
| 971 | lock_sock(&(cf_sk->sk)); | ||
| 972 | |||
| 973 | if (result == -ERESTARTSYS) { | ||
| 974 | pr_debug("CAIF: %s(): wait_event_interruptible" | ||
| 975 | "woken by a signal (2)", __func__); | ||
| 976 | ret = -ERESTARTSYS; | ||
| 977 | goto open_error; | ||
| 978 | } | ||
| 979 | |||
| 980 | if (!STATE_IS_OPEN(cf_sk)) { | ||
| 981 | /* Lower layers said "no" */ | ||
| 982 | pr_debug("CAIF: %s(): Closed received\n", __func__); | ||
| 983 | ret = -EPIPE; | ||
| 984 | goto open_error; | ||
| 985 | } | ||
| 986 | 919 | ||
| 987 | trace_printk("CAIF: %s(): Connect received\n", __func__); | 920 | timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); |
| 921 | |||
| 922 | release_sock(sk); | ||
| 923 | err = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
| 924 | sk->sk_state != CAIF_CONNECTING, | ||
| 925 | timeo); | ||
| 926 | lock_sock(sk); | ||
| 927 | if (err < 0) | ||
| 928 | goto out; /* -ERESTARTSYS */ | ||
| 929 | if (err == 0 && sk->sk_state != CAIF_CONNECTED) { | ||
| 930 | err = -ETIMEDOUT; | ||
| 931 | goto out; | ||
| 988 | } | 932 | } |
| 989 | /* Open is ok */ | ||
| 990 | cf_sk->file_mode |= mode; | ||
| 991 | 933 | ||
| 992 | trace_printk("CAIF: %s(): Connected - file mode = %x\n", | 934 | if (sk->sk_state != CAIF_CONNECTED) { |
| 993 | __func__, cf_sk->file_mode); | 935 | sock->state = SS_UNCONNECTED; |
| 994 | 936 | err = sock_error(sk); | |
| 995 | release_sock(&cf_sk->sk); | 937 | if (!err) |
| 996 | return 0; | 938 | err = -ECONNREFUSED; |
| 997 | open_error: | 939 | goto out; |
| 998 | sock->state = SS_UNCONNECTED; | 940 | } |
| 999 | release_sock(&cf_sk->sk); | 941 | sock->state = SS_CONNECTED; |
| 942 | err = 0; | ||
| 1000 | out: | 943 | out: |
| 1001 | return ret; | 944 | release_sock(sk); |
| 945 | return err; | ||
| 1002 | } | 946 | } |
| 1003 | 947 | ||
| 1004 | static int caif_shutdown(struct socket *sock, int how) | 948 | |
| 949 | /* | ||
| 950 | * caif_release() - Disconnect a CAIF Socket | ||
| 951 | * Copied and modified af_irda.c:irda_release(). | ||
| 952 | */ | ||
| 953 | static int caif_release(struct socket *sock) | ||
| 1005 | { | 954 | { |
| 1006 | struct caifsock *cf_sk = NULL; | ||
| 1007 | int result = 0; | ||
| 1008 | int tx_flow_state_was_on; | ||
| 1009 | struct sock *sk = sock->sk; | 955 | struct sock *sk = sock->sk; |
| 956 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
| 957 | int res = 0; | ||
| 1010 | 958 | ||
| 1011 | trace_printk("CAIF: %s(): enter\n", __func__); | 959 | if (!sk) |
| 1012 | pr_debug("f_flags=%x\n", sock->file->f_flags); | 960 | return 0; |
| 1013 | |||
| 1014 | if (how != SHUT_RDWR) | ||
| 1015 | return -EOPNOTSUPP; | ||
| 1016 | |||
| 1017 | cf_sk = container_of(sk, struct caifsock, sk); | ||
| 1018 | if (cf_sk == NULL) { | ||
| 1019 | pr_debug("CAIF: %s(): COULD NOT FIND SOCKET\n", __func__); | ||
| 1020 | return -EBADF; | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | /* I want to be alone on cf_sk (except status queue) */ | ||
| 1024 | lock_sock(&(cf_sk->sk)); | ||
| 1025 | sock_hold(&cf_sk->sk); | ||
| 1026 | |||
| 1027 | /* IS_CLOSED have double meaning: | ||
| 1028 | * 1) Spontanous Remote Shutdown Request. | ||
| 1029 | * 2) Ack on a channel teardown(disconnect) | ||
| 1030 | * Must clear bit in case we previously received | ||
| 1031 | * remote shudown request. | ||
| 1032 | */ | ||
| 1033 | if (STATE_IS_OPEN(cf_sk) && !STATE_IS_PENDING(cf_sk)) { | ||
| 1034 | SET_STATE_CLOSED(cf_sk); | ||
| 1035 | SET_PENDING_ON(cf_sk); | ||
| 1036 | tx_flow_state_was_on = TX_FLOW_IS_ON(cf_sk); | ||
| 1037 | SET_TX_FLOW_OFF(cf_sk); | ||
| 1038 | |||
| 1039 | /* Hold the socket until DEINIT_RSP is received */ | ||
| 1040 | sock_hold(&cf_sk->sk); | ||
| 1041 | result = caif_disconnect_client(&cf_sk->layer); | ||
| 1042 | |||
| 1043 | if (result < 0) { | ||
| 1044 | pr_debug("CAIF: %s(): " | ||
| 1045 | "caif_disconnect_client() failed\n", | ||
| 1046 | __func__); | ||
| 1047 | SET_STATE_CLOSED(cf_sk); | ||
| 1048 | SET_PENDING_OFF(cf_sk); | ||
| 1049 | SET_TX_FLOW_OFF(cf_sk); | ||
| 1050 | release_sock(&cf_sk->sk); | ||
| 1051 | sock_put(&cf_sk->sk); | ||
| 1052 | return -EIO; | ||
| 1053 | } | ||
| 1054 | 961 | ||
| 1055 | } | 962 | set_tx_flow_off(cf_sk); |
| 1056 | if (STATE_IS_REMOTE_SHUTDOWN(cf_sk)) { | ||
| 1057 | SET_PENDING_OFF(cf_sk); | ||
| 1058 | SET_REMOTE_SHUTDOWN_OFF(cf_sk); | ||
| 1059 | } | ||
| 1060 | 963 | ||
| 1061 | /* | 964 | /* |
| 1062 | * Socket is no longer in state pending close, | 965 | * Ensure that packets are not queued after this point in time. |
| 1063 | * and we can release the reference. | 966 | * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock, |
| 967 | * this ensures no packets when sock is dead. | ||
| 1064 | */ | 968 | */ |
| 969 | spin_lock(&sk->sk_receive_queue.lock); | ||
| 970 | sock_set_flag(sk, SOCK_DEAD); | ||
| 971 | spin_unlock(&sk->sk_receive_queue.lock); | ||
| 972 | sock->sk = NULL; | ||
| 1065 | 973 | ||
| 1066 | dbfs_atomic_inc(&cnt.num_close); | 974 | dbfs_atomic_inc(&cnt.num_disconnect); |
| 1067 | drain_queue(cf_sk); | ||
| 1068 | SET_RX_FLOW_ON(cf_sk); | ||
| 1069 | cf_sk->file_mode = 0; | ||
| 1070 | sock_put(&cf_sk->sk); | ||
| 1071 | release_sock(&cf_sk->sk); | ||
| 1072 | if (!result && (sock->file->f_flags & O_NONBLOCK)) { | ||
| 1073 | pr_debug("nonblocking shutdown returing -EAGAIN\n"); | ||
| 1074 | return -EAGAIN; | ||
| 1075 | } else | ||
| 1076 | return result; | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | static ssize_t caif_sock_no_sendpage(struct socket *sock, | ||
| 1080 | struct page *page, | ||
| 1081 | int offset, size_t size, int flags) | ||
| 1082 | { | ||
| 1083 | return -EOPNOTSUPP; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | /* This function is called as part of close. */ | ||
| 1087 | static int caif_release(struct socket *sock) | ||
| 1088 | { | ||
| 1089 | struct sock *sk = sock->sk; | ||
| 1090 | struct caifsock *cf_sk = NULL; | ||
| 1091 | int res; | ||
| 1092 | caif_assert(sk != NULL); | ||
| 1093 | cf_sk = container_of(sk, struct caifsock, sk); | ||
| 1094 | 975 | ||
| 1095 | if (cf_sk->debugfs_socket_dir != NULL) | 976 | if (cf_sk->debugfs_socket_dir != NULL) |
| 1096 | debugfs_remove_recursive(cf_sk->debugfs_socket_dir); | 977 | debugfs_remove_recursive(cf_sk->debugfs_socket_dir); |
| 1097 | 978 | ||
| 1098 | res = caif_shutdown(sock, SHUT_RDWR); | ||
| 1099 | if (res && res != -EINPROGRESS) | ||
| 1100 | return res; | ||
| 1101 | |||
| 1102 | /* | ||
| 1103 | * FIXME: Shutdown should probably be possible to do async | ||
| 1104 | * without flushing queues, allowing reception of frames while | ||
| 1105 | * waiting for DEINIT_IND. | ||
| 1106 | * Release should always block, to allow secure decoupling of | ||
| 1107 | * CAIF stack. | ||
| 1108 | */ | ||
| 1109 | if (!(sock->file->f_flags & O_NONBLOCK)) { | ||
| 1110 | res = wait_event_interruptible(*cf_sk->sk.sk_sleep, | ||
| 1111 | !STATE_IS_PENDING(cf_sk)); | ||
| 1112 | |||
| 1113 | if (res == -ERESTARTSYS) { | ||
| 1114 | pr_debug("CAIF: %s(): wait_event_interruptible" | ||
| 1115 | "woken by a signal (1)", __func__); | ||
| 1116 | } | ||
| 1117 | } | ||
| 1118 | lock_sock(&(cf_sk->sk)); | 979 | lock_sock(&(cf_sk->sk)); |
| 980 | sk->sk_state = CAIF_DISCONNECTED; | ||
| 981 | sk->sk_shutdown = SHUTDOWN_MASK; | ||
| 1119 | 982 | ||
| 1120 | sock->sk = NULL; | 983 | if (cf_sk->sk.sk_socket->state == SS_CONNECTED || |
| 984 | cf_sk->sk.sk_socket->state == SS_CONNECTING) | ||
| 985 | res = caif_disconnect_client(&cf_sk->layer); | ||
| 1121 | 986 | ||
| 1122 | /* Detach the socket from its process context by making it orphan. */ | 987 | cf_sk->sk.sk_socket->state = SS_DISCONNECTING; |
| 1123 | sock_orphan(sk); | 988 | wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP); |
| 1124 | 989 | ||
| 1125 | /* | 990 | sock_orphan(sk); |
| 1126 | * Setting SHUTDOWN_MASK means that both send and receive are shutdown | 991 | cf_sk->layer.dn = NULL; |
| 1127 | * for the socket. | 992 | sk_stream_kill_queues(&cf_sk->sk); |
| 1128 | */ | 993 | release_sock(sk); |
| 1129 | sk->sk_shutdown = SHUTDOWN_MASK; | 994 | sock_put(sk); |
| 995 | return res; | ||
| 996 | } | ||
| 1130 | 997 | ||
| 1131 | /* | 998 | /* Copied from af_unix.c:unix_poll(), added CAIF tx_flow handling */ |
| 1132 | * Set the socket state to closed, the TCP_CLOSE macro is used when | 999 | static unsigned int caif_poll(struct file *file, |
| 1133 | * closing any socket. | 1000 | struct socket *sock, poll_table *wait) |
| 1134 | */ | 1001 | { |
| 1002 | struct sock *sk = sock->sk; | ||
| 1003 | unsigned int mask; | ||
| 1004 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||
| 1135 | 1005 | ||
| 1136 | /* Flush out this sockets receive queue. */ | 1006 | sock_poll_wait(file, sk_sleep(sk), wait); |
| 1137 | drain_queue(cf_sk); | 1007 | mask = 0; |
| 1138 | 1008 | ||
| 1139 | /* Finally release the socket. */ | 1009 | /* exceptional events? */ |
| 1140 | SET_STATE_PENDING_DESTROY(cf_sk); | 1010 | if (sk->sk_err) |
| 1011 | mask |= POLLERR; | ||
| 1012 | if (sk->sk_shutdown == SHUTDOWN_MASK) | ||
| 1013 | mask |= POLLHUP; | ||
| 1014 | if (sk->sk_shutdown & RCV_SHUTDOWN) | ||
| 1015 | mask |= POLLRDHUP; | ||
| 1141 | 1016 | ||
| 1142 | release_sock(&cf_sk->sk); | 1017 | /* readable? */ |
| 1018 | if (!skb_queue_empty(&sk->sk_receive_queue) || | ||
| 1019 | (sk->sk_shutdown & RCV_SHUTDOWN)) | ||
| 1020 | mask |= POLLIN | POLLRDNORM; | ||
| 1143 | 1021 | ||
| 1144 | sock_put(sk); | 1022 | /* Connection-based need to check for termination and startup */ |
| 1023 | if (sk->sk_state == CAIF_DISCONNECTED) | ||
| 1024 | mask |= POLLHUP; | ||
| 1145 | 1025 | ||
| 1146 | /* | 1026 | /* |
| 1147 | * The rest of the cleanup will be handled from the | 1027 | * we set writable also when the other side has shut down the |
| 1148 | * caif_sock_destructor | 1028 | * connection. This prevents stuck sockets. |
| 1149 | */ | 1029 | */ |
| 1150 | return res; | 1030 | if (sock_writeable(sk) && tx_flow_is_on(cf_sk)) |
| 1031 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; | ||
| 1032 | |||
| 1033 | return mask; | ||
| 1151 | } | 1034 | } |
| 1152 | 1035 | ||
| 1153 | static const struct proto_ops caif_ops = { | 1036 | static const struct proto_ops caif_seqpacket_ops = { |
| 1037 | .family = PF_CAIF, | ||
| 1038 | .owner = THIS_MODULE, | ||
| 1039 | .release = caif_release, | ||
| 1040 | .bind = sock_no_bind, | ||
| 1041 | .connect = caif_connect, | ||
| 1042 | .socketpair = sock_no_socketpair, | ||
| 1043 | .accept = sock_no_accept, | ||
| 1044 | .getname = sock_no_getname, | ||
| 1045 | .poll = caif_poll, | ||
| 1046 | .ioctl = sock_no_ioctl, | ||
| 1047 | .listen = sock_no_listen, | ||
| 1048 | .shutdown = sock_no_shutdown, | ||
| 1049 | .setsockopt = setsockopt, | ||
| 1050 | .getsockopt = sock_no_getsockopt, | ||
| 1051 | .sendmsg = caif_seqpkt_sendmsg, | ||
| 1052 | .recvmsg = caif_seqpkt_recvmsg, | ||
| 1053 | .mmap = sock_no_mmap, | ||
| 1054 | .sendpage = sock_no_sendpage, | ||
| 1055 | }; | ||
| 1056 | |||
| 1057 | static const struct proto_ops caif_stream_ops = { | ||
| 1154 | .family = PF_CAIF, | 1058 | .family = PF_CAIF, |
| 1155 | .owner = THIS_MODULE, | 1059 | .owner = THIS_MODULE, |
| 1156 | .release = caif_release, | 1060 | .release = caif_release, |
| @@ -1162,73 +1066,62 @@ static const struct proto_ops caif_ops = { | |||
| 1162 | .poll = caif_poll, | 1066 | .poll = caif_poll, |
| 1163 | .ioctl = sock_no_ioctl, | 1067 | .ioctl = sock_no_ioctl, |
| 1164 | .listen = sock_no_listen, | 1068 | .listen = sock_no_listen, |
| 1165 | .shutdown = caif_shutdown, | 1069 | .shutdown = sock_no_shutdown, |
| 1166 | .setsockopt = setsockopt, | 1070 | .setsockopt = setsockopt, |
| 1167 | .getsockopt = sock_no_getsockopt, | 1071 | .getsockopt = sock_no_getsockopt, |
| 1168 | .sendmsg = caif_sendmsg, | 1072 | .sendmsg = caif_stream_sendmsg, |
| 1169 | .recvmsg = caif_recvmsg, | 1073 | .recvmsg = caif_stream_recvmsg, |
| 1170 | .mmap = sock_no_mmap, | 1074 | .mmap = sock_no_mmap, |
| 1171 | .sendpage = caif_sock_no_sendpage, | 1075 | .sendpage = sock_no_sendpage, |
| 1172 | }; | 1076 | }; |
| 1173 | 1077 | ||
| 1174 | /* This function is called when a socket is finally destroyed. */ | 1078 | /* This function is called when a socket is finally destroyed. */ |
| 1175 | static void caif_sock_destructor(struct sock *sk) | 1079 | static void caif_sock_destructor(struct sock *sk) |
| 1176 | { | 1080 | { |
| 1177 | struct caifsock *cf_sk = NULL; | 1081 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
| 1178 | cf_sk = container_of(sk, struct caifsock, sk); | ||
| 1179 | /* Error checks. */ | ||
| 1180 | caif_assert(!atomic_read(&sk->sk_wmem_alloc)); | 1082 | caif_assert(!atomic_read(&sk->sk_wmem_alloc)); |
| 1181 | caif_assert(sk_unhashed(sk)); | 1083 | caif_assert(sk_unhashed(sk)); |
| 1182 | caif_assert(!sk->sk_socket); | 1084 | caif_assert(!sk->sk_socket); |
| 1183 | if (!sock_flag(sk, SOCK_DEAD)) { | 1085 | if (!sock_flag(sk, SOCK_DEAD)) { |
| 1184 | pr_debug("CAIF: %s(): 0x%p", __func__, sk); | 1086 | pr_info("Attempt to release alive CAIF socket: %p\n", sk); |
| 1185 | return; | 1087 | return; |
| 1186 | } | 1088 | } |
| 1187 | 1089 | sk_stream_kill_queues(&cf_sk->sk); | |
| 1188 | if (STATE_IS_OPEN(cf_sk)) { | 1090 | dbfs_atomic_dec(&cnt.caif_nr_socks); |
| 1189 | pr_debug("CAIF: %s(): socket is opened (cf_sk=%p)" | ||
| 1190 | " file_mode = 0x%x\n", __func__, | ||
| 1191 | cf_sk, cf_sk->file_mode); | ||
| 1192 | return; | ||
| 1193 | } | ||
| 1194 | drain_queue(cf_sk); | ||
| 1195 | kfree(cf_sk->pktq); | ||
| 1196 | |||
| 1197 | trace_printk("CAIF: %s(): caif_sock_destructor: Removing socket %s\n", | ||
| 1198 | __func__, cf_sk->name); | ||
| 1199 | atomic_dec(&caif_nr_socks); | ||
| 1200 | } | 1091 | } |
| 1201 | 1092 | ||
| 1202 | static int caif_create(struct net *net, struct socket *sock, int protocol, | 1093 | static int caif_create(struct net *net, struct socket *sock, int protocol, |
| 1203 | int kern) | 1094 | int kern) |
| 1204 | { | 1095 | { |
| 1205 | struct sock *sk = NULL; | 1096 | struct sock *sk = NULL; |
| 1206 | struct caifsock *cf_sk = NULL; | 1097 | struct caifsock *cf_sk = NULL; |
| 1207 | int result = 0; | ||
| 1208 | static struct proto prot = {.name = "PF_CAIF", | 1098 | static struct proto prot = {.name = "PF_CAIF", |
| 1209 | .owner = THIS_MODULE, | 1099 | .owner = THIS_MODULE, |
| 1210 | .obj_size = sizeof(struct caifsock), | 1100 | .obj_size = sizeof(struct caifsock), |
| 1211 | }; | 1101 | }; |
| 1212 | 1102 | ||
| 1103 | if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN)) | ||
| 1104 | return -EPERM; | ||
| 1213 | /* | 1105 | /* |
| 1214 | * The sock->type specifies the socket type to use. | 1106 | * The sock->type specifies the socket type to use. |
| 1215 | * in SEQPACKET mode packet boundaries are enforced. | 1107 | * The CAIF socket is a packet stream in the sense |
| 1108 | * that it is packet based. CAIF trusts the reliability | ||
| 1109 | * of the link, no resending is implemented. | ||
| 1216 | */ | 1110 | */ |
| 1217 | if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) | 1111 | if (sock->type == SOCK_SEQPACKET) |
| 1112 | sock->ops = &caif_seqpacket_ops; | ||
| 1113 | else if (sock->type == SOCK_STREAM) | ||
| 1114 | sock->ops = &caif_stream_ops; | ||
| 1115 | else | ||
| 1218 | return -ESOCKTNOSUPPORT; | 1116 | return -ESOCKTNOSUPPORT; |
| 1219 | 1117 | ||
| 1220 | if (net != &init_net) | ||
| 1221 | return -EAFNOSUPPORT; | ||
| 1222 | |||
| 1223 | if (protocol < 0 || protocol >= CAIFPROTO_MAX) | 1118 | if (protocol < 0 || protocol >= CAIFPROTO_MAX) |
| 1224 | return -EPROTONOSUPPORT; | 1119 | return -EPROTONOSUPPORT; |
| 1225 | /* | 1120 | /* |
| 1226 | * Set the socket state to unconnected. The socket state is really | 1121 | * Set the socket state to unconnected. The socket state |
| 1227 | * not used at all in the net/core or socket.c but the | 1122 | * is really not used at all in the net/core or socket.c but the |
| 1228 | * initialization makes sure that sock->state is not uninitialized. | 1123 | * initialization makes sure that sock->state is not uninitialized. |
| 1229 | */ | 1124 | */ |
| 1230 | sock->state = SS_UNCONNECTED; | ||
| 1231 | |||
| 1232 | sk = sk_alloc(net, PF_CAIF, GFP_KERNEL, &prot); | 1125 | sk = sk_alloc(net, PF_CAIF, GFP_KERNEL, &prot); |
| 1233 | if (!sk) | 1126 | if (!sk) |
| 1234 | return -ENOMEM; | 1127 | return -ENOMEM; |
| @@ -1238,11 +1131,9 @@ static int caif_create(struct net *net, struct socket *sock, int protocol, | |||
| 1238 | /* Store the protocol */ | 1131 | /* Store the protocol */ |
| 1239 | sk->sk_protocol = (unsigned char) protocol; | 1132 | sk->sk_protocol = (unsigned char) protocol; |
| 1240 | 1133 | ||
| 1241 | spin_lock_init(&cf_sk->read_queue_len_lock); | 1134 | /* Sendbuf dictates the amount of outbound packets not yet sent */ |
| 1242 | 1135 | sk->sk_sndbuf = CAIF_DEF_SNDBUF; | |
| 1243 | /* Fill in some information concerning the misc socket. */ | 1136 | sk->sk_rcvbuf = CAIF_DEF_RCVBUF; |
| 1244 | snprintf(cf_sk->name, sizeof(cf_sk->name), "cf_sk%d", | ||
| 1245 | atomic_read(&caif_nr_socks)); | ||
| 1246 | 1137 | ||
| 1247 | /* | 1138 | /* |
| 1248 | * Lock in order to try to stop someone from opening the socket | 1139 | * Lock in order to try to stop someone from opening the socket |
| @@ -1252,108 +1143,85 @@ static int caif_create(struct net *net, struct socket *sock, int protocol, | |||
| 1252 | 1143 | ||
| 1253 | /* Initialize the nozero default sock structure data. */ | 1144 | /* Initialize the nozero default sock structure data. */ |
| 1254 | sock_init_data(sock, sk); | 1145 | sock_init_data(sock, sk); |
| 1255 | sock->ops = &caif_ops; | ||
| 1256 | sk->sk_destruct = caif_sock_destructor; | 1146 | sk->sk_destruct = caif_sock_destructor; |
| 1257 | sk->sk_sndbuf = caif_sockbuf_size; | ||
| 1258 | sk->sk_rcvbuf = caif_sockbuf_size; | ||
| 1259 | 1147 | ||
| 1260 | cf_sk->pktq = cfpktq_create(); | 1148 | mutex_init(&cf_sk->readlock); /* single task reading lock */ |
| 1149 | cf_sk->layer.ctrlcmd = caif_ctrl_cb; | ||
| 1150 | cf_sk->sk.sk_socket->state = SS_UNCONNECTED; | ||
| 1151 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; | ||
| 1261 | 1152 | ||
| 1262 | if (!cf_sk->pktq) { | 1153 | set_tx_flow_off(cf_sk); |
| 1263 | pr_err("CAIF: %s(): queue create failed.\n", __func__); | 1154 | set_rx_flow_on(cf_sk); |
| 1264 | result = -ENOMEM; | ||
| 1265 | release_sock(&cf_sk->sk); | ||
| 1266 | goto err_failed; | ||
| 1267 | } | ||
| 1268 | cf_sk->layer.ctrlcmd = caif_sktflowctrl_cb; | ||
| 1269 | SET_STATE_CLOSED(cf_sk); | ||
| 1270 | SET_PENDING_OFF(cf_sk); | ||
| 1271 | SET_TX_FLOW_OFF(cf_sk); | ||
| 1272 | SET_RX_FLOW_ON(cf_sk); | ||
| 1273 | 1155 | ||
| 1274 | /* Set default options on configuration */ | 1156 | /* Set default options on configuration */ |
| 1275 | cf_sk->conn_req.priority = CAIF_PRIO_NORMAL; | 1157 | cf_sk->conn_req.priority = CAIF_PRIO_NORMAL; |
| 1276 | cf_sk->conn_req.link_selector = CAIF_LINK_HIGH_BANDW; | 1158 | cf_sk->conn_req.link_selector = CAIF_LINK_LOW_LATENCY; |
| 1277 | cf_sk->conn_req.protocol = protocol; | 1159 | cf_sk->conn_req.protocol = protocol; |
| 1278 | /* Increase the number of sockets created. */ | 1160 | /* Increase the number of sockets created. */ |
| 1279 | atomic_inc(&caif_nr_socks); | 1161 | dbfs_atomic_inc(&cnt.caif_nr_socks); |
| 1162 | #ifdef CONFIG_DEBUG_FS | ||
| 1280 | if (!IS_ERR(debugfsdir)) { | 1163 | if (!IS_ERR(debugfsdir)) { |
| 1164 | /* Fill in some information concerning the misc socket. */ | ||
| 1165 | snprintf(cf_sk->name, sizeof(cf_sk->name), "cfsk%d", | ||
| 1166 | atomic_read(&cnt.caif_nr_socks)); | ||
| 1167 | |||
| 1281 | cf_sk->debugfs_socket_dir = | 1168 | cf_sk->debugfs_socket_dir = |
| 1282 | debugfs_create_dir(cf_sk->name, debugfsdir); | 1169 | debugfs_create_dir(cf_sk->name, debugfsdir); |
| 1283 | debugfs_create_u32("conn_state", S_IRUSR | S_IWUSR, | 1170 | debugfs_create_u32("sk_state", S_IRUSR | S_IWUSR, |
| 1284 | cf_sk->debugfs_socket_dir, &cf_sk->conn_state); | 1171 | cf_sk->debugfs_socket_dir, |
| 1172 | (u32 *) &cf_sk->sk.sk_state); | ||
| 1285 | debugfs_create_u32("flow_state", S_IRUSR | S_IWUSR, | 1173 | debugfs_create_u32("flow_state", S_IRUSR | S_IWUSR, |
| 1286 | cf_sk->debugfs_socket_dir, &cf_sk->flow_state); | 1174 | cf_sk->debugfs_socket_dir, &cf_sk->flow_state); |
| 1287 | debugfs_create_u32("read_queue_len", S_IRUSR | S_IWUSR, | 1175 | debugfs_create_u32("sk_rmem_alloc", S_IRUSR | S_IWUSR, |
| 1176 | cf_sk->debugfs_socket_dir, | ||
| 1177 | (u32 *) &cf_sk->sk.sk_rmem_alloc); | ||
| 1178 | debugfs_create_u32("sk_wmem_alloc", S_IRUSR | S_IWUSR, | ||
| 1288 | cf_sk->debugfs_socket_dir, | 1179 | cf_sk->debugfs_socket_dir, |
| 1289 | (u32 *) &cf_sk->read_queue_len); | 1180 | (u32 *) &cf_sk->sk.sk_wmem_alloc); |
| 1290 | debugfs_create_u32("identity", S_IRUSR | S_IWUSR, | 1181 | debugfs_create_u32("identity", S_IRUSR | S_IWUSR, |
| 1291 | cf_sk->debugfs_socket_dir, | 1182 | cf_sk->debugfs_socket_dir, |
| 1292 | (u32 *) &cf_sk->layer.id); | 1183 | (u32 *) &cf_sk->layer.id); |
| 1293 | } | 1184 | } |
| 1185 | #endif | ||
| 1294 | release_sock(&cf_sk->sk); | 1186 | release_sock(&cf_sk->sk); |
| 1295 | return 0; | 1187 | return 0; |
| 1296 | err_failed: | ||
| 1297 | sk_free(sk); | ||
| 1298 | return result; | ||
| 1299 | } | 1188 | } |
| 1300 | 1189 | ||
| 1190 | |||
| 1301 | static struct net_proto_family caif_family_ops = { | 1191 | static struct net_proto_family caif_family_ops = { |
| 1302 | .family = PF_CAIF, | 1192 | .family = PF_CAIF, |
| 1303 | .create = caif_create, | 1193 | .create = caif_create, |
| 1304 | .owner = THIS_MODULE, | 1194 | .owner = THIS_MODULE, |
| 1305 | }; | 1195 | }; |
| 1306 | 1196 | ||
| 1307 | static int af_caif_init(void) | 1197 | int af_caif_init(void) |
| 1308 | { | 1198 | { |
| 1309 | int err; | 1199 | int err = sock_register(&caif_family_ops); |
| 1310 | err = sock_register(&caif_family_ops); | ||
| 1311 | |||
| 1312 | if (!err) | 1200 | if (!err) |
| 1313 | return err; | 1201 | return err; |
| 1314 | |||
| 1315 | return 0; | 1202 | return 0; |
| 1316 | } | 1203 | } |
| 1317 | 1204 | ||
| 1318 | static int __init caif_sktinit_module(void) | 1205 | static int __init caif_sktinit_module(void) |
| 1319 | { | 1206 | { |
| 1320 | int stat; | ||
| 1321 | #ifdef CONFIG_DEBUG_FS | 1207 | #ifdef CONFIG_DEBUG_FS |
| 1322 | debugfsdir = debugfs_create_dir("chnl_skt", NULL); | 1208 | debugfsdir = debugfs_create_dir("caif_sk", NULL); |
| 1323 | if (!IS_ERR(debugfsdir)) { | 1209 | if (!IS_ERR(debugfsdir)) { |
| 1324 | debugfs_create_u32("skb_inuse", S_IRUSR | S_IWUSR, | ||
| 1325 | debugfsdir, | ||
| 1326 | (u32 *) &cnt.skb_in_use); | ||
| 1327 | debugfs_create_u32("skb_alloc", S_IRUSR | S_IWUSR, | ||
| 1328 | debugfsdir, | ||
| 1329 | (u32 *) &cnt.skb_alloc); | ||
| 1330 | debugfs_create_u32("skb_free", S_IRUSR | S_IWUSR, | ||
| 1331 | debugfsdir, | ||
| 1332 | (u32 *) &cnt.skb_free); | ||
| 1333 | debugfs_create_u32("num_sockets", S_IRUSR | S_IWUSR, | 1210 | debugfs_create_u32("num_sockets", S_IRUSR | S_IWUSR, |
| 1334 | debugfsdir, | 1211 | debugfsdir, |
| 1335 | (u32 *) &caif_nr_socks); | 1212 | (u32 *) &cnt.caif_nr_socks); |
| 1336 | debugfs_create_u32("num_open", S_IRUSR | S_IWUSR, | 1213 | debugfs_create_u32("num_connect_req", S_IRUSR | S_IWUSR, |
| 1337 | debugfsdir, | 1214 | debugfsdir, |
| 1338 | (u32 *) &cnt.num_open); | 1215 | (u32 *) &cnt.num_connect_req); |
| 1339 | debugfs_create_u32("num_close", S_IRUSR | S_IWUSR, | 1216 | debugfs_create_u32("num_connect_resp", S_IRUSR | S_IWUSR, |
| 1340 | debugfsdir, | 1217 | debugfsdir, |
| 1341 | (u32 *) &cnt.num_close); | 1218 | (u32 *) &cnt.num_connect_resp); |
| 1342 | debugfs_create_u32("num_init", S_IRUSR | S_IWUSR, | 1219 | debugfs_create_u32("num_connect_fail_resp", S_IRUSR | S_IWUSR, |
| 1343 | debugfsdir, | 1220 | debugfsdir, |
| 1344 | (u32 *) &cnt.num_init); | 1221 | (u32 *) &cnt.num_connect_fail_resp); |
| 1345 | debugfs_create_u32("num_init_resp", S_IRUSR | S_IWUSR, | 1222 | debugfs_create_u32("num_disconnect", S_IRUSR | S_IWUSR, |
| 1346 | debugfsdir, | 1223 | debugfsdir, |
| 1347 | (u32 *) &cnt.num_init_resp); | 1224 | (u32 *) &cnt.num_disconnect); |
| 1348 | debugfs_create_u32("num_init_fail_resp", S_IRUSR | S_IWUSR, | ||
| 1349 | debugfsdir, | ||
| 1350 | (u32 *) &cnt.num_init_fail_resp); | ||
| 1351 | debugfs_create_u32("num_deinit", S_IRUSR | S_IWUSR, | ||
| 1352 | debugfsdir, | ||
| 1353 | (u32 *) &cnt.num_deinit); | ||
| 1354 | debugfs_create_u32("num_deinit_resp", S_IRUSR | S_IWUSR, | ||
| 1355 | debugfsdir, | ||
| 1356 | (u32 *) &cnt.num_deinit_resp); | ||
| 1357 | debugfs_create_u32("num_remote_shutdown_ind", | 1225 | debugfs_create_u32("num_remote_shutdown_ind", |
| 1358 | S_IRUSR | S_IWUSR, debugfsdir, | 1226 | S_IRUSR | S_IWUSR, debugfsdir, |
| 1359 | (u32 *) &cnt.num_remote_shutdown_ind); | 1227 | (u32 *) &cnt.num_remote_shutdown_ind); |
| @@ -1371,13 +1239,7 @@ static int __init caif_sktinit_module(void) | |||
| 1371 | (u32 *) &cnt.num_rx_flow_on); | 1239 | (u32 *) &cnt.num_rx_flow_on); |
| 1372 | } | 1240 | } |
| 1373 | #endif | 1241 | #endif |
| 1374 | stat = af_caif_init(); | 1242 | return af_caif_init(); |
| 1375 | if (stat) { | ||
| 1376 | pr_err("CAIF: %s(): Failed to initialize CAIF socket layer.", | ||
| 1377 | __func__); | ||
| 1378 | return stat; | ||
| 1379 | } | ||
| 1380 | return 0; | ||
| 1381 | } | 1243 | } |
| 1382 | 1244 | ||
| 1383 | static void __exit caif_sktexit_module(void) | 1245 | static void __exit caif_sktexit_module(void) |
| @@ -1386,6 +1248,5 @@ static void __exit caif_sktexit_module(void) | |||
| 1386 | if (debugfsdir != NULL) | 1248 | if (debugfsdir != NULL) |
| 1387 | debugfs_remove_recursive(debugfsdir); | 1249 | debugfs_remove_recursive(debugfsdir); |
| 1388 | } | 1250 | } |
| 1389 | |||
| 1390 | module_init(caif_sktinit_module); | 1251 | module_init(caif_sktinit_module); |
| 1391 | module_exit(caif_sktexit_module); | 1252 | module_exit(caif_sktexit_module); |
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index c873e3d4387c..471c62939fad 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c | |||
| @@ -51,12 +51,11 @@ struct cfcnfg { | |||
| 51 | struct cfcnfg_phyinfo phy_layers[MAX_PHY_LAYERS]; | 51 | struct cfcnfg_phyinfo phy_layers[MAX_PHY_LAYERS]; |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | static void cncfg_linkup_rsp(struct cflayer *layer, u8 linkid, | 54 | static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, |
| 55 | enum cfctrl_srv serv, u8 phyid, | 55 | enum cfctrl_srv serv, u8 phyid, |
| 56 | struct cflayer *adapt_layer); | 56 | struct cflayer *adapt_layer); |
| 57 | static void cncfg_linkdestroy_rsp(struct cflayer *layer, u8 linkid, | 57 | static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id); |
| 58 | struct cflayer *client_layer); | 58 | static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, |
| 59 | static void cncfg_reject_rsp(struct cflayer *layer, u8 linkid, | ||
| 60 | struct cflayer *adapt_layer); | 59 | struct cflayer *adapt_layer); |
| 61 | static void cfctrl_resp_func(void); | 60 | static void cfctrl_resp_func(void); |
| 62 | static void cfctrl_enum_resp(void); | 61 | static void cfctrl_enum_resp(void); |
| @@ -82,13 +81,13 @@ struct cfcnfg *cfcnfg_create(void) | |||
| 82 | resp = cfctrl_get_respfuncs(this->ctrl); | 81 | resp = cfctrl_get_respfuncs(this->ctrl); |
| 83 | resp->enum_rsp = cfctrl_enum_resp; | 82 | resp->enum_rsp = cfctrl_enum_resp; |
| 84 | resp->linkerror_ind = cfctrl_resp_func; | 83 | resp->linkerror_ind = cfctrl_resp_func; |
| 85 | resp->linkdestroy_rsp = cncfg_linkdestroy_rsp; | 84 | resp->linkdestroy_rsp = cfcnfg_linkdestroy_rsp; |
| 86 | resp->sleep_rsp = cfctrl_resp_func; | 85 | resp->sleep_rsp = cfctrl_resp_func; |
| 87 | resp->wake_rsp = cfctrl_resp_func; | 86 | resp->wake_rsp = cfctrl_resp_func; |
| 88 | resp->restart_rsp = cfctrl_resp_func; | 87 | resp->restart_rsp = cfctrl_resp_func; |
| 89 | resp->radioset_rsp = cfctrl_resp_func; | 88 | resp->radioset_rsp = cfctrl_resp_func; |
| 90 | resp->linksetup_rsp = cncfg_linkup_rsp; | 89 | resp->linksetup_rsp = cfcnfg_linkup_rsp; |
| 91 | resp->reject_rsp = cncfg_reject_rsp; | 90 | resp->reject_rsp = cfcnfg_reject_rsp; |
| 92 | 91 | ||
| 93 | this->last_phyid = 1; | 92 | this->last_phyid = 1; |
| 94 | 93 | ||
| @@ -175,142 +174,82 @@ int cfcnfg_get_named(struct cfcnfg *cnfg, char *name) | |||
| 175 | return 0; | 174 | return 0; |
| 176 | } | 175 | } |
| 177 | 176 | ||
| 178 | /* | 177 | int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer) |
| 179 | * NOTE: What happens on destroy failure: | ||
| 180 | * 1a) No response - Too early | ||
| 181 | * This will not happen because enumerate has already | ||
| 182 | * completed. | ||
| 183 | * 1b) No response - FATAL | ||
| 184 | * Not handled, but this should be a CAIF PROTOCOL ERROR | ||
| 185 | * Modem error, response is really expected - this | ||
| 186 | * case is not really handled. | ||
| 187 | * 2) O/E-bit indicate error | ||
| 188 | * Ignored - this link is destroyed anyway. | ||
| 189 | * 3) Not able to match on request | ||
| 190 | * Not handled, but this should be a CAIF PROTOCOL ERROR | ||
| 191 | * 4) Link-Error - (no response) | ||
| 192 | * Not handled, but this should be a CAIF PROTOCOL ERROR | ||
| 193 | */ | ||
| 194 | |||
| 195 | int cfcnfg_del_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer) | ||
| 196 | { | 178 | { |
| 197 | u8 channel_id = 0; | 179 | u8 channel_id = 0; |
| 198 | int ret = 0; | 180 | int ret = 0; |
| 181 | struct cflayer *servl = NULL; | ||
| 199 | struct cfcnfg_phyinfo *phyinfo = NULL; | 182 | struct cfcnfg_phyinfo *phyinfo = NULL; |
| 200 | u8 phyid = 0; | 183 | u8 phyid = 0; |
| 201 | |||
| 202 | caif_assert(adap_layer != NULL); | 184 | caif_assert(adap_layer != NULL); |
| 203 | channel_id = adap_layer->id; | 185 | channel_id = adap_layer->id; |
| 204 | if (channel_id == 0) { | 186 | if (adap_layer->dn == NULL || channel_id == 0) { |
| 205 | pr_err("CAIF: %s():adap_layer->id is 0\n", __func__); | 187 | pr_err("CAIF: %s():adap_layer->id is 0\n", __func__); |
| 206 | ret = -ENOTCONN; | 188 | ret = -ENOTCONN; |
| 207 | goto end; | 189 | goto end; |
| 208 | } | 190 | } |
| 209 | 191 | servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id); | |
| 210 | if (adap_layer->dn == NULL) { | 192 | if (servl == NULL) |
| 211 | pr_err("CAIF: %s():adap_layer->dn is NULL\n", __func__); | ||
| 212 | ret = -ENODEV; | ||
| 213 | goto end; | ||
| 214 | } | ||
| 215 | |||
| 216 | if (adap_layer->dn != NULL) | ||
| 217 | phyid = cfsrvl_getphyid(adap_layer->dn); | ||
| 218 | |||
| 219 | phyinfo = cfcnfg_get_phyinfo(cnfg, phyid); | ||
| 220 | if (phyinfo == NULL) { | ||
| 221 | pr_warning("CAIF: %s(): No interface to send disconnect to\n", | ||
| 222 | __func__); | ||
| 223 | ret = -ENODEV; | ||
| 224 | goto end; | 193 | goto end; |
| 225 | } | 194 | layer_set_up(servl, NULL); |
| 226 | 195 | ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer); | |
| 227 | if (phyinfo->id != phyid | 196 | if (servl == NULL) { |
| 228 | || phyinfo->phy_layer->id != phyid | 197 | pr_err("CAIF: %s(): PROTOCOL ERROR " |
| 229 | || phyinfo->frm_layer->id != phyid) { | 198 | "- Error removing service_layer Channel_Id(%d)", |
| 230 | 199 | __func__, channel_id); | |
| 231 | pr_err("CAIF: %s(): Inconsistency in phy registration\n", | ||
| 232 | __func__); | ||
| 233 | ret = -EINVAL; | 200 | ret = -EINVAL; |
| 234 | goto end; | 201 | goto end; |
| 235 | } | 202 | } |
| 203 | caif_assert(channel_id == servl->id); | ||
| 204 | if (adap_layer->dn != NULL) { | ||
| 205 | phyid = cfsrvl_getphyid(adap_layer->dn); | ||
| 236 | 206 | ||
| 237 | ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer); | 207 | phyinfo = cfcnfg_get_phyinfo(cnfg, phyid); |
| 238 | 208 | if (phyinfo == NULL) { | |
| 239 | end: | 209 | pr_warning("CAIF: %s(): " |
| 210 | "No interface to send disconnect to\n", | ||
| 211 | __func__); | ||
| 212 | ret = -ENODEV; | ||
| 213 | goto end; | ||
| 214 | } | ||
| 215 | if (phyinfo->id != phyid || | ||
| 216 | phyinfo->phy_layer->id != phyid || | ||
| 217 | phyinfo->frm_layer->id != phyid) { | ||
| 218 | pr_err("CAIF: %s(): " | ||
| 219 | "Inconsistency in phy registration\n", | ||
| 220 | __func__); | ||
| 221 | ret = -EINVAL; | ||
| 222 | goto end; | ||
| 223 | } | ||
| 224 | } | ||
| 240 | if (phyinfo != NULL && --phyinfo->phy_ref_count == 0 && | 225 | if (phyinfo != NULL && --phyinfo->phy_ref_count == 0 && |
| 241 | phyinfo->phy_layer != NULL && | 226 | phyinfo->phy_layer != NULL && |
| 242 | phyinfo->phy_layer->modemcmd != NULL) { | 227 | phyinfo->phy_layer->modemcmd != NULL) { |
| 243 | phyinfo->phy_layer->modemcmd(phyinfo->phy_layer, | 228 | phyinfo->phy_layer->modemcmd(phyinfo->phy_layer, |
| 244 | _CAIF_MODEMCMD_PHYIF_USELESS); | 229 | _CAIF_MODEMCMD_PHYIF_USELESS); |
| 245 | } | 230 | } |
| 231 | end: | ||
| 232 | cfsrvl_put(servl); | ||
| 233 | cfctrl_cancel_req(cnfg->ctrl, adap_layer); | ||
| 234 | if (adap_layer->ctrlcmd != NULL) | ||
| 235 | adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0); | ||
| 246 | return ret; | 236 | return ret; |
| 247 | 237 | ||
| 248 | } | 238 | } |
| 249 | EXPORT_SYMBOL(cfcnfg_del_adapt_layer); | 239 | EXPORT_SYMBOL(cfcnfg_disconn_adapt_layer); |
| 250 | 240 | ||
| 251 | static void cncfg_linkdestroy_rsp(struct cflayer *layer, u8 linkid, | 241 | void cfcnfg_release_adap_layer(struct cflayer *adap_layer) |
| 252 | struct cflayer *client_layer) | ||
| 253 | { | 242 | { |
| 254 | struct cfcnfg *cnfg = container_obj(layer); | 243 | if (adap_layer->dn) |
| 255 | struct cflayer *servl; | 244 | cfsrvl_put(adap_layer->dn); |
| 256 | |||
| 257 | /* | ||
| 258 | * 1) Remove service from the MUX layer. The MUX must | ||
| 259 | * guarante that no more payload sent "upwards" (receive) | ||
| 260 | */ | ||
| 261 | servl = cfmuxl_remove_uplayer(cnfg->mux, linkid); | ||
| 262 | |||
| 263 | if (servl == NULL) { | ||
| 264 | pr_err("CAIF: %s(): PROTOCOL ERROR " | ||
| 265 | "- Error removing service_layer Linkid(%d)", | ||
| 266 | __func__, linkid); | ||
| 267 | return; | ||
| 268 | } | ||
| 269 | caif_assert(linkid == servl->id); | ||
| 270 | |||
| 271 | if (servl != client_layer && servl->up != client_layer) { | ||
| 272 | pr_err("CAIF: %s(): Error removing service_layer " | ||
| 273 | "Linkid(%d) %p %p", | ||
| 274 | __func__, linkid, (void *) servl, | ||
| 275 | (void *) client_layer); | ||
| 276 | return; | ||
| 277 | } | ||
| 278 | |||
| 279 | /* | ||
| 280 | * 2) DEINIT_RSP must guarantee that no more packets are transmitted | ||
| 281 | * from client (adap_layer) when it returns. | ||
| 282 | */ | ||
| 283 | |||
| 284 | if (servl->ctrlcmd == NULL) { | ||
| 285 | pr_err("CAIF: %s(): Error servl->ctrlcmd == NULL", __func__); | ||
| 286 | return; | ||
| 287 | } | ||
| 288 | |||
| 289 | servl->ctrlcmd(servl, CAIF_CTRLCMD_DEINIT_RSP, 0); | ||
| 290 | |||
| 291 | /* 3) It is now safe to destroy the service layer. */ | ||
| 292 | cfservl_destroy(servl); | ||
| 293 | } | 245 | } |
| 246 | EXPORT_SYMBOL(cfcnfg_release_adap_layer); | ||
| 294 | 247 | ||
| 295 | /* | 248 | static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) |
| 296 | * NOTE: What happens on linksetup failure: | 249 | { |
| 297 | * 1a) No response - Too early | 250 | } |
| 298 | * This will not happen because enumerate is secured | ||
| 299 | * before using interface. | ||
| 300 | * 1b) No response - FATAL | ||
| 301 | * Not handled, but this should be a CAIF PROTOCOL ERROR | ||
| 302 | * Modem error, response is really expected - this case is | ||
| 303 | * not really handled. | ||
| 304 | * 2) O/E-bit indicate error | ||
| 305 | * Handled in cnfg_reject_rsp | ||
| 306 | * 3) Not able to match on request | ||
| 307 | * Not handled, but this should be a CAIF PROTOCOL ERROR | ||
| 308 | * 4) Link-Error - (no response) | ||
| 309 | * Not handled, but this should be a CAIF PROTOCOL ERROR | ||
| 310 | */ | ||
| 311 | 251 | ||
| 312 | int | 252 | int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, |
| 313 | cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, | ||
| 314 | struct cfctrl_link_param *param, | 253 | struct cfctrl_link_param *param, |
| 315 | struct cflayer *adap_layer) | 254 | struct cflayer *adap_layer) |
| 316 | { | 255 | { |
| @@ -340,12 +279,11 @@ cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, | |||
| 340 | param->phyid); | 279 | param->phyid); |
| 341 | /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ | 280 | /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ |
| 342 | cfctrl_enum_req(cnfg->ctrl, param->phyid); | 281 | cfctrl_enum_req(cnfg->ctrl, param->phyid); |
| 343 | cfctrl_linkup_request(cnfg->ctrl, param, adap_layer); | 282 | return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer); |
| 344 | return 0; | ||
| 345 | } | 283 | } |
| 346 | EXPORT_SYMBOL(cfcnfg_add_adaptation_layer); | 284 | EXPORT_SYMBOL(cfcnfg_add_adaptation_layer); |
| 347 | 285 | ||
| 348 | static void cncfg_reject_rsp(struct cflayer *layer, u8 linkid, | 286 | static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, |
| 349 | struct cflayer *adapt_layer) | 287 | struct cflayer *adapt_layer) |
| 350 | { | 288 | { |
| 351 | if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL) | 289 | if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL) |
| @@ -354,15 +292,17 @@ static void cncfg_reject_rsp(struct cflayer *layer, u8 linkid, | |||
| 354 | } | 292 | } |
| 355 | 293 | ||
| 356 | static void | 294 | static void |
| 357 | cncfg_linkup_rsp(struct cflayer *layer, u8 linkid, enum cfctrl_srv serv, | 295 | cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, |
| 358 | u8 phyid, struct cflayer *adapt_layer) | 296 | u8 phyid, struct cflayer *adapt_layer) |
| 359 | { | 297 | { |
| 360 | struct cfcnfg *cnfg = container_obj(layer); | 298 | struct cfcnfg *cnfg = container_obj(layer); |
| 361 | struct cflayer *servicel = NULL; | 299 | struct cflayer *servicel = NULL; |
| 362 | struct cfcnfg_phyinfo *phyinfo; | 300 | struct cfcnfg_phyinfo *phyinfo; |
| 363 | if (adapt_layer == NULL) { | 301 | if (adapt_layer == NULL) { |
| 364 | pr_err("CAIF: %s(): PROTOCOL ERROR " | 302 | pr_debug("CAIF: %s(): link setup response " |
| 365 | "- LinkUp Request/Response did not match\n", __func__); | 303 | "but no client exist, send linkdown back\n", |
| 304 | __func__); | ||
| 305 | cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL); | ||
| 366 | return; | 306 | return; |
| 367 | } | 307 | } |
| 368 | 308 | ||
| @@ -383,26 +323,26 @@ cncfg_linkup_rsp(struct cflayer *layer, u8 linkid, enum cfctrl_srv serv, | |||
| 383 | _CAIF_MODEMCMD_PHYIF_USEFULL); | 323 | _CAIF_MODEMCMD_PHYIF_USEFULL); |
| 384 | 324 | ||
| 385 | } | 325 | } |
| 386 | adapt_layer->id = linkid; | 326 | adapt_layer->id = channel_id; |
| 387 | 327 | ||
| 388 | switch (serv) { | 328 | switch (serv) { |
| 389 | case CFCTRL_SRV_VEI: | 329 | case CFCTRL_SRV_VEI: |
| 390 | servicel = cfvei_create(linkid, &phyinfo->dev_info); | 330 | servicel = cfvei_create(channel_id, &phyinfo->dev_info); |
| 391 | break; | 331 | break; |
| 392 | case CFCTRL_SRV_DATAGRAM: | 332 | case CFCTRL_SRV_DATAGRAM: |
| 393 | servicel = cfdgml_create(linkid, &phyinfo->dev_info); | 333 | servicel = cfdgml_create(channel_id, &phyinfo->dev_info); |
| 394 | break; | 334 | break; |
| 395 | case CFCTRL_SRV_RFM: | 335 | case CFCTRL_SRV_RFM: |
| 396 | servicel = cfrfml_create(linkid, &phyinfo->dev_info); | 336 | servicel = cfrfml_create(channel_id, &phyinfo->dev_info); |
| 397 | break; | 337 | break; |
| 398 | case CFCTRL_SRV_UTIL: | 338 | case CFCTRL_SRV_UTIL: |
| 399 | servicel = cfutill_create(linkid, &phyinfo->dev_info); | 339 | servicel = cfutill_create(channel_id, &phyinfo->dev_info); |
| 400 | break; | 340 | break; |
| 401 | case CFCTRL_SRV_VIDEO: | 341 | case CFCTRL_SRV_VIDEO: |
| 402 | servicel = cfvidl_create(linkid, &phyinfo->dev_info); | 342 | servicel = cfvidl_create(channel_id, &phyinfo->dev_info); |
| 403 | break; | 343 | break; |
| 404 | case CFCTRL_SRV_DBG: | 344 | case CFCTRL_SRV_DBG: |
| 405 | servicel = cfdbgl_create(linkid, &phyinfo->dev_info); | 345 | servicel = cfdbgl_create(channel_id, &phyinfo->dev_info); |
| 406 | break; | 346 | break; |
| 407 | default: | 347 | default: |
| 408 | pr_err("CAIF: %s(): Protocol error. " | 348 | pr_err("CAIF: %s(): Protocol error. " |
| @@ -415,9 +355,10 @@ cncfg_linkup_rsp(struct cflayer *layer, u8 linkid, enum cfctrl_srv serv, | |||
| 415 | return; | 355 | return; |
| 416 | } | 356 | } |
| 417 | layer_set_dn(servicel, cnfg->mux); | 357 | layer_set_dn(servicel, cnfg->mux); |
| 418 | cfmuxl_set_uplayer(cnfg->mux, servicel, linkid); | 358 | cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id); |
| 419 | layer_set_up(servicel, adapt_layer); | 359 | layer_set_up(servicel, adapt_layer); |
| 420 | layer_set_dn(adapt_layer, servicel); | 360 | layer_set_dn(adapt_layer, servicel); |
| 361 | cfsrvl_get(servicel); | ||
| 421 | servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0); | 362 | servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0); |
| 422 | } | 363 | } |
| 423 | 364 | ||
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index 11f80140f3cb..a521d32cfe56 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c | |||
| @@ -32,6 +32,7 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
| 32 | 32 | ||
| 33 | struct cflayer *cfctrl_create(void) | 33 | struct cflayer *cfctrl_create(void) |
| 34 | { | 34 | { |
| 35 | struct dev_info dev_info; | ||
| 35 | struct cfctrl *this = | 36 | struct cfctrl *this = |
| 36 | kmalloc(sizeof(struct cfctrl), GFP_ATOMIC); | 37 | kmalloc(sizeof(struct cfctrl), GFP_ATOMIC); |
| 37 | if (!this) { | 38 | if (!this) { |
| @@ -39,12 +40,13 @@ struct cflayer *cfctrl_create(void) | |||
| 39 | return NULL; | 40 | return NULL; |
| 40 | } | 41 | } |
| 41 | caif_assert(offsetof(struct cfctrl, serv.layer) == 0); | 42 | caif_assert(offsetof(struct cfctrl, serv.layer) == 0); |
| 43 | memset(&dev_info, 0, sizeof(dev_info)); | ||
| 44 | dev_info.id = 0xff; | ||
| 42 | memset(this, 0, sizeof(*this)); | 45 | memset(this, 0, sizeof(*this)); |
| 46 | cfsrvl_init(&this->serv, 0, &dev_info); | ||
| 43 | spin_lock_init(&this->info_list_lock); | 47 | spin_lock_init(&this->info_list_lock); |
| 44 | atomic_set(&this->req_seq_no, 1); | 48 | atomic_set(&this->req_seq_no, 1); |
| 45 | atomic_set(&this->rsp_seq_no, 1); | 49 | atomic_set(&this->rsp_seq_no, 1); |
| 46 | this->serv.dev_info.id = 0xff; | ||
| 47 | this->serv.layer.id = 0; | ||
| 48 | this->serv.layer.receive = cfctrl_recv; | 50 | this->serv.layer.receive = cfctrl_recv; |
| 49 | sprintf(this->serv.layer.name, "ctrl"); | 51 | sprintf(this->serv.layer.name, "ctrl"); |
| 50 | this->serv.layer.ctrlcmd = cfctrl_ctrlcmd; | 52 | this->serv.layer.ctrlcmd = cfctrl_ctrlcmd; |
| @@ -127,20 +129,6 @@ void cfctrl_insert_req(struct cfctrl *ctrl, | |||
| 127 | spin_unlock(&ctrl->info_list_lock); | 129 | spin_unlock(&ctrl->info_list_lock); |
| 128 | } | 130 | } |
| 129 | 131 | ||
| 130 | static void cfctrl_insert_req2(struct cfctrl *ctrl, enum cfctrl_cmd cmd, | ||
| 131 | u8 linkid, struct cflayer *user_layer) | ||
| 132 | { | ||
| 133 | struct cfctrl_request_info *req = kmalloc(sizeof(*req), GFP_KERNEL); | ||
| 134 | if (!req) { | ||
| 135 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | ||
| 136 | return; | ||
| 137 | } | ||
| 138 | req->client_layer = user_layer; | ||
| 139 | req->cmd = cmd; | ||
| 140 | req->channel_id = linkid; | ||
| 141 | cfctrl_insert_req(ctrl, req); | ||
| 142 | } | ||
| 143 | |||
| 144 | /* Compare and remove request */ | 132 | /* Compare and remove request */ |
| 145 | struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, | 133 | struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, |
| 146 | struct cfctrl_request_info *req) | 134 | struct cfctrl_request_info *req) |
| @@ -234,7 +222,7 @@ void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid) | |||
| 234 | } | 222 | } |
| 235 | } | 223 | } |
| 236 | 224 | ||
| 237 | void cfctrl_linkup_request(struct cflayer *layer, | 225 | int cfctrl_linkup_request(struct cflayer *layer, |
| 238 | struct cfctrl_link_param *param, | 226 | struct cfctrl_link_param *param, |
| 239 | struct cflayer *user_layer) | 227 | struct cflayer *user_layer) |
| 240 | { | 228 | { |
| @@ -248,7 +236,7 @@ void cfctrl_linkup_request(struct cflayer *layer, | |||
| 248 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | 236 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); |
| 249 | if (!pkt) { | 237 | if (!pkt) { |
| 250 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | 238 | pr_warning("CAIF: %s(): Out of memory\n", __func__); |
| 251 | return; | 239 | return -ENOMEM; |
| 252 | } | 240 | } |
| 253 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP); | 241 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP); |
| 254 | cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype); | 242 | cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype); |
| @@ -294,11 +282,12 @@ void cfctrl_linkup_request(struct cflayer *layer, | |||
| 294 | default: | 282 | default: |
| 295 | pr_warning("CAIF: %s():Request setup of bad link type = %d\n", | 283 | pr_warning("CAIF: %s():Request setup of bad link type = %d\n", |
| 296 | __func__, param->linktype); | 284 | __func__, param->linktype); |
| 285 | return -EINVAL; | ||
| 297 | } | 286 | } |
| 298 | req = kmalloc(sizeof(*req), GFP_KERNEL); | 287 | req = kmalloc(sizeof(*req), GFP_KERNEL); |
| 299 | if (!req) { | 288 | if (!req) { |
| 300 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | 289 | pr_warning("CAIF: %s(): Out of memory\n", __func__); |
| 301 | return; | 290 | return -ENOMEM; |
| 302 | } | 291 | } |
| 303 | memset(req, 0, sizeof(*req)); | 292 | memset(req, 0, sizeof(*req)); |
| 304 | req->client_layer = user_layer; | 293 | req->client_layer = user_layer; |
| @@ -306,6 +295,11 @@ void cfctrl_linkup_request(struct cflayer *layer, | |||
| 306 | req->param = *param; | 295 | req->param = *param; |
| 307 | cfctrl_insert_req(cfctrl, req); | 296 | cfctrl_insert_req(cfctrl, req); |
| 308 | init_info(cfpkt_info(pkt), cfctrl); | 297 | init_info(cfpkt_info(pkt), cfctrl); |
| 298 | /* | ||
| 299 | * NOTE:Always send linkup and linkdown request on the same | ||
| 300 | * device as the payload. Otherwise old queued up payload | ||
| 301 | * might arrive with the newly allocated channel ID. | ||
| 302 | */ | ||
| 309 | cfpkt_info(pkt)->dev_info->id = param->phyid; | 303 | cfpkt_info(pkt)->dev_info->id = param->phyid; |
| 310 | ret = | 304 | ret = |
| 311 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | 305 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); |
| @@ -313,7 +307,9 @@ void cfctrl_linkup_request(struct cflayer *layer, | |||
| 313 | pr_err("CAIF: %s(): Could not transmit linksetup request\n", | 307 | pr_err("CAIF: %s(): Could not transmit linksetup request\n", |
| 314 | __func__); | 308 | __func__); |
| 315 | cfpkt_destroy(pkt); | 309 | cfpkt_destroy(pkt); |
| 310 | return -ENODEV; | ||
| 316 | } | 311 | } |
| 312 | return 0; | ||
| 317 | } | 313 | } |
| 318 | 314 | ||
| 319 | int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, | 315 | int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, |
| @@ -326,7 +322,6 @@ int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, | |||
| 326 | pr_warning("CAIF: %s(): Out of memory\n", __func__); | 322 | pr_warning("CAIF: %s(): Out of memory\n", __func__); |
| 327 | return -ENOMEM; | 323 | return -ENOMEM; |
| 328 | } | 324 | } |
| 329 | cfctrl_insert_req2(cfctrl, CFCTRL_CMD_LINK_DESTROY, channelid, client); | ||
| 330 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY); | 325 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY); |
| 331 | cfpkt_addbdy(pkt, channelid); | 326 | cfpkt_addbdy(pkt, channelid); |
| 332 | init_info(cfpkt_info(pkt), cfctrl); | 327 | init_info(cfpkt_info(pkt), cfctrl); |
| @@ -392,6 +387,38 @@ void cfctrl_getstartreason_req(struct cflayer *layer) | |||
| 392 | } | 387 | } |
| 393 | 388 | ||
| 394 | 389 | ||
| 390 | void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) | ||
| 391 | { | ||
| 392 | struct cfctrl_request_info *p, *req; | ||
| 393 | struct cfctrl *ctrl = container_obj(layr); | ||
| 394 | spin_lock(&ctrl->info_list_lock); | ||
| 395 | |||
| 396 | if (ctrl->first_req == NULL) { | ||
| 397 | spin_unlock(&ctrl->info_list_lock); | ||
| 398 | return; | ||
| 399 | } | ||
| 400 | |||
| 401 | if (ctrl->first_req->client_layer == adap_layer) { | ||
| 402 | |||
| 403 | req = ctrl->first_req; | ||
| 404 | ctrl->first_req = ctrl->first_req->next; | ||
| 405 | kfree(req); | ||
| 406 | } | ||
| 407 | |||
| 408 | p = ctrl->first_req; | ||
| 409 | while (p != NULL && p->next != NULL) { | ||
| 410 | if (p->next->client_layer == adap_layer) { | ||
| 411 | |||
| 412 | req = p->next; | ||
| 413 | p->next = p->next->next; | ||
| 414 | kfree(p->next); | ||
| 415 | } | ||
| 416 | p = p->next; | ||
| 417 | } | ||
| 418 | |||
| 419 | spin_unlock(&ctrl->info_list_lock); | ||
| 420 | } | ||
| 421 | |||
| 395 | static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | 422 | static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) |
| 396 | { | 423 | { |
| 397 | u8 cmdrsp; | 424 | u8 cmdrsp; |
| @@ -409,11 +436,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
| 409 | cmd = cmdrsp & CFCTRL_CMD_MASK; | 436 | cmd = cmdrsp & CFCTRL_CMD_MASK; |
| 410 | if (cmd != CFCTRL_CMD_LINK_ERR | 437 | if (cmd != CFCTRL_CMD_LINK_ERR |
| 411 | && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) { | 438 | && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) { |
| 412 | if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE) { | 439 | if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE) |
| 413 | pr_info("CAIF: %s() CAIF Protocol error:" | 440 | cmdrsp |= CFCTRL_ERR_BIT; |
| 414 | "Response bit not set\n", __func__); | ||
| 415 | goto error; | ||
| 416 | } | ||
| 417 | } | 441 | } |
| 418 | 442 | ||
| 419 | switch (cmd) { | 443 | switch (cmd) { |
| @@ -451,12 +475,16 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
| 451 | switch (serv) { | 475 | switch (serv) { |
| 452 | case CFCTRL_SRV_VEI: | 476 | case CFCTRL_SRV_VEI: |
| 453 | case CFCTRL_SRV_DBG: | 477 | case CFCTRL_SRV_DBG: |
| 478 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
| 479 | break; | ||
| 454 | /* Link ID */ | 480 | /* Link ID */ |
| 455 | cfpkt_extr_head(pkt, &linkid, 1); | 481 | cfpkt_extr_head(pkt, &linkid, 1); |
| 456 | break; | 482 | break; |
| 457 | case CFCTRL_SRV_VIDEO: | 483 | case CFCTRL_SRV_VIDEO: |
| 458 | cfpkt_extr_head(pkt, &tmp, 1); | 484 | cfpkt_extr_head(pkt, &tmp, 1); |
| 459 | linkparam.u.video.connid = tmp; | 485 | linkparam.u.video.connid = tmp; |
| 486 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
| 487 | break; | ||
| 460 | /* Link ID */ | 488 | /* Link ID */ |
| 461 | cfpkt_extr_head(pkt, &linkid, 1); | 489 | cfpkt_extr_head(pkt, &linkid, 1); |
| 462 | break; | 490 | break; |
| @@ -465,6 +493,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
| 465 | cfpkt_extr_head(pkt, &tmp32, 4); | 493 | cfpkt_extr_head(pkt, &tmp32, 4); |
| 466 | linkparam.u.datagram.connid = | 494 | linkparam.u.datagram.connid = |
| 467 | le32_to_cpu(tmp32); | 495 | le32_to_cpu(tmp32); |
| 496 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
| 497 | break; | ||
| 468 | /* Link ID */ | 498 | /* Link ID */ |
| 469 | cfpkt_extr_head(pkt, &linkid, 1); | 499 | cfpkt_extr_head(pkt, &linkid, 1); |
| 470 | break; | 500 | break; |
| @@ -483,6 +513,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
| 483 | *cp++ = tmp; | 513 | *cp++ = tmp; |
| 484 | *cp = '\0'; | 514 | *cp = '\0'; |
| 485 | 515 | ||
| 516 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
| 517 | break; | ||
| 486 | /* Link ID */ | 518 | /* Link ID */ |
| 487 | cfpkt_extr_head(pkt, &linkid, 1); | 519 | cfpkt_extr_head(pkt, &linkid, 1); |
| 488 | 520 | ||
| @@ -519,6 +551,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
| 519 | cfpkt_extr_head(pkt, &tmp, 1); | 551 | cfpkt_extr_head(pkt, &tmp, 1); |
| 520 | *cp++ = tmp; | 552 | *cp++ = tmp; |
| 521 | } | 553 | } |
| 554 | if (CFCTRL_ERR_BIT & cmdrsp) | ||
| 555 | break; | ||
| 522 | /* Link ID */ | 556 | /* Link ID */ |
| 523 | cfpkt_extr_head(pkt, &linkid, 1); | 557 | cfpkt_extr_head(pkt, &linkid, 1); |
| 524 | /* Length */ | 558 | /* Length */ |
| @@ -560,13 +594,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
| 560 | break; | 594 | break; |
| 561 | case CFCTRL_CMD_LINK_DESTROY: | 595 | case CFCTRL_CMD_LINK_DESTROY: |
| 562 | cfpkt_extr_head(pkt, &linkid, 1); | 596 | cfpkt_extr_head(pkt, &linkid, 1); |
| 563 | rsp.cmd = cmd; | 597 | cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid); |
| 564 | rsp.channel_id = linkid; | ||
| 565 | req = cfctrl_remove_req(cfctrl, &rsp); | ||
| 566 | cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid, | ||
| 567 | req ? req->client_layer : NULL); | ||
| 568 | if (req != NULL) | ||
| 569 | kfree(req); | ||
| 570 | break; | 598 | break; |
| 571 | case CFCTRL_CMD_LINK_ERR: | 599 | case CFCTRL_CMD_LINK_ERR: |
| 572 | pr_err("CAIF: %s(): Frame Error Indication received\n", | 600 | pr_err("CAIF: %s(): Frame Error Indication received\n", |
| @@ -608,7 +636,7 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
| 608 | case CAIF_CTRLCMD_FLOW_OFF_IND: | 636 | case CAIF_CTRLCMD_FLOW_OFF_IND: |
| 609 | spin_lock(&this->info_list_lock); | 637 | spin_lock(&this->info_list_lock); |
| 610 | if (this->first_req != NULL) { | 638 | if (this->first_req != NULL) { |
| 611 | pr_warning("CAIF: %s(): Received flow off in " | 639 | pr_debug("CAIF: %s(): Received flow off in " |
| 612 | "control layer", __func__); | 640 | "control layer", __func__); |
| 613 | } | 641 | } |
| 614 | spin_unlock(&this->info_list_lock); | 642 | spin_unlock(&this->info_list_lock); |
| @@ -633,6 +661,7 @@ static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt) | |||
| 633 | if (!ctrl->loop_linkused[linkid]) | 661 | if (!ctrl->loop_linkused[linkid]) |
| 634 | goto found; | 662 | goto found; |
| 635 | spin_unlock(&ctrl->loop_linkid_lock); | 663 | spin_unlock(&ctrl->loop_linkid_lock); |
| 664 | pr_err("CAIF: %s(): Out of link-ids\n", __func__); | ||
| 636 | return -EINVAL; | 665 | return -EINVAL; |
| 637 | found: | 666 | found: |
| 638 | if (!ctrl->loop_linkused[linkid]) | 667 | if (!ctrl->loop_linkused[linkid]) |
diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c index 6fb9f9e96cf8..7372f27f1d32 100644 --- a/net/caif/cfmuxl.c +++ b/net/caif/cfmuxl.c | |||
| @@ -62,6 +62,7 @@ int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid) | |||
| 62 | { | 62 | { |
| 63 | struct cfmuxl *muxl = container_obj(layr); | 63 | struct cfmuxl *muxl = container_obj(layr); |
| 64 | spin_lock(&muxl->receive_lock); | 64 | spin_lock(&muxl->receive_lock); |
| 65 | cfsrvl_get(up); | ||
| 65 | list_add(&up->node, &muxl->srvl_list); | 66 | list_add(&up->node, &muxl->srvl_list); |
| 66 | spin_unlock(&muxl->receive_lock); | 67 | spin_unlock(&muxl->receive_lock); |
| 67 | return 0; | 68 | return 0; |
| @@ -172,8 +173,11 @@ struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 id) | |||
| 172 | struct cfmuxl *muxl = container_obj(layr); | 173 | struct cfmuxl *muxl = container_obj(layr); |
| 173 | spin_lock(&muxl->receive_lock); | 174 | spin_lock(&muxl->receive_lock); |
| 174 | up = get_up(muxl, id); | 175 | up = get_up(muxl, id); |
| 176 | if (up == NULL) | ||
| 177 | return NULL; | ||
| 175 | memset(muxl->up_cache, 0, sizeof(muxl->up_cache)); | 178 | memset(muxl->up_cache, 0, sizeof(muxl->up_cache)); |
| 176 | list_del(&up->node); | 179 | list_del(&up->node); |
| 180 | cfsrvl_put(up); | ||
| 177 | spin_unlock(&muxl->receive_lock); | 181 | spin_unlock(&muxl->receive_lock); |
| 178 | return up; | 182 | return up; |
| 179 | } | 183 | } |
| @@ -203,8 +207,9 @@ static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt) | |||
| 203 | */ | 207 | */ |
| 204 | return /* CFGLU_EPROT; */ 0; | 208 | return /* CFGLU_EPROT; */ 0; |
| 205 | } | 209 | } |
| 206 | 210 | cfsrvl_get(up); | |
| 207 | ret = up->receive(up, pkt); | 211 | ret = up->receive(up, pkt); |
| 212 | cfsrvl_put(up); | ||
| 208 | return ret; | 213 | return ret; |
| 209 | } | 214 | } |
| 210 | 215 | ||
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index d470c51c6431..aff31f34528f 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c | |||
| @@ -158,6 +158,13 @@ void cfsrvl_init(struct cfsrvl *service, | |||
| 158 | service->layer.ctrlcmd = cfservl_ctrlcmd; | 158 | service->layer.ctrlcmd = cfservl_ctrlcmd; |
| 159 | service->layer.modemcmd = cfservl_modemcmd; | 159 | service->layer.modemcmd = cfservl_modemcmd; |
| 160 | service->dev_info = *dev_info; | 160 | service->dev_info = *dev_info; |
| 161 | kref_init(&service->ref); | ||
| 162 | } | ||
| 163 | |||
| 164 | void cfsrvl_release(struct kref *kref) | ||
| 165 | { | ||
| 166 | struct cfsrvl *service = container_of(kref, struct cfsrvl, ref); | ||
| 167 | kfree(service); | ||
| 161 | } | 168 | } |
| 162 | 169 | ||
| 163 | bool cfsrvl_ready(struct cfsrvl *service, int *err) | 170 | bool cfsrvl_ready(struct cfsrvl *service, int *err) |
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index f622ff1d39ba..610966abe2dc 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c | |||
| @@ -22,10 +22,10 @@ | |||
| 22 | #include <net/caif/cfpkt.h> | 22 | #include <net/caif/cfpkt.h> |
| 23 | #include <net/caif/caif_dev.h> | 23 | #include <net/caif/caif_dev.h> |
| 24 | 24 | ||
| 25 | #define CAIF_CONNECT_TIMEOUT 30 | 25 | /* GPRS PDP connection has MTU to 1500 */ |
| 26 | #define SIZE_MTU 1500 | 26 | #define SIZE_MTU 1500 |
| 27 | #define SIZE_MTU_MAX 4080 | 27 | /* 5 sec. connect timeout */ |
| 28 | #define SIZE_MTU_MIN 68 | 28 | #define CONNECT_TIMEOUT (5 * HZ) |
| 29 | #define CAIF_NET_DEFAULT_QUEUE_LEN 500 | 29 | #define CAIF_NET_DEFAULT_QUEUE_LEN 500 |
| 30 | 30 | ||
| 31 | #undef pr_debug | 31 | #undef pr_debug |
| @@ -37,6 +37,13 @@ static LIST_HEAD(chnl_net_list); | |||
| 37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
| 38 | MODULE_ALIAS_RTNL_LINK("caif"); | 38 | MODULE_ALIAS_RTNL_LINK("caif"); |
| 39 | 39 | ||
| 40 | enum caif_states { | ||
| 41 | CAIF_CONNECTED = 1, | ||
| 42 | CAIF_CONNECTING, | ||
| 43 | CAIF_DISCONNECTED, | ||
| 44 | CAIF_SHUTDOWN | ||
| 45 | }; | ||
| 46 | |||
| 40 | struct chnl_net { | 47 | struct chnl_net { |
| 41 | struct cflayer chnl; | 48 | struct cflayer chnl; |
| 42 | struct net_device_stats stats; | 49 | struct net_device_stats stats; |
| @@ -47,7 +54,7 @@ struct chnl_net { | |||
| 47 | wait_queue_head_t netmgmt_wq; | 54 | wait_queue_head_t netmgmt_wq; |
| 48 | /* Flow status to remember and control the transmission. */ | 55 | /* Flow status to remember and control the transmission. */ |
| 49 | bool flowenabled; | 56 | bool flowenabled; |
| 50 | bool pending_close; | 57 | enum caif_states state; |
| 51 | }; | 58 | }; |
| 52 | 59 | ||
| 53 | static void robust_list_del(struct list_head *delete_node) | 60 | static void robust_list_del(struct list_head *delete_node) |
| @@ -58,15 +65,16 @@ static void robust_list_del(struct list_head *delete_node) | |||
| 58 | list_for_each_safe(list_node, n, &chnl_net_list) { | 65 | list_for_each_safe(list_node, n, &chnl_net_list) { |
| 59 | if (list_node == delete_node) { | 66 | if (list_node == delete_node) { |
| 60 | list_del(list_node); | 67 | list_del(list_node); |
| 61 | break; | 68 | return; |
| 62 | } | 69 | } |
| 63 | } | 70 | } |
| 71 | WARN_ON(1); | ||
| 64 | } | 72 | } |
| 65 | 73 | ||
| 66 | static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) | 74 | static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) |
| 67 | { | 75 | { |
| 68 | struct sk_buff *skb; | 76 | struct sk_buff *skb; |
| 69 | struct chnl_net *priv = NULL; | 77 | struct chnl_net *priv = container_of(layr, struct chnl_net, chnl); |
| 70 | int pktlen; | 78 | int pktlen; |
| 71 | int err = 0; | 79 | int err = 0; |
| 72 | 80 | ||
| @@ -91,7 +99,6 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) | |||
| 91 | else | 99 | else |
| 92 | skb->ip_summed = CHECKSUM_NONE; | 100 | skb->ip_summed = CHECKSUM_NONE; |
| 93 | 101 | ||
| 94 | /* FIXME: Drivers should call this in tasklet context. */ | ||
| 95 | if (in_interrupt()) | 102 | if (in_interrupt()) |
| 96 | netif_rx(skb); | 103 | netif_rx(skb); |
| 97 | else | 104 | else |
| @@ -117,23 +124,25 @@ static void close_work(struct work_struct *work) | |||
| 117 | struct chnl_net *dev = NULL; | 124 | struct chnl_net *dev = NULL; |
| 118 | struct list_head *list_node; | 125 | struct list_head *list_node; |
| 119 | struct list_head *_tmp; | 126 | struct list_head *_tmp; |
| 120 | rtnl_lock(); | 127 | /* May be called with or without RTNL lock held */ |
| 128 | int islocked = rtnl_is_locked(); | ||
| 129 | if (!islocked) | ||
| 130 | rtnl_lock(); | ||
| 121 | list_for_each_safe(list_node, _tmp, &chnl_net_list) { | 131 | list_for_each_safe(list_node, _tmp, &chnl_net_list) { |
| 122 | dev = list_entry(list_node, struct chnl_net, list_field); | 132 | dev = list_entry(list_node, struct chnl_net, list_field); |
| 123 | if (!dev->pending_close) | 133 | if (dev->state == CAIF_SHUTDOWN) |
| 124 | continue; | 134 | dev_close(dev->netdev); |
| 125 | list_del(list_node); | ||
| 126 | delete_device(dev); | ||
| 127 | } | 135 | } |
| 128 | rtnl_unlock(); | 136 | if (!islocked) |
| 137 | rtnl_unlock(); | ||
| 129 | } | 138 | } |
| 130 | static DECLARE_WORK(close_worker, close_work); | 139 | static DECLARE_WORK(close_worker, close_work); |
| 131 | 140 | ||
| 132 | static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, | 141 | static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, |
| 133 | int phyid) | 142 | int phyid) |
| 134 | { | 143 | { |
| 135 | struct chnl_net *priv; | 144 | struct chnl_net *priv = container_of(layr, struct chnl_net, chnl); |
| 136 | pr_debug("CAIF: %s(): NET flowctrl func called flow: %s.\n", | 145 | pr_debug("CAIF: %s(): NET flowctrl func called flow: %s\n", |
| 137 | __func__, | 146 | __func__, |
| 138 | flow == CAIF_CTRLCMD_FLOW_ON_IND ? "ON" : | 147 | flow == CAIF_CTRLCMD_FLOW_ON_IND ? "ON" : |
| 139 | flow == CAIF_CTRLCMD_INIT_RSP ? "INIT" : | 148 | flow == CAIF_CTRLCMD_INIT_RSP ? "INIT" : |
| @@ -143,21 +152,31 @@ static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, | |||
| 143 | flow == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND ? | 152 | flow == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND ? |
| 144 | "REMOTE_SHUTDOWN" : "UKNOWN CTRL COMMAND"); | 153 | "REMOTE_SHUTDOWN" : "UKNOWN CTRL COMMAND"); |
| 145 | 154 | ||
| 146 | priv = container_of(layr, struct chnl_net, chnl); | 155 | |
| 147 | 156 | ||
| 148 | switch (flow) { | 157 | switch (flow) { |
| 149 | case CAIF_CTRLCMD_FLOW_OFF_IND: | 158 | case CAIF_CTRLCMD_FLOW_OFF_IND: |
| 159 | priv->flowenabled = false; | ||
| 160 | netif_stop_queue(priv->netdev); | ||
| 161 | break; | ||
| 150 | case CAIF_CTRLCMD_DEINIT_RSP: | 162 | case CAIF_CTRLCMD_DEINIT_RSP: |
| 163 | priv->state = CAIF_DISCONNECTED; | ||
| 164 | break; | ||
| 151 | case CAIF_CTRLCMD_INIT_FAIL_RSP: | 165 | case CAIF_CTRLCMD_INIT_FAIL_RSP: |
| 166 | priv->state = CAIF_DISCONNECTED; | ||
| 167 | wake_up_interruptible(&priv->netmgmt_wq); | ||
| 168 | break; | ||
| 152 | case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: | 169 | case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: |
| 153 | priv->flowenabled = false; | 170 | priv->state = CAIF_SHUTDOWN; |
| 154 | netif_tx_disable(priv->netdev); | 171 | netif_tx_disable(priv->netdev); |
| 155 | pr_warning("CAIF: %s(): done\n", __func__); | ||
| 156 | priv->pending_close = 1; | ||
| 157 | schedule_work(&close_worker); | 172 | schedule_work(&close_worker); |
| 158 | break; | 173 | break; |
| 159 | case CAIF_CTRLCMD_FLOW_ON_IND: | 174 | case CAIF_CTRLCMD_FLOW_ON_IND: |
| 175 | priv->flowenabled = true; | ||
| 176 | netif_wake_queue(priv->netdev); | ||
| 177 | break; | ||
| 160 | case CAIF_CTRLCMD_INIT_RSP: | 178 | case CAIF_CTRLCMD_INIT_RSP: |
| 179 | priv->state = CAIF_CONNECTED; | ||
| 161 | priv->flowenabled = true; | 180 | priv->flowenabled = true; |
| 162 | netif_wake_queue(priv->netdev); | 181 | netif_wake_queue(priv->netdev); |
| 163 | wake_up_interruptible(&priv->netmgmt_wq); | 182 | wake_up_interruptible(&priv->netmgmt_wq); |
| @@ -194,9 +213,6 @@ static int chnl_net_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 194 | 213 | ||
| 195 | pkt = cfpkt_fromnative(CAIF_DIR_OUT, (void *) skb); | 214 | pkt = cfpkt_fromnative(CAIF_DIR_OUT, (void *) skb); |
| 196 | 215 | ||
| 197 | pr_debug("CAIF: %s(): transmit inst %s %d,%p\n", | ||
| 198 | __func__, dev->name, priv->chnl.dn->id, &priv->chnl.dn); | ||
| 199 | |||
| 200 | /* Send the packet down the stack. */ | 216 | /* Send the packet down the stack. */ |
| 201 | result = priv->chnl.dn->transmit(priv->chnl.dn, pkt); | 217 | result = priv->chnl.dn->transmit(priv->chnl.dn, pkt); |
| 202 | if (result) { | 218 | if (result) { |
| @@ -217,61 +233,59 @@ static int chnl_net_open(struct net_device *dev) | |||
| 217 | struct chnl_net *priv = NULL; | 233 | struct chnl_net *priv = NULL; |
| 218 | int result = -1; | 234 | int result = -1; |
| 219 | ASSERT_RTNL(); | 235 | ASSERT_RTNL(); |
| 220 | |||
| 221 | priv = netdev_priv(dev); | 236 | priv = netdev_priv(dev); |
| 222 | pr_debug("CAIF: %s(): dev name: %s\n", __func__, priv->name); | ||
| 223 | |||
| 224 | if (!priv) { | 237 | if (!priv) { |
| 225 | pr_debug("CAIF: %s(): chnl_net_open: no priv\n", __func__); | 238 | pr_debug("CAIF: %s(): chnl_net_open: no priv\n", __func__); |
| 226 | return -ENODEV; | 239 | return -ENODEV; |
| 227 | } | 240 | } |
| 228 | result = caif_connect_client(&priv->conn_req, &priv->chnl); | 241 | |
| 229 | if (result != 0) { | 242 | if (priv->state != CAIF_CONNECTING) { |
| 230 | pr_debug("CAIF: %s(): err: " | 243 | priv->state = CAIF_CONNECTING; |
| 231 | "Unable to register and open device, Err:%d\n", | 244 | result = caif_connect_client(&priv->conn_req, &priv->chnl); |
| 232 | __func__, | 245 | if (result != 0) { |
| 233 | result); | 246 | priv->state = CAIF_DISCONNECTED; |
| 234 | return -ENODEV; | 247 | pr_debug("CAIF: %s(): err: " |
| 248 | "Unable to register and open device," | ||
| 249 | " Err:%d\n", | ||
| 250 | __func__, | ||
| 251 | result); | ||
| 252 | return result; | ||
| 253 | } | ||
| 235 | } | 254 | } |
| 236 | result = wait_event_interruptible(priv->netmgmt_wq, priv->flowenabled); | 255 | |
| 256 | result = wait_event_interruptible_timeout(priv->netmgmt_wq, | ||
| 257 | priv->state != CAIF_CONNECTING, | ||
| 258 | CONNECT_TIMEOUT); | ||
| 237 | 259 | ||
| 238 | if (result == -ERESTARTSYS) { | 260 | if (result == -ERESTARTSYS) { |
| 239 | pr_debug("CAIF: %s(): wait_event_interruptible" | 261 | pr_debug("CAIF: %s(): wait_event_interruptible" |
| 240 | " woken by a signal\n", __func__); | 262 | " woken by a signal\n", __func__); |
| 241 | return -ERESTARTSYS; | 263 | return -ERESTARTSYS; |
| 242 | } else | 264 | } |
| 243 | pr_debug("CAIF: %s(): Flow on recieved\n", __func__); | 265 | if (result == 0) { |
| 266 | pr_debug("CAIF: %s(): connect timeout\n", __func__); | ||
| 267 | caif_disconnect_client(&priv->chnl); | ||
| 268 | priv->state = CAIF_DISCONNECTED; | ||
| 269 | pr_debug("CAIF: %s(): state disconnected\n", __func__); | ||
| 270 | return -ETIMEDOUT; | ||
| 271 | } | ||
| 244 | 272 | ||
| 273 | if (priv->state != CAIF_CONNECTED) { | ||
| 274 | pr_debug("CAIF: %s(): connect failed\n", __func__); | ||
| 275 | return -ECONNREFUSED; | ||
| 276 | } | ||
| 277 | pr_debug("CAIF: %s(): CAIF Netdevice connected\n", __func__); | ||
| 245 | return 0; | 278 | return 0; |
| 246 | } | 279 | } |
| 247 | 280 | ||
| 248 | static int chnl_net_stop(struct net_device *dev) | 281 | static int chnl_net_stop(struct net_device *dev) |
| 249 | { | 282 | { |
| 250 | struct chnl_net *priv; | 283 | struct chnl_net *priv; |
| 251 | int result = -1; | 284 | |
| 252 | ASSERT_RTNL(); | 285 | ASSERT_RTNL(); |
| 253 | priv = netdev_priv(dev); | 286 | priv = netdev_priv(dev); |
| 254 | 287 | priv->state = CAIF_DISCONNECTED; | |
| 255 | result = caif_disconnect_client(&priv->chnl); | 288 | caif_disconnect_client(&priv->chnl); |
| 256 | if (result != 0) { | ||
| 257 | pr_debug("CAIF: %s(): chnl_net_stop: err: " | ||
| 258 | "Unable to STOP device, Err:%d\n", | ||
| 259 | __func__, result); | ||
| 260 | return -EBUSY; | ||
| 261 | } | ||
| 262 | result = wait_event_interruptible(priv->netmgmt_wq, | ||
| 263 | !priv->flowenabled); | ||
| 264 | |||
| 265 | if (result == -ERESTARTSYS) { | ||
| 266 | pr_debug("CAIF: %s(): wait_event_interruptible woken by" | ||
| 267 | " signal, signal_pending(current) = %d\n", | ||
| 268 | __func__, | ||
| 269 | signal_pending(current)); | ||
| 270 | } else { | ||
| 271 | pr_debug("CAIF: %s(): disconnect received\n", __func__); | ||
| 272 | |||
| 273 | } | ||
| 274 | |||
| 275 | return 0; | 289 | return 0; |
| 276 | } | 290 | } |
| 277 | 291 | ||
| @@ -377,6 +391,8 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev, | |||
| 377 | ASSERT_RTNL(); | 391 | ASSERT_RTNL(); |
| 378 | caifdev = netdev_priv(dev); | 392 | caifdev = netdev_priv(dev); |
| 379 | caif_netlink_parms(data, &caifdev->conn_req); | 393 | caif_netlink_parms(data, &caifdev->conn_req); |
| 394 | dev_net_set(caifdev->netdev, src_net); | ||
| 395 | |||
| 380 | ret = register_netdevice(dev); | 396 | ret = register_netdevice(dev); |
| 381 | if (ret) | 397 | if (ret) |
| 382 | pr_warning("CAIF: %s(): device rtml registration failed\n", | 398 | pr_warning("CAIF: %s(): device rtml registration failed\n", |
diff --git a/net/core/datagram.c b/net/core/datagram.c index 2dccd4ee591b..e0097531417a 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
| @@ -86,7 +86,7 @@ static int wait_for_packet(struct sock *sk, int *err, long *timeo_p) | |||
| 86 | int error; | 86 | int error; |
| 87 | DEFINE_WAIT_FUNC(wait, receiver_wake_function); | 87 | DEFINE_WAIT_FUNC(wait, receiver_wake_function); |
| 88 | 88 | ||
| 89 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 89 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 90 | 90 | ||
| 91 | /* Socket errors? */ | 91 | /* Socket errors? */ |
| 92 | error = sock_error(sk); | 92 | error = sock_error(sk); |
| @@ -115,7 +115,7 @@ static int wait_for_packet(struct sock *sk, int *err, long *timeo_p) | |||
| 115 | error = 0; | 115 | error = 0; |
| 116 | *timeo_p = schedule_timeout(*timeo_p); | 116 | *timeo_p = schedule_timeout(*timeo_p); |
| 117 | out: | 117 | out: |
| 118 | finish_wait(sk->sk_sleep, &wait); | 118 | finish_wait(sk_sleep(sk), &wait); |
| 119 | return error; | 119 | return error; |
| 120 | interrupted: | 120 | interrupted: |
| 121 | error = sock_intr_errno(*timeo_p); | 121 | error = sock_intr_errno(*timeo_p); |
| @@ -229,9 +229,18 @@ EXPORT_SYMBOL(skb_free_datagram); | |||
| 229 | 229 | ||
| 230 | void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) | 230 | void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) |
| 231 | { | 231 | { |
| 232 | lock_sock(sk); | 232 | if (likely(atomic_read(&skb->users) == 1)) |
| 233 | skb_free_datagram(sk, skb); | 233 | smp_rmb(); |
| 234 | release_sock(sk); | 234 | else if (likely(!atomic_dec_and_test(&skb->users))) |
| 235 | return; | ||
| 236 | |||
| 237 | lock_sock_bh(sk); | ||
| 238 | skb_orphan(skb); | ||
| 239 | sk_mem_reclaim_partial(sk); | ||
| 240 | unlock_sock_bh(sk); | ||
| 241 | |||
| 242 | /* skb is now orphaned, can be freed outside of locked section */ | ||
| 243 | __kfree_skb(skb); | ||
| 235 | } | 244 | } |
| 236 | EXPORT_SYMBOL(skb_free_datagram_locked); | 245 | EXPORT_SYMBOL(skb_free_datagram_locked); |
| 237 | 246 | ||
| @@ -726,7 +735,7 @@ unsigned int datagram_poll(struct file *file, struct socket *sock, | |||
| 726 | struct sock *sk = sock->sk; | 735 | struct sock *sk = sock->sk; |
| 727 | unsigned int mask; | 736 | unsigned int mask; |
| 728 | 737 | ||
| 729 | sock_poll_wait(file, sk->sk_sleep, wait); | 738 | sock_poll_wait(file, sk_sleep(sk), wait); |
| 730 | mask = 0; | 739 | mask = 0; |
| 731 | 740 | ||
| 732 | /* exceptional events? */ | 741 | /* exceptional events? */ |
diff --git a/net/core/dev.c b/net/core/dev.c index b31d5d69a467..32611c8f1219 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1557,8 +1557,9 @@ static inline void __netif_reschedule(struct Qdisc *q) | |||
| 1557 | 1557 | ||
| 1558 | local_irq_save(flags); | 1558 | local_irq_save(flags); |
| 1559 | sd = &__get_cpu_var(softnet_data); | 1559 | sd = &__get_cpu_var(softnet_data); |
| 1560 | q->next_sched = sd->output_queue; | 1560 | q->next_sched = NULL; |
| 1561 | sd->output_queue = q; | 1561 | *sd->output_queue_tailp = q; |
| 1562 | sd->output_queue_tailp = &q->next_sched; | ||
| 1562 | raise_softirq_irqoff(NET_TX_SOFTIRQ); | 1563 | raise_softirq_irqoff(NET_TX_SOFTIRQ); |
| 1563 | local_irq_restore(flags); | 1564 | local_irq_restore(flags); |
| 1564 | } | 1565 | } |
| @@ -1902,13 +1903,6 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | |||
| 1902 | if (!list_empty(&ptype_all)) | 1903 | if (!list_empty(&ptype_all)) |
| 1903 | dev_queue_xmit_nit(skb, dev); | 1904 | dev_queue_xmit_nit(skb, dev); |
| 1904 | 1905 | ||
| 1905 | if (netif_needs_gso(dev, skb)) { | ||
| 1906 | if (unlikely(dev_gso_segment(skb))) | ||
| 1907 | goto out_kfree_skb; | ||
| 1908 | if (skb->next) | ||
| 1909 | goto gso; | ||
| 1910 | } | ||
| 1911 | |||
| 1912 | /* | 1906 | /* |
| 1913 | * If device doesnt need skb->dst, release it right now while | 1907 | * If device doesnt need skb->dst, release it right now while |
| 1914 | * its hot in this cpu cache | 1908 | * its hot in this cpu cache |
| @@ -1917,6 +1911,14 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | |||
| 1917 | skb_dst_drop(skb); | 1911 | skb_dst_drop(skb); |
| 1918 | 1912 | ||
| 1919 | skb_orphan_try(skb); | 1913 | skb_orphan_try(skb); |
| 1914 | |||
| 1915 | if (netif_needs_gso(dev, skb)) { | ||
| 1916 | if (unlikely(dev_gso_segment(skb))) | ||
| 1917 | goto out_kfree_skb; | ||
| 1918 | if (skb->next) | ||
| 1919 | goto gso; | ||
| 1920 | } | ||
| 1921 | |||
| 1920 | rc = ops->ndo_start_xmit(skb, dev); | 1922 | rc = ops->ndo_start_xmit(skb, dev); |
| 1921 | if (rc == NETDEV_TX_OK) | 1923 | if (rc == NETDEV_TX_OK) |
| 1922 | txq_trans_update(txq); | 1924 | txq_trans_update(txq); |
| @@ -1937,7 +1939,6 @@ gso: | |||
| 1937 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) | 1939 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) |
| 1938 | skb_dst_drop(nskb); | 1940 | skb_dst_drop(nskb); |
| 1939 | 1941 | ||
| 1940 | skb_orphan_try(nskb); | ||
| 1941 | rc = ops->ndo_start_xmit(nskb, dev); | 1942 | rc = ops->ndo_start_xmit(nskb, dev); |
| 1942 | if (unlikely(rc != NETDEV_TX_OK)) { | 1943 | if (unlikely(rc != NETDEV_TX_OK)) { |
| 1943 | if (rc & ~NETDEV_TX_MASK) | 1944 | if (rc & ~NETDEV_TX_MASK) |
| @@ -2015,8 +2016,12 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev, | |||
| 2015 | if (dev->real_num_tx_queues > 1) | 2016 | if (dev->real_num_tx_queues > 1) |
| 2016 | queue_index = skb_tx_hash(dev, skb); | 2017 | queue_index = skb_tx_hash(dev, skb); |
| 2017 | 2018 | ||
| 2018 | if (sk && rcu_dereference_check(sk->sk_dst_cache, 1)) | 2019 | if (sk) { |
| 2019 | sk_tx_queue_set(sk, queue_index); | 2020 | struct dst_entry *dst = rcu_dereference_check(sk->sk_dst_cache, 1); |
| 2021 | |||
| 2022 | if (dst && skb_dst(skb) == dst) | ||
| 2023 | sk_tx_queue_set(sk, queue_index); | ||
| 2024 | } | ||
| 2020 | } | 2025 | } |
| 2021 | } | 2026 | } |
| 2022 | 2027 | ||
| @@ -2200,7 +2205,13 @@ int netdev_max_backlog __read_mostly = 1000; | |||
| 2200 | int netdev_budget __read_mostly = 300; | 2205 | int netdev_budget __read_mostly = 300; |
| 2201 | int weight_p __read_mostly = 64; /* old backlog weight */ | 2206 | int weight_p __read_mostly = 64; /* old backlog weight */ |
| 2202 | 2207 | ||
| 2203 | DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; | 2208 | /* Called with irq disabled */ |
| 2209 | static inline void ____napi_schedule(struct softnet_data *sd, | ||
| 2210 | struct napi_struct *napi) | ||
| 2211 | { | ||
| 2212 | list_add_tail(&napi->poll_list, &sd->poll_list); | ||
| 2213 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
| 2214 | } | ||
| 2204 | 2215 | ||
| 2205 | #ifdef CONFIG_RPS | 2216 | #ifdef CONFIG_RPS |
| 2206 | 2217 | ||
| @@ -2225,7 +2236,11 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
| 2225 | int cpu = -1; | 2236 | int cpu = -1; |
| 2226 | u8 ip_proto; | 2237 | u8 ip_proto; |
| 2227 | u16 tcpu; | 2238 | u16 tcpu; |
| 2228 | u32 addr1, addr2, ports, ihl; | 2239 | u32 addr1, addr2, ihl; |
| 2240 | union { | ||
| 2241 | u32 v32; | ||
| 2242 | u16 v16[2]; | ||
| 2243 | } ports; | ||
| 2229 | 2244 | ||
| 2230 | if (skb_rx_queue_recorded(skb)) { | 2245 | if (skb_rx_queue_recorded(skb)) { |
| 2231 | u16 index = skb_get_rx_queue(skb); | 2246 | u16 index = skb_get_rx_queue(skb); |
| @@ -2271,7 +2286,6 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
| 2271 | default: | 2286 | default: |
| 2272 | goto done; | 2287 | goto done; |
| 2273 | } | 2288 | } |
| 2274 | ports = 0; | ||
| 2275 | switch (ip_proto) { | 2289 | switch (ip_proto) { |
| 2276 | case IPPROTO_TCP: | 2290 | case IPPROTO_TCP: |
| 2277 | case IPPROTO_UDP: | 2291 | case IPPROTO_UDP: |
| @@ -2281,25 +2295,20 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
| 2281 | case IPPROTO_SCTP: | 2295 | case IPPROTO_SCTP: |
| 2282 | case IPPROTO_UDPLITE: | 2296 | case IPPROTO_UDPLITE: |
| 2283 | if (pskb_may_pull(skb, (ihl * 4) + 4)) { | 2297 | if (pskb_may_pull(skb, (ihl * 4) + 4)) { |
| 2284 | __be16 *hports = (__be16 *) (skb->data + (ihl * 4)); | 2298 | ports.v32 = * (__force u32 *) (skb->data + (ihl * 4)); |
| 2285 | u32 sport, dport; | 2299 | if (ports.v16[1] < ports.v16[0]) |
| 2286 | 2300 | swap(ports.v16[0], ports.v16[1]); | |
| 2287 | sport = (__force u16) hports[0]; | 2301 | break; |
| 2288 | dport = (__force u16) hports[1]; | ||
| 2289 | if (dport < sport) | ||
| 2290 | swap(sport, dport); | ||
| 2291 | ports = (sport << 16) + dport; | ||
| 2292 | } | 2302 | } |
| 2293 | break; | ||
| 2294 | |||
| 2295 | default: | 2303 | default: |
| 2304 | ports.v32 = 0; | ||
| 2296 | break; | 2305 | break; |
| 2297 | } | 2306 | } |
| 2298 | 2307 | ||
| 2299 | /* get a consistent hash (same value on both flow directions) */ | 2308 | /* get a consistent hash (same value on both flow directions) */ |
| 2300 | if (addr2 < addr1) | 2309 | if (addr2 < addr1) |
| 2301 | swap(addr1, addr2); | 2310 | swap(addr1, addr2); |
| 2302 | skb->rxhash = jhash_3words(addr1, addr2, ports, hashrnd); | 2311 | skb->rxhash = jhash_3words(addr1, addr2, ports.v32, hashrnd); |
| 2303 | if (!skb->rxhash) | 2312 | if (!skb->rxhash) |
| 2304 | skb->rxhash = 1; | 2313 | skb->rxhash = 1; |
| 2305 | 2314 | ||
| @@ -2362,8 +2371,8 @@ static void rps_trigger_softirq(void *data) | |||
| 2362 | { | 2371 | { |
| 2363 | struct softnet_data *sd = data; | 2372 | struct softnet_data *sd = data; |
| 2364 | 2373 | ||
| 2365 | __napi_schedule(&sd->backlog); | 2374 | ____napi_schedule(sd, &sd->backlog); |
| 2366 | __get_cpu_var(netdev_rx_stat).received_rps++; | 2375 | sd->received_rps++; |
| 2367 | } | 2376 | } |
| 2368 | 2377 | ||
| 2369 | #endif /* CONFIG_RPS */ | 2378 | #endif /* CONFIG_RPS */ |
| @@ -2402,15 +2411,15 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu, | |||
| 2402 | sd = &per_cpu(softnet_data, cpu); | 2411 | sd = &per_cpu(softnet_data, cpu); |
| 2403 | 2412 | ||
| 2404 | local_irq_save(flags); | 2413 | local_irq_save(flags); |
| 2405 | __get_cpu_var(netdev_rx_stat).total++; | ||
| 2406 | 2414 | ||
| 2407 | rps_lock(sd); | 2415 | rps_lock(sd); |
| 2408 | if (sd->input_pkt_queue.qlen <= netdev_max_backlog) { | 2416 | if (skb_queue_len(&sd->input_pkt_queue) <= netdev_max_backlog) { |
| 2409 | if (sd->input_pkt_queue.qlen) { | 2417 | if (skb_queue_len(&sd->input_pkt_queue)) { |
| 2410 | enqueue: | 2418 | enqueue: |
| 2411 | __skb_queue_tail(&sd->input_pkt_queue, skb); | 2419 | __skb_queue_tail(&sd->input_pkt_queue, skb); |
| 2412 | #ifdef CONFIG_RPS | 2420 | #ifdef CONFIG_RPS |
| 2413 | *qtail = sd->input_queue_head + sd->input_pkt_queue.qlen; | 2421 | *qtail = sd->input_queue_head + |
| 2422 | skb_queue_len(&sd->input_pkt_queue); | ||
| 2414 | #endif | 2423 | #endif |
| 2415 | rps_unlock(sd); | 2424 | rps_unlock(sd); |
| 2416 | local_irq_restore(flags); | 2425 | local_irq_restore(flags); |
| @@ -2420,14 +2429,14 @@ enqueue: | |||
| 2420 | /* Schedule NAPI for backlog device */ | 2429 | /* Schedule NAPI for backlog device */ |
| 2421 | if (napi_schedule_prep(&sd->backlog)) { | 2430 | if (napi_schedule_prep(&sd->backlog)) { |
| 2422 | if (!rps_ipi_queued(sd)) | 2431 | if (!rps_ipi_queued(sd)) |
| 2423 | __napi_schedule(&sd->backlog); | 2432 | ____napi_schedule(sd, &sd->backlog); |
| 2424 | } | 2433 | } |
| 2425 | goto enqueue; | 2434 | goto enqueue; |
| 2426 | } | 2435 | } |
| 2427 | 2436 | ||
| 2437 | sd->dropped++; | ||
| 2428 | rps_unlock(sd); | 2438 | rps_unlock(sd); |
| 2429 | 2439 | ||
| 2430 | __get_cpu_var(netdev_rx_stat).dropped++; | ||
| 2431 | local_irq_restore(flags); | 2440 | local_irq_restore(flags); |
| 2432 | 2441 | ||
| 2433 | kfree_skb(skb); | 2442 | kfree_skb(skb); |
| @@ -2527,6 +2536,7 @@ static void net_tx_action(struct softirq_action *h) | |||
| 2527 | local_irq_disable(); | 2536 | local_irq_disable(); |
| 2528 | head = sd->output_queue; | 2537 | head = sd->output_queue; |
| 2529 | sd->output_queue = NULL; | 2538 | sd->output_queue = NULL; |
| 2539 | sd->output_queue_tailp = &sd->output_queue; | ||
| 2530 | local_irq_enable(); | 2540 | local_irq_enable(); |
| 2531 | 2541 | ||
| 2532 | while (head) { | 2542 | while (head) { |
| @@ -2801,7 +2811,7 @@ static int __netif_receive_skb(struct sk_buff *skb) | |||
| 2801 | skb->dev = master; | 2811 | skb->dev = master; |
| 2802 | } | 2812 | } |
| 2803 | 2813 | ||
| 2804 | __get_cpu_var(netdev_rx_stat).total++; | 2814 | __get_cpu_var(softnet_data).processed++; |
| 2805 | 2815 | ||
| 2806 | skb_reset_network_header(skb); | 2816 | skb_reset_network_header(skb); |
| 2807 | skb_reset_transport_header(skb); | 2817 | skb_reset_transport_header(skb); |
| @@ -2930,13 +2940,21 @@ static void flush_backlog(void *arg) | |||
| 2930 | struct sk_buff *skb, *tmp; | 2940 | struct sk_buff *skb, *tmp; |
| 2931 | 2941 | ||
| 2932 | rps_lock(sd); | 2942 | rps_lock(sd); |
| 2933 | skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) | 2943 | skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) { |
| 2934 | if (skb->dev == dev) { | 2944 | if (skb->dev == dev) { |
| 2935 | __skb_unlink(skb, &sd->input_pkt_queue); | 2945 | __skb_unlink(skb, &sd->input_pkt_queue); |
| 2936 | kfree_skb(skb); | 2946 | kfree_skb(skb); |
| 2937 | input_queue_head_incr(sd); | 2947 | input_queue_head_add(sd, 1); |
| 2938 | } | 2948 | } |
| 2949 | } | ||
| 2939 | rps_unlock(sd); | 2950 | rps_unlock(sd); |
| 2951 | |||
| 2952 | skb_queue_walk_safe(&sd->process_queue, skb, tmp) { | ||
| 2953 | if (skb->dev == dev) { | ||
| 2954 | __skb_unlink(skb, &sd->process_queue); | ||
| 2955 | kfree_skb(skb); | ||
| 2956 | } | ||
| 2957 | } | ||
| 2940 | } | 2958 | } |
| 2941 | 2959 | ||
| 2942 | static int napi_gro_complete(struct sk_buff *skb) | 2960 | static int napi_gro_complete(struct sk_buff *skb) |
| @@ -3239,30 +3257,85 @@ gro_result_t napi_gro_frags(struct napi_struct *napi) | |||
| 3239 | } | 3257 | } |
| 3240 | EXPORT_SYMBOL(napi_gro_frags); | 3258 | EXPORT_SYMBOL(napi_gro_frags); |
| 3241 | 3259 | ||
| 3260 | /* | ||
| 3261 | * net_rps_action sends any pending IPI's for rps. | ||
| 3262 | * Note: called with local irq disabled, but exits with local irq enabled. | ||
| 3263 | */ | ||
| 3264 | static void net_rps_action_and_irq_enable(struct softnet_data *sd) | ||
| 3265 | { | ||
| 3266 | #ifdef CONFIG_RPS | ||
| 3267 | struct softnet_data *remsd = sd->rps_ipi_list; | ||
| 3268 | |||
| 3269 | if (remsd) { | ||
| 3270 | sd->rps_ipi_list = NULL; | ||
| 3271 | |||
| 3272 | local_irq_enable(); | ||
| 3273 | |||
| 3274 | /* Send pending IPI's to kick RPS processing on remote cpus. */ | ||
| 3275 | while (remsd) { | ||
| 3276 | struct softnet_data *next = remsd->rps_ipi_next; | ||
| 3277 | |||
| 3278 | if (cpu_online(remsd->cpu)) | ||
| 3279 | __smp_call_function_single(remsd->cpu, | ||
| 3280 | &remsd->csd, 0); | ||
| 3281 | remsd = next; | ||
| 3282 | } | ||
| 3283 | } else | ||
| 3284 | #endif | ||
| 3285 | local_irq_enable(); | ||
| 3286 | } | ||
| 3287 | |||
| 3242 | static int process_backlog(struct napi_struct *napi, int quota) | 3288 | static int process_backlog(struct napi_struct *napi, int quota) |
| 3243 | { | 3289 | { |
| 3244 | int work = 0; | 3290 | int work = 0; |
| 3245 | struct softnet_data *sd = &__get_cpu_var(softnet_data); | 3291 | struct softnet_data *sd = container_of(napi, struct softnet_data, backlog); |
| 3246 | 3292 | ||
| 3293 | #ifdef CONFIG_RPS | ||
| 3294 | /* Check if we have pending ipi, its better to send them now, | ||
| 3295 | * not waiting net_rx_action() end. | ||
| 3296 | */ | ||
| 3297 | if (sd->rps_ipi_list) { | ||
| 3298 | local_irq_disable(); | ||
| 3299 | net_rps_action_and_irq_enable(sd); | ||
| 3300 | } | ||
| 3301 | #endif | ||
| 3247 | napi->weight = weight_p; | 3302 | napi->weight = weight_p; |
| 3248 | do { | 3303 | local_irq_disable(); |
| 3304 | while (work < quota) { | ||
| 3249 | struct sk_buff *skb; | 3305 | struct sk_buff *skb; |
| 3306 | unsigned int qlen; | ||
| 3250 | 3307 | ||
| 3251 | local_irq_disable(); | 3308 | while ((skb = __skb_dequeue(&sd->process_queue))) { |
| 3252 | rps_lock(sd); | ||
| 3253 | skb = __skb_dequeue(&sd->input_pkt_queue); | ||
| 3254 | if (!skb) { | ||
| 3255 | __napi_complete(napi); | ||
| 3256 | rps_unlock(sd); | ||
| 3257 | local_irq_enable(); | 3309 | local_irq_enable(); |
| 3258 | break; | 3310 | __netif_receive_skb(skb); |
| 3311 | if (++work >= quota) | ||
| 3312 | return work; | ||
| 3313 | local_irq_disable(); | ||
| 3259 | } | 3314 | } |
| 3260 | input_queue_head_incr(sd); | ||
| 3261 | rps_unlock(sd); | ||
| 3262 | local_irq_enable(); | ||
| 3263 | 3315 | ||
| 3264 | __netif_receive_skb(skb); | 3316 | rps_lock(sd); |
| 3265 | } while (++work < quota); | 3317 | qlen = skb_queue_len(&sd->input_pkt_queue); |
| 3318 | if (qlen) { | ||
| 3319 | input_queue_head_add(sd, qlen); | ||
| 3320 | skb_queue_splice_tail_init(&sd->input_pkt_queue, | ||
| 3321 | &sd->process_queue); | ||
| 3322 | } | ||
| 3323 | if (qlen < quota - work) { | ||
| 3324 | /* | ||
| 3325 | * Inline a custom version of __napi_complete(). | ||
| 3326 | * only current cpu owns and manipulates this napi, | ||
| 3327 | * and NAPI_STATE_SCHED is the only possible flag set on backlog. | ||
| 3328 | * we can use a plain write instead of clear_bit(), | ||
| 3329 | * and we dont need an smp_mb() memory barrier. | ||
| 3330 | */ | ||
| 3331 | list_del(&napi->poll_list); | ||
| 3332 | napi->state = 0; | ||
| 3333 | |||
| 3334 | quota = work + qlen; | ||
| 3335 | } | ||
| 3336 | rps_unlock(sd); | ||
| 3337 | } | ||
| 3338 | local_irq_enable(); | ||
| 3266 | 3339 | ||
| 3267 | return work; | 3340 | return work; |
| 3268 | } | 3341 | } |
| @@ -3278,8 +3351,7 @@ void __napi_schedule(struct napi_struct *n) | |||
| 3278 | unsigned long flags; | 3351 | unsigned long flags; |
| 3279 | 3352 | ||
| 3280 | local_irq_save(flags); | 3353 | local_irq_save(flags); |
| 3281 | list_add_tail(&n->poll_list, &__get_cpu_var(softnet_data).poll_list); | 3354 | ____napi_schedule(&__get_cpu_var(softnet_data), n); |
| 3282 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
| 3283 | local_irq_restore(flags); | 3355 | local_irq_restore(flags); |
| 3284 | } | 3356 | } |
| 3285 | EXPORT_SYMBOL(__napi_schedule); | 3357 | EXPORT_SYMBOL(__napi_schedule); |
| @@ -3350,45 +3422,16 @@ void netif_napi_del(struct napi_struct *napi) | |||
| 3350 | } | 3422 | } |
| 3351 | EXPORT_SYMBOL(netif_napi_del); | 3423 | EXPORT_SYMBOL(netif_napi_del); |
| 3352 | 3424 | ||
| 3353 | /* | ||
| 3354 | * net_rps_action sends any pending IPI's for rps. | ||
| 3355 | * Note: called with local irq disabled, but exits with local irq enabled. | ||
| 3356 | */ | ||
| 3357 | static void net_rps_action_and_irq_disable(void) | ||
| 3358 | { | ||
| 3359 | #ifdef CONFIG_RPS | ||
| 3360 | struct softnet_data *sd = &__get_cpu_var(softnet_data); | ||
| 3361 | struct softnet_data *remsd = sd->rps_ipi_list; | ||
| 3362 | |||
| 3363 | if (remsd) { | ||
| 3364 | sd->rps_ipi_list = NULL; | ||
| 3365 | |||
| 3366 | local_irq_enable(); | ||
| 3367 | |||
| 3368 | /* Send pending IPI's to kick RPS processing on remote cpus. */ | ||
| 3369 | while (remsd) { | ||
| 3370 | struct softnet_data *next = remsd->rps_ipi_next; | ||
| 3371 | |||
| 3372 | if (cpu_online(remsd->cpu)) | ||
| 3373 | __smp_call_function_single(remsd->cpu, | ||
| 3374 | &remsd->csd, 0); | ||
| 3375 | remsd = next; | ||
| 3376 | } | ||
| 3377 | } else | ||
| 3378 | #endif | ||
| 3379 | local_irq_enable(); | ||
| 3380 | } | ||
| 3381 | |||
| 3382 | static void net_rx_action(struct softirq_action *h) | 3425 | static void net_rx_action(struct softirq_action *h) |
| 3383 | { | 3426 | { |
| 3384 | struct list_head *list = &__get_cpu_var(softnet_data).poll_list; | 3427 | struct softnet_data *sd = &__get_cpu_var(softnet_data); |
| 3385 | unsigned long time_limit = jiffies + 2; | 3428 | unsigned long time_limit = jiffies + 2; |
| 3386 | int budget = netdev_budget; | 3429 | int budget = netdev_budget; |
| 3387 | void *have; | 3430 | void *have; |
| 3388 | 3431 | ||
| 3389 | local_irq_disable(); | 3432 | local_irq_disable(); |
| 3390 | 3433 | ||
| 3391 | while (!list_empty(list)) { | 3434 | while (!list_empty(&sd->poll_list)) { |
| 3392 | struct napi_struct *n; | 3435 | struct napi_struct *n; |
| 3393 | int work, weight; | 3436 | int work, weight; |
| 3394 | 3437 | ||
| @@ -3406,7 +3449,7 @@ static void net_rx_action(struct softirq_action *h) | |||
| 3406 | * entries to the tail of this list, and only ->poll() | 3449 | * entries to the tail of this list, and only ->poll() |
| 3407 | * calls can remove this head entry from the list. | 3450 | * calls can remove this head entry from the list. |
| 3408 | */ | 3451 | */ |
| 3409 | n = list_first_entry(list, struct napi_struct, poll_list); | 3452 | n = list_first_entry(&sd->poll_list, struct napi_struct, poll_list); |
| 3410 | 3453 | ||
| 3411 | have = netpoll_poll_lock(n); | 3454 | have = netpoll_poll_lock(n); |
| 3412 | 3455 | ||
| @@ -3441,13 +3484,13 @@ static void net_rx_action(struct softirq_action *h) | |||
| 3441 | napi_complete(n); | 3484 | napi_complete(n); |
| 3442 | local_irq_disable(); | 3485 | local_irq_disable(); |
| 3443 | } else | 3486 | } else |
| 3444 | list_move_tail(&n->poll_list, list); | 3487 | list_move_tail(&n->poll_list, &sd->poll_list); |
| 3445 | } | 3488 | } |
| 3446 | 3489 | ||
| 3447 | netpoll_poll_unlock(have); | 3490 | netpoll_poll_unlock(have); |
| 3448 | } | 3491 | } |
| 3449 | out: | 3492 | out: |
| 3450 | net_rps_action_and_irq_disable(); | 3493 | net_rps_action_and_irq_enable(sd); |
| 3451 | 3494 | ||
| 3452 | #ifdef CONFIG_NET_DMA | 3495 | #ifdef CONFIG_NET_DMA |
| 3453 | /* | 3496 | /* |
| @@ -3460,7 +3503,7 @@ out: | |||
| 3460 | return; | 3503 | return; |
| 3461 | 3504 | ||
| 3462 | softnet_break: | 3505 | softnet_break: |
| 3463 | __get_cpu_var(netdev_rx_stat).time_squeeze++; | 3506 | sd->time_squeeze++; |
| 3464 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | 3507 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); |
| 3465 | goto out; | 3508 | goto out; |
| 3466 | } | 3509 | } |
| @@ -3661,17 +3704,17 @@ static int dev_seq_show(struct seq_file *seq, void *v) | |||
| 3661 | return 0; | 3704 | return 0; |
| 3662 | } | 3705 | } |
| 3663 | 3706 | ||
| 3664 | static struct netif_rx_stats *softnet_get_online(loff_t *pos) | 3707 | static struct softnet_data *softnet_get_online(loff_t *pos) |
| 3665 | { | 3708 | { |
| 3666 | struct netif_rx_stats *rc = NULL; | 3709 | struct softnet_data *sd = NULL; |
| 3667 | 3710 | ||
| 3668 | while (*pos < nr_cpu_ids) | 3711 | while (*pos < nr_cpu_ids) |
| 3669 | if (cpu_online(*pos)) { | 3712 | if (cpu_online(*pos)) { |
| 3670 | rc = &per_cpu(netdev_rx_stat, *pos); | 3713 | sd = &per_cpu(softnet_data, *pos); |
| 3671 | break; | 3714 | break; |
| 3672 | } else | 3715 | } else |
| 3673 | ++*pos; | 3716 | ++*pos; |
| 3674 | return rc; | 3717 | return sd; |
| 3675 | } | 3718 | } |
| 3676 | 3719 | ||
| 3677 | static void *softnet_seq_start(struct seq_file *seq, loff_t *pos) | 3720 | static void *softnet_seq_start(struct seq_file *seq, loff_t *pos) |
| @@ -3691,12 +3734,12 @@ static void softnet_seq_stop(struct seq_file *seq, void *v) | |||
| 3691 | 3734 | ||
| 3692 | static int softnet_seq_show(struct seq_file *seq, void *v) | 3735 | static int softnet_seq_show(struct seq_file *seq, void *v) |
| 3693 | { | 3736 | { |
| 3694 | struct netif_rx_stats *s = v; | 3737 | struct softnet_data *sd = v; |
| 3695 | 3738 | ||
| 3696 | seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", | 3739 | seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", |
| 3697 | s->total, s->dropped, s->time_squeeze, 0, | 3740 | sd->processed, sd->dropped, sd->time_squeeze, 0, |
| 3698 | 0, 0, 0, 0, /* was fastroute */ | 3741 | 0, 0, 0, 0, /* was fastroute */ |
| 3699 | s->cpu_collision, s->received_rps); | 3742 | sd->cpu_collision, sd->received_rps); |
| 3700 | return 0; | 3743 | return 0; |
| 3701 | } | 3744 | } |
| 3702 | 3745 | ||
| @@ -5584,7 +5627,6 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
| 5584 | void *ocpu) | 5627 | void *ocpu) |
| 5585 | { | 5628 | { |
| 5586 | struct sk_buff **list_skb; | 5629 | struct sk_buff **list_skb; |
| 5587 | struct Qdisc **list_net; | ||
| 5588 | struct sk_buff *skb; | 5630 | struct sk_buff *skb; |
| 5589 | unsigned int cpu, oldcpu = (unsigned long)ocpu; | 5631 | unsigned int cpu, oldcpu = (unsigned long)ocpu; |
| 5590 | struct softnet_data *sd, *oldsd; | 5632 | struct softnet_data *sd, *oldsd; |
| @@ -5605,13 +5647,13 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
| 5605 | *list_skb = oldsd->completion_queue; | 5647 | *list_skb = oldsd->completion_queue; |
| 5606 | oldsd->completion_queue = NULL; | 5648 | oldsd->completion_queue = NULL; |
| 5607 | 5649 | ||
| 5608 | /* Find end of our output_queue. */ | ||
| 5609 | list_net = &sd->output_queue; | ||
| 5610 | while (*list_net) | ||
| 5611 | list_net = &(*list_net)->next_sched; | ||
| 5612 | /* Append output queue from offline CPU. */ | 5650 | /* Append output queue from offline CPU. */ |
| 5613 | *list_net = oldsd->output_queue; | 5651 | if (oldsd->output_queue) { |
| 5614 | oldsd->output_queue = NULL; | 5652 | *sd->output_queue_tailp = oldsd->output_queue; |
| 5653 | sd->output_queue_tailp = oldsd->output_queue_tailp; | ||
| 5654 | oldsd->output_queue = NULL; | ||
| 5655 | oldsd->output_queue_tailp = &oldsd->output_queue; | ||
| 5656 | } | ||
| 5615 | 5657 | ||
| 5616 | raise_softirq_irqoff(NET_TX_SOFTIRQ); | 5658 | raise_softirq_irqoff(NET_TX_SOFTIRQ); |
| 5617 | local_irq_enable(); | 5659 | local_irq_enable(); |
| @@ -5619,8 +5661,10 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
| 5619 | /* Process offline CPU's input_pkt_queue */ | 5661 | /* Process offline CPU's input_pkt_queue */ |
| 5620 | while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { | 5662 | while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { |
| 5621 | netif_rx(skb); | 5663 | netif_rx(skb); |
| 5622 | input_queue_head_incr(oldsd); | 5664 | input_queue_head_add(oldsd, 1); |
| 5623 | } | 5665 | } |
| 5666 | while ((skb = __skb_dequeue(&oldsd->process_queue))) | ||
| 5667 | netif_rx(skb); | ||
| 5624 | 5668 | ||
| 5625 | return NOTIFY_OK; | 5669 | return NOTIFY_OK; |
| 5626 | } | 5670 | } |
| @@ -5838,10 +5882,13 @@ static int __init net_dev_init(void) | |||
| 5838 | for_each_possible_cpu(i) { | 5882 | for_each_possible_cpu(i) { |
| 5839 | struct softnet_data *sd = &per_cpu(softnet_data, i); | 5883 | struct softnet_data *sd = &per_cpu(softnet_data, i); |
| 5840 | 5884 | ||
| 5885 | memset(sd, 0, sizeof(*sd)); | ||
| 5841 | skb_queue_head_init(&sd->input_pkt_queue); | 5886 | skb_queue_head_init(&sd->input_pkt_queue); |
| 5887 | skb_queue_head_init(&sd->process_queue); | ||
| 5842 | sd->completion_queue = NULL; | 5888 | sd->completion_queue = NULL; |
| 5843 | INIT_LIST_HEAD(&sd->poll_list); | 5889 | INIT_LIST_HEAD(&sd->poll_list); |
| 5844 | 5890 | sd->output_queue = NULL; | |
| 5891 | sd->output_queue_tailp = &sd->output_queue; | ||
| 5845 | #ifdef CONFIG_RPS | 5892 | #ifdef CONFIG_RPS |
| 5846 | sd->csd.func = rps_trigger_softirq; | 5893 | sd->csd.func = rps_trigger_softirq; |
| 5847 | sd->csd.info = sd; | 5894 | sd->csd.info = sd; |
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 1bc66592453c..42e84e08a1be 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
| @@ -122,7 +122,7 @@ errout: | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | struct fib_rules_ops * | 124 | struct fib_rules_ops * |
| 125 | fib_rules_register(struct fib_rules_ops *tmpl, struct net *net) | 125 | fib_rules_register(const struct fib_rules_ops *tmpl, struct net *net) |
| 126 | { | 126 | { |
| 127 | struct fib_rules_ops *ops; | 127 | struct fib_rules_ops *ops; |
| 128 | int err; | 128 | int err; |
diff --git a/net/core/filter.c b/net/core/filter.c index ff943bed21af..da69fb728d32 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -302,6 +302,8 @@ load_b: | |||
| 302 | A = skb->pkt_type; | 302 | A = skb->pkt_type; |
| 303 | continue; | 303 | continue; |
| 304 | case SKF_AD_IFINDEX: | 304 | case SKF_AD_IFINDEX: |
| 305 | if (!skb->dev) | ||
| 306 | return 0; | ||
| 305 | A = skb->dev->ifindex; | 307 | A = skb->dev->ifindex; |
| 306 | continue; | 308 | continue; |
| 307 | case SKF_AD_MARK: | 309 | case SKF_AD_MARK: |
| @@ -310,6 +312,11 @@ load_b: | |||
| 310 | case SKF_AD_QUEUE: | 312 | case SKF_AD_QUEUE: |
| 311 | A = skb->queue_mapping; | 313 | A = skb->queue_mapping; |
| 312 | continue; | 314 | continue; |
| 315 | case SKF_AD_HATYPE: | ||
| 316 | if (!skb->dev) | ||
| 317 | return 0; | ||
| 318 | A = skb->dev->type; | ||
| 319 | continue; | ||
| 313 | case SKF_AD_NLATTR: { | 320 | case SKF_AD_NLATTR: { |
| 314 | struct nlattr *nla; | 321 | struct nlattr *nla; |
| 315 | 322 | ||
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index bd8c4712ea24..c988e685433a 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
| @@ -27,6 +27,51 @@ EXPORT_SYMBOL(init_net); | |||
| 27 | 27 | ||
| 28 | #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ | 28 | #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ |
| 29 | 29 | ||
| 30 | static void net_generic_release(struct rcu_head *rcu) | ||
| 31 | { | ||
| 32 | struct net_generic *ng; | ||
| 33 | |||
| 34 | ng = container_of(rcu, struct net_generic, rcu); | ||
| 35 | kfree(ng); | ||
| 36 | } | ||
| 37 | |||
| 38 | static int net_assign_generic(struct net *net, int id, void *data) | ||
| 39 | { | ||
| 40 | struct net_generic *ng, *old_ng; | ||
| 41 | |||
| 42 | BUG_ON(!mutex_is_locked(&net_mutex)); | ||
| 43 | BUG_ON(id == 0); | ||
| 44 | |||
| 45 | ng = old_ng = net->gen; | ||
| 46 | if (old_ng->len >= id) | ||
| 47 | goto assign; | ||
| 48 | |||
| 49 | ng = kzalloc(sizeof(struct net_generic) + | ||
| 50 | id * sizeof(void *), GFP_KERNEL); | ||
| 51 | if (ng == NULL) | ||
| 52 | return -ENOMEM; | ||
| 53 | |||
| 54 | /* | ||
| 55 | * Some synchronisation notes: | ||
| 56 | * | ||
| 57 | * The net_generic explores the net->gen array inside rcu | ||
| 58 | * read section. Besides once set the net->gen->ptr[x] | ||
| 59 | * pointer never changes (see rules in netns/generic.h). | ||
| 60 | * | ||
| 61 | * That said, we simply duplicate this array and schedule | ||
| 62 | * the old copy for kfree after a grace period. | ||
| 63 | */ | ||
| 64 | |||
| 65 | ng->len = id; | ||
| 66 | memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); | ||
| 67 | |||
| 68 | rcu_assign_pointer(net->gen, ng); | ||
| 69 | call_rcu(&old_ng->rcu, net_generic_release); | ||
| 70 | assign: | ||
| 71 | ng->ptr[id - 1] = data; | ||
| 72 | return 0; | ||
| 73 | } | ||
| 74 | |||
| 30 | static int ops_init(const struct pernet_operations *ops, struct net *net) | 75 | static int ops_init(const struct pernet_operations *ops, struct net *net) |
| 31 | { | 76 | { |
| 32 | int err; | 77 | int err; |
| @@ -469,10 +514,10 @@ EXPORT_SYMBOL_GPL(register_pernet_subsys); | |||
| 469 | * addition run the exit method for all existing network | 514 | * addition run the exit method for all existing network |
| 470 | * namespaces. | 515 | * namespaces. |
| 471 | */ | 516 | */ |
| 472 | void unregister_pernet_subsys(struct pernet_operations *module) | 517 | void unregister_pernet_subsys(struct pernet_operations *ops) |
| 473 | { | 518 | { |
| 474 | mutex_lock(&net_mutex); | 519 | mutex_lock(&net_mutex); |
| 475 | unregister_pernet_operations(module); | 520 | unregister_pernet_operations(ops); |
| 476 | mutex_unlock(&net_mutex); | 521 | mutex_unlock(&net_mutex); |
| 477 | } | 522 | } |
| 478 | EXPORT_SYMBOL_GPL(unregister_pernet_subsys); | 523 | EXPORT_SYMBOL_GPL(unregister_pernet_subsys); |
| @@ -526,49 +571,3 @@ void unregister_pernet_device(struct pernet_operations *ops) | |||
| 526 | mutex_unlock(&net_mutex); | 571 | mutex_unlock(&net_mutex); |
| 527 | } | 572 | } |
| 528 | EXPORT_SYMBOL_GPL(unregister_pernet_device); | 573 | EXPORT_SYMBOL_GPL(unregister_pernet_device); |
| 529 | |||
| 530 | static void net_generic_release(struct rcu_head *rcu) | ||
| 531 | { | ||
| 532 | struct net_generic *ng; | ||
| 533 | |||
| 534 | ng = container_of(rcu, struct net_generic, rcu); | ||
| 535 | kfree(ng); | ||
| 536 | } | ||
| 537 | |||
| 538 | int net_assign_generic(struct net *net, int id, void *data) | ||
| 539 | { | ||
| 540 | struct net_generic *ng, *old_ng; | ||
| 541 | |||
| 542 | BUG_ON(!mutex_is_locked(&net_mutex)); | ||
| 543 | BUG_ON(id == 0); | ||
| 544 | |||
| 545 | ng = old_ng = net->gen; | ||
| 546 | if (old_ng->len >= id) | ||
| 547 | goto assign; | ||
| 548 | |||
| 549 | ng = kzalloc(sizeof(struct net_generic) + | ||
| 550 | id * sizeof(void *), GFP_KERNEL); | ||
| 551 | if (ng == NULL) | ||
| 552 | return -ENOMEM; | ||
| 553 | |||
| 554 | /* | ||
| 555 | * Some synchronisation notes: | ||
| 556 | * | ||
| 557 | * The net_generic explores the net->gen array inside rcu | ||
| 558 | * read section. Besides once set the net->gen->ptr[x] | ||
| 559 | * pointer never changes (see rules in netns/generic.h). | ||
| 560 | * | ||
| 561 | * That said, we simply duplicate this array and schedule | ||
| 562 | * the old copy for kfree after a grace period. | ||
| 563 | */ | ||
| 564 | |||
| 565 | ng->len = id; | ||
| 566 | memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); | ||
| 567 | |||
| 568 | rcu_assign_pointer(net->gen, ng); | ||
| 569 | call_rcu(&old_ng->rcu, net_generic_release); | ||
| 570 | assign: | ||
| 571 | ng->ptr[id - 1] = data; | ||
| 572 | return 0; | ||
| 573 | } | ||
| 574 | EXPORT_SYMBOL_GPL(net_assign_generic); | ||
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index a58f59b97597..94825b109551 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -179,9 +179,8 @@ static void service_arp_queue(struct netpoll_info *npi) | |||
| 179 | } | 179 | } |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | void netpoll_poll(struct netpoll *np) | 182 | void netpoll_poll_dev(struct net_device *dev) |
| 183 | { | 183 | { |
| 184 | struct net_device *dev = np->dev; | ||
| 185 | const struct net_device_ops *ops; | 184 | const struct net_device_ops *ops; |
| 186 | 185 | ||
| 187 | if (!dev || !netif_running(dev)) | 186 | if (!dev || !netif_running(dev)) |
| @@ -201,6 +200,11 @@ void netpoll_poll(struct netpoll *np) | |||
| 201 | zap_completion_queue(); | 200 | zap_completion_queue(); |
| 202 | } | 201 | } |
| 203 | 202 | ||
| 203 | void netpoll_poll(struct netpoll *np) | ||
| 204 | { | ||
| 205 | netpoll_poll_dev(np->dev); | ||
| 206 | } | ||
| 207 | |||
| 204 | static void refill_skbs(void) | 208 | static void refill_skbs(void) |
| 205 | { | 209 | { |
| 206 | struct sk_buff *skb; | 210 | struct sk_buff *skb; |
| @@ -282,7 +286,7 @@ static int netpoll_owner_active(struct net_device *dev) | |||
| 282 | return 0; | 286 | return 0; |
| 283 | } | 287 | } |
| 284 | 288 | ||
| 285 | static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | 289 | void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) |
| 286 | { | 290 | { |
| 287 | int status = NETDEV_TX_BUSY; | 291 | int status = NETDEV_TX_BUSY; |
| 288 | unsigned long tries; | 292 | unsigned long tries; |
| @@ -308,7 +312,9 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | |||
| 308 | tries > 0; --tries) { | 312 | tries > 0; --tries) { |
| 309 | if (__netif_tx_trylock(txq)) { | 313 | if (__netif_tx_trylock(txq)) { |
| 310 | if (!netif_tx_queue_stopped(txq)) { | 314 | if (!netif_tx_queue_stopped(txq)) { |
| 315 | dev->priv_flags |= IFF_IN_NETPOLL; | ||
| 311 | status = ops->ndo_start_xmit(skb, dev); | 316 | status = ops->ndo_start_xmit(skb, dev); |
| 317 | dev->priv_flags &= ~IFF_IN_NETPOLL; | ||
| 312 | if (status == NETDEV_TX_OK) | 318 | if (status == NETDEV_TX_OK) |
| 313 | txq_trans_update(txq); | 319 | txq_trans_update(txq); |
| 314 | } | 320 | } |
| @@ -756,7 +762,10 @@ int netpoll_setup(struct netpoll *np) | |||
| 756 | atomic_inc(&npinfo->refcnt); | 762 | atomic_inc(&npinfo->refcnt); |
| 757 | } | 763 | } |
| 758 | 764 | ||
| 759 | if (!ndev->netdev_ops->ndo_poll_controller) { | 765 | npinfo->netpoll = np; |
| 766 | |||
| 767 | if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) || | ||
| 768 | !ndev->netdev_ops->ndo_poll_controller) { | ||
| 760 | printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", | 769 | printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", |
| 761 | np->name, np->dev_name); | 770 | np->name, np->dev_name); |
| 762 | err = -ENOTSUPP; | 771 | err = -ENOTSUPP; |
| @@ -878,6 +887,7 @@ void netpoll_cleanup(struct netpoll *np) | |||
| 878 | } | 887 | } |
| 879 | 888 | ||
| 880 | if (atomic_dec_and_test(&npinfo->refcnt)) { | 889 | if (atomic_dec_and_test(&npinfo->refcnt)) { |
| 890 | const struct net_device_ops *ops; | ||
| 881 | skb_queue_purge(&npinfo->arp_tx); | 891 | skb_queue_purge(&npinfo->arp_tx); |
| 882 | skb_queue_purge(&npinfo->txq); | 892 | skb_queue_purge(&npinfo->txq); |
| 883 | cancel_rearming_delayed_work(&npinfo->tx_work); | 893 | cancel_rearming_delayed_work(&npinfo->tx_work); |
| @@ -885,7 +895,11 @@ void netpoll_cleanup(struct netpoll *np) | |||
| 885 | /* clean after last, unfinished work */ | 895 | /* clean after last, unfinished work */ |
| 886 | __skb_queue_purge(&npinfo->txq); | 896 | __skb_queue_purge(&npinfo->txq); |
| 887 | kfree(npinfo); | 897 | kfree(npinfo); |
| 888 | np->dev->npinfo = NULL; | 898 | ops = np->dev->netdev_ops; |
| 899 | if (ops->ndo_netpoll_cleanup) | ||
| 900 | ops->ndo_netpoll_cleanup(np->dev); | ||
| 901 | else | ||
| 902 | np->dev->npinfo = NULL; | ||
| 889 | } | 903 | } |
| 890 | } | 904 | } |
| 891 | 905 | ||
| @@ -908,6 +922,7 @@ void netpoll_set_trap(int trap) | |||
| 908 | atomic_dec(&trapped); | 922 | atomic_dec(&trapped); |
| 909 | } | 923 | } |
| 910 | 924 | ||
| 925 | EXPORT_SYMBOL(netpoll_send_skb); | ||
| 911 | EXPORT_SYMBOL(netpoll_set_trap); | 926 | EXPORT_SYMBOL(netpoll_set_trap); |
| 912 | EXPORT_SYMBOL(netpoll_trap); | 927 | EXPORT_SYMBOL(netpoll_trap); |
| 913 | EXPORT_SYMBOL(netpoll_print_options); | 928 | EXPORT_SYMBOL(netpoll_print_options); |
| @@ -915,4 +930,5 @@ EXPORT_SYMBOL(netpoll_parse_options); | |||
| 915 | EXPORT_SYMBOL(netpoll_setup); | 930 | EXPORT_SYMBOL(netpoll_setup); |
| 916 | EXPORT_SYMBOL(netpoll_cleanup); | 931 | EXPORT_SYMBOL(netpoll_cleanup); |
| 917 | EXPORT_SYMBOL(netpoll_send_udp); | 932 | EXPORT_SYMBOL(netpoll_send_udp); |
| 933 | EXPORT_SYMBOL(netpoll_poll_dev); | ||
| 918 | EXPORT_SYMBOL(netpoll_poll); | 934 | EXPORT_SYMBOL(netpoll_poll); |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 78c85985cb30..23a71cb21273 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -98,7 +98,7 @@ int lockdep_rtnl_is_held(void) | |||
| 98 | EXPORT_SYMBOL(lockdep_rtnl_is_held); | 98 | EXPORT_SYMBOL(lockdep_rtnl_is_held); |
| 99 | #endif /* #ifdef CONFIG_PROVE_LOCKING */ | 99 | #endif /* #ifdef CONFIG_PROVE_LOCKING */ |
| 100 | 100 | ||
| 101 | static struct rtnl_link *rtnl_msg_handlers[NPROTO]; | 101 | static struct rtnl_link *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1]; |
| 102 | 102 | ||
| 103 | static inline int rtm_msgindex(int msgtype) | 103 | static inline int rtm_msgindex(int msgtype) |
| 104 | { | 104 | { |
| @@ -118,7 +118,7 @@ static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex) | |||
| 118 | { | 118 | { |
| 119 | struct rtnl_link *tab; | 119 | struct rtnl_link *tab; |
| 120 | 120 | ||
| 121 | if (protocol < NPROTO) | 121 | if (protocol <= RTNL_FAMILY_MAX) |
| 122 | tab = rtnl_msg_handlers[protocol]; | 122 | tab = rtnl_msg_handlers[protocol]; |
| 123 | else | 123 | else |
| 124 | tab = NULL; | 124 | tab = NULL; |
| @@ -133,7 +133,7 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex) | |||
| 133 | { | 133 | { |
| 134 | struct rtnl_link *tab; | 134 | struct rtnl_link *tab; |
| 135 | 135 | ||
| 136 | if (protocol < NPROTO) | 136 | if (protocol <= RTNL_FAMILY_MAX) |
| 137 | tab = rtnl_msg_handlers[protocol]; | 137 | tab = rtnl_msg_handlers[protocol]; |
| 138 | else | 138 | else |
| 139 | tab = NULL; | 139 | tab = NULL; |
| @@ -167,7 +167,7 @@ int __rtnl_register(int protocol, int msgtype, | |||
| 167 | struct rtnl_link *tab; | 167 | struct rtnl_link *tab; |
| 168 | int msgindex; | 168 | int msgindex; |
| 169 | 169 | ||
| 170 | BUG_ON(protocol < 0 || protocol >= NPROTO); | 170 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
| 171 | msgindex = rtm_msgindex(msgtype); | 171 | msgindex = rtm_msgindex(msgtype); |
| 172 | 172 | ||
| 173 | tab = rtnl_msg_handlers[protocol]; | 173 | tab = rtnl_msg_handlers[protocol]; |
| @@ -219,7 +219,7 @@ int rtnl_unregister(int protocol, int msgtype) | |||
| 219 | { | 219 | { |
| 220 | int msgindex; | 220 | int msgindex; |
| 221 | 221 | ||
| 222 | BUG_ON(protocol < 0 || protocol >= NPROTO); | 222 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
| 223 | msgindex = rtm_msgindex(msgtype); | 223 | msgindex = rtm_msgindex(msgtype); |
| 224 | 224 | ||
| 225 | if (rtnl_msg_handlers[protocol] == NULL) | 225 | if (rtnl_msg_handlers[protocol] == NULL) |
| @@ -241,7 +241,7 @@ EXPORT_SYMBOL_GPL(rtnl_unregister); | |||
| 241 | */ | 241 | */ |
| 242 | void rtnl_unregister_all(int protocol) | 242 | void rtnl_unregister_all(int protocol) |
| 243 | { | 243 | { |
| 244 | BUG_ON(protocol < 0 || protocol >= NPROTO); | 244 | BUG_ON(protocol < 0 || protocol > RTNL_FAMILY_MAX); |
| 245 | 245 | ||
| 246 | kfree(rtnl_msg_handlers[protocol]); | 246 | kfree(rtnl_msg_handlers[protocol]); |
| 247 | rtnl_msg_handlers[protocol] = NULL; | 247 | rtnl_msg_handlers[protocol] = NULL; |
| @@ -1319,10 +1319,11 @@ replay: | |||
| 1319 | err = ops->newlink(net, dev, tb, data); | 1319 | err = ops->newlink(net, dev, tb, data); |
| 1320 | else | 1320 | else |
| 1321 | err = register_netdevice(dev); | 1321 | err = register_netdevice(dev); |
| 1322 | if (err < 0 && !IS_ERR(dev)) { | 1322 | |
| 1323 | if (err < 0 && !IS_ERR(dev)) | ||
| 1323 | free_netdev(dev); | 1324 | free_netdev(dev); |
| 1325 | if (err < 0) | ||
| 1324 | goto out; | 1326 | goto out; |
| 1325 | } | ||
| 1326 | 1327 | ||
| 1327 | err = rtnl_configure_link(dev, ifm); | 1328 | err = rtnl_configure_link(dev, ifm); |
| 1328 | if (err < 0) | 1329 | if (err < 0) |
| @@ -1384,7 +1385,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1384 | 1385 | ||
| 1385 | if (s_idx == 0) | 1386 | if (s_idx == 0) |
| 1386 | s_idx = 1; | 1387 | s_idx = 1; |
| 1387 | for (idx = 1; idx < NPROTO; idx++) { | 1388 | for (idx = 1; idx <= RTNL_FAMILY_MAX; idx++) { |
| 1388 | int type = cb->nlh->nlmsg_type-RTM_BASE; | 1389 | int type = cb->nlh->nlmsg_type-RTM_BASE; |
| 1389 | if (idx < s_idx || idx == PF_PACKET) | 1390 | if (idx < s_idx || idx == PF_PACKET) |
| 1390 | continue; | 1391 | continue; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index bdea0efdf8cb..a9b0e1f77806 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -117,7 +117,7 @@ static const struct pipe_buf_operations sock_pipe_buf_ops = { | |||
| 117 | * | 117 | * |
| 118 | * Out of line support code for skb_put(). Not user callable. | 118 | * Out of line support code for skb_put(). Not user callable. |
| 119 | */ | 119 | */ |
| 120 | void skb_over_panic(struct sk_buff *skb, int sz, void *here) | 120 | static void skb_over_panic(struct sk_buff *skb, int sz, void *here) |
| 121 | { | 121 | { |
| 122 | printk(KERN_EMERG "skb_over_panic: text:%p len:%d put:%d head:%p " | 122 | printk(KERN_EMERG "skb_over_panic: text:%p len:%d put:%d head:%p " |
| 123 | "data:%p tail:%#lx end:%#lx dev:%s\n", | 123 | "data:%p tail:%#lx end:%#lx dev:%s\n", |
| @@ -126,7 +126,6 @@ void skb_over_panic(struct sk_buff *skb, int sz, void *here) | |||
| 126 | skb->dev ? skb->dev->name : "<NULL>"); | 126 | skb->dev ? skb->dev->name : "<NULL>"); |
| 127 | BUG(); | 127 | BUG(); |
| 128 | } | 128 | } |
| 129 | EXPORT_SYMBOL(skb_over_panic); | ||
| 130 | 129 | ||
| 131 | /** | 130 | /** |
| 132 | * skb_under_panic - private function | 131 | * skb_under_panic - private function |
| @@ -137,7 +136,7 @@ EXPORT_SYMBOL(skb_over_panic); | |||
| 137 | * Out of line support code for skb_push(). Not user callable. | 136 | * Out of line support code for skb_push(). Not user callable. |
| 138 | */ | 137 | */ |
| 139 | 138 | ||
| 140 | void skb_under_panic(struct sk_buff *skb, int sz, void *here) | 139 | static void skb_under_panic(struct sk_buff *skb, int sz, void *here) |
| 141 | { | 140 | { |
| 142 | printk(KERN_EMERG "skb_under_panic: text:%p len:%d put:%d head:%p " | 141 | printk(KERN_EMERG "skb_under_panic: text:%p len:%d put:%d head:%p " |
| 143 | "data:%p tail:%#lx end:%#lx dev:%s\n", | 142 | "data:%p tail:%#lx end:%#lx dev:%s\n", |
| @@ -146,7 +145,6 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here) | |||
| 146 | skb->dev ? skb->dev->name : "<NULL>"); | 145 | skb->dev ? skb->dev->name : "<NULL>"); |
| 147 | BUG(); | 146 | BUG(); |
| 148 | } | 147 | } |
| 149 | EXPORT_SYMBOL(skb_under_panic); | ||
| 150 | 148 | ||
| 151 | /* Allocate a new skbuff. We do this ourselves so we can fill in a few | 149 | /* Allocate a new skbuff. We do this ourselves so we can fill in a few |
| 152 | * 'private' fields and also do memory statistics to find all the | 150 | * 'private' fields and also do memory statistics to find all the |
| @@ -183,12 +181,14 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, | |||
| 183 | skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node); | 181 | skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node); |
| 184 | if (!skb) | 182 | if (!skb) |
| 185 | goto out; | 183 | goto out; |
| 184 | prefetchw(skb); | ||
| 186 | 185 | ||
| 187 | size = SKB_DATA_ALIGN(size); | 186 | size = SKB_DATA_ALIGN(size); |
| 188 | data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info), | 187 | data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info), |
| 189 | gfp_mask, node); | 188 | gfp_mask, node); |
| 190 | if (!data) | 189 | if (!data) |
| 191 | goto nodata; | 190 | goto nodata; |
| 191 | prefetchw(data + size); | ||
| 192 | 192 | ||
| 193 | /* | 193 | /* |
| 194 | * Only clear those fields we need to clear, not those that we will | 194 | * Only clear those fields we need to clear, not those that we will |
| @@ -210,15 +210,8 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, | |||
| 210 | 210 | ||
| 211 | /* make sure we initialize shinfo sequentially */ | 211 | /* make sure we initialize shinfo sequentially */ |
| 212 | shinfo = skb_shinfo(skb); | 212 | shinfo = skb_shinfo(skb); |
| 213 | memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); | ||
| 213 | atomic_set(&shinfo->dataref, 1); | 214 | atomic_set(&shinfo->dataref, 1); |
| 214 | shinfo->nr_frags = 0; | ||
| 215 | shinfo->gso_size = 0; | ||
| 216 | shinfo->gso_segs = 0; | ||
| 217 | shinfo->gso_type = 0; | ||
| 218 | shinfo->ip6_frag_id = 0; | ||
| 219 | shinfo->tx_flags.flags = 0; | ||
| 220 | skb_frag_list_init(skb); | ||
| 221 | memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps)); | ||
| 222 | 215 | ||
| 223 | if (fclone) { | 216 | if (fclone) { |
| 224 | struct sk_buff *child = skb + 1; | 217 | struct sk_buff *child = skb + 1; |
| @@ -507,16 +500,10 @@ int skb_recycle_check(struct sk_buff *skb, int skb_size) | |||
| 507 | return 0; | 500 | return 0; |
| 508 | 501 | ||
| 509 | skb_release_head_state(skb); | 502 | skb_release_head_state(skb); |
| 503 | |||
| 510 | shinfo = skb_shinfo(skb); | 504 | shinfo = skb_shinfo(skb); |
| 505 | memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); | ||
| 511 | atomic_set(&shinfo->dataref, 1); | 506 | atomic_set(&shinfo->dataref, 1); |
| 512 | shinfo->nr_frags = 0; | ||
| 513 | shinfo->gso_size = 0; | ||
| 514 | shinfo->gso_segs = 0; | ||
| 515 | shinfo->gso_type = 0; | ||
| 516 | shinfo->ip6_frag_id = 0; | ||
| 517 | shinfo->tx_flags.flags = 0; | ||
| 518 | skb_frag_list_init(skb); | ||
| 519 | memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps)); | ||
| 520 | 507 | ||
| 521 | memset(skb, 0, offsetof(struct sk_buff, tail)); | 508 | memset(skb, 0, offsetof(struct sk_buff, tail)); |
| 522 | skb->data = skb->head + NET_SKB_PAD; | 509 | skb->data = skb->head + NET_SKB_PAD; |
| @@ -1053,7 +1040,7 @@ EXPORT_SYMBOL(skb_push); | |||
| 1053 | */ | 1040 | */ |
| 1054 | unsigned char *skb_pull(struct sk_buff *skb, unsigned int len) | 1041 | unsigned char *skb_pull(struct sk_buff *skb, unsigned int len) |
| 1055 | { | 1042 | { |
| 1056 | return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len); | 1043 | return skb_pull_inline(skb, len); |
| 1057 | } | 1044 | } |
| 1058 | EXPORT_SYMBOL(skb_pull); | 1045 | EXPORT_SYMBOL(skb_pull); |
| 1059 | 1046 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 7effa1e689df..94c4affdda9b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -327,6 +327,10 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested) | |||
| 327 | 327 | ||
| 328 | skb->dev = NULL; | 328 | skb->dev = NULL; |
| 329 | 329 | ||
| 330 | if (sk_rcvqueues_full(sk, skb)) { | ||
| 331 | atomic_inc(&sk->sk_drops); | ||
| 332 | goto discard_and_relse; | ||
| 333 | } | ||
| 330 | if (nested) | 334 | if (nested) |
| 331 | bh_lock_sock_nested(sk); | 335 | bh_lock_sock_nested(sk); |
| 332 | else | 336 | else |
| @@ -1207,7 +1211,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
| 1207 | */ | 1211 | */ |
| 1208 | sk_refcnt_debug_inc(newsk); | 1212 | sk_refcnt_debug_inc(newsk); |
| 1209 | sk_set_socket(newsk, NULL); | 1213 | sk_set_socket(newsk, NULL); |
| 1210 | newsk->sk_sleep = NULL; | 1214 | newsk->sk_wq = NULL; |
| 1211 | 1215 | ||
| 1212 | if (newsk->sk_prot->sockets_allocated) | 1216 | if (newsk->sk_prot->sockets_allocated) |
| 1213 | percpu_counter_inc(newsk->sk_prot->sockets_allocated); | 1217 | percpu_counter_inc(newsk->sk_prot->sockets_allocated); |
| @@ -1395,7 +1399,7 @@ static long sock_wait_for_wmem(struct sock *sk, long timeo) | |||
| 1395 | if (signal_pending(current)) | 1399 | if (signal_pending(current)) |
| 1396 | break; | 1400 | break; |
| 1397 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | 1401 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); |
| 1398 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1402 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 1399 | if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) | 1403 | if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) |
| 1400 | break; | 1404 | break; |
| 1401 | if (sk->sk_shutdown & SEND_SHUTDOWN) | 1405 | if (sk->sk_shutdown & SEND_SHUTDOWN) |
| @@ -1404,7 +1408,7 @@ static long sock_wait_for_wmem(struct sock *sk, long timeo) | |||
| 1404 | break; | 1408 | break; |
| 1405 | timeo = schedule_timeout(timeo); | 1409 | timeo = schedule_timeout(timeo); |
| 1406 | } | 1410 | } |
| 1407 | finish_wait(sk->sk_sleep, &wait); | 1411 | finish_wait(sk_sleep(sk), &wait); |
| 1408 | return timeo; | 1412 | return timeo; |
| 1409 | } | 1413 | } |
| 1410 | 1414 | ||
| @@ -1570,11 +1574,11 @@ int sk_wait_data(struct sock *sk, long *timeo) | |||
| 1570 | int rc; | 1574 | int rc; |
| 1571 | DEFINE_WAIT(wait); | 1575 | DEFINE_WAIT(wait); |
| 1572 | 1576 | ||
| 1573 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1577 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 1574 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1578 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
| 1575 | rc = sk_wait_event(sk, timeo, !skb_queue_empty(&sk->sk_receive_queue)); | 1579 | rc = sk_wait_event(sk, timeo, !skb_queue_empty(&sk->sk_receive_queue)); |
| 1576 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1580 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
| 1577 | finish_wait(sk->sk_sleep, &wait); | 1581 | finish_wait(sk_sleep(sk), &wait); |
| 1578 | return rc; | 1582 | return rc; |
| 1579 | } | 1583 | } |
| 1580 | EXPORT_SYMBOL(sk_wait_data); | 1584 | EXPORT_SYMBOL(sk_wait_data); |
| @@ -1796,41 +1800,53 @@ EXPORT_SYMBOL(sock_no_sendpage); | |||
| 1796 | 1800 | ||
| 1797 | static void sock_def_wakeup(struct sock *sk) | 1801 | static void sock_def_wakeup(struct sock *sk) |
| 1798 | { | 1802 | { |
| 1799 | read_lock(&sk->sk_callback_lock); | 1803 | struct socket_wq *wq; |
| 1800 | if (sk_has_sleeper(sk)) | 1804 | |
| 1801 | wake_up_interruptible_all(sk->sk_sleep); | 1805 | rcu_read_lock(); |
| 1802 | read_unlock(&sk->sk_callback_lock); | 1806 | wq = rcu_dereference(sk->sk_wq); |
| 1807 | if (wq_has_sleeper(wq)) | ||
| 1808 | wake_up_interruptible_all(&wq->wait); | ||
| 1809 | rcu_read_unlock(); | ||
| 1803 | } | 1810 | } |
| 1804 | 1811 | ||
| 1805 | static void sock_def_error_report(struct sock *sk) | 1812 | static void sock_def_error_report(struct sock *sk) |
| 1806 | { | 1813 | { |
| 1807 | read_lock(&sk->sk_callback_lock); | 1814 | struct socket_wq *wq; |
| 1808 | if (sk_has_sleeper(sk)) | 1815 | |
| 1809 | wake_up_interruptible_poll(sk->sk_sleep, POLLERR); | 1816 | rcu_read_lock(); |
| 1817 | wq = rcu_dereference(sk->sk_wq); | ||
| 1818 | if (wq_has_sleeper(wq)) | ||
| 1819 | wake_up_interruptible_poll(&wq->wait, POLLERR); | ||
| 1810 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); | 1820 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); |
| 1811 | read_unlock(&sk->sk_callback_lock); | 1821 | rcu_read_unlock(); |
| 1812 | } | 1822 | } |
| 1813 | 1823 | ||
| 1814 | static void sock_def_readable(struct sock *sk, int len) | 1824 | static void sock_def_readable(struct sock *sk, int len) |
| 1815 | { | 1825 | { |
| 1816 | read_lock(&sk->sk_callback_lock); | 1826 | struct socket_wq *wq; |
| 1817 | if (sk_has_sleeper(sk)) | 1827 | |
| 1818 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN | | 1828 | rcu_read_lock(); |
| 1829 | wq = rcu_dereference(sk->sk_wq); | ||
| 1830 | if (wq_has_sleeper(wq)) | ||
| 1831 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | | ||
| 1819 | POLLRDNORM | POLLRDBAND); | 1832 | POLLRDNORM | POLLRDBAND); |
| 1820 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); | 1833 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); |
| 1821 | read_unlock(&sk->sk_callback_lock); | 1834 | rcu_read_unlock(); |
| 1822 | } | 1835 | } |
| 1823 | 1836 | ||
| 1824 | static void sock_def_write_space(struct sock *sk) | 1837 | static void sock_def_write_space(struct sock *sk) |
| 1825 | { | 1838 | { |
| 1826 | read_lock(&sk->sk_callback_lock); | 1839 | struct socket_wq *wq; |
| 1840 | |||
| 1841 | rcu_read_lock(); | ||
| 1827 | 1842 | ||
| 1828 | /* Do not wake up a writer until he can make "significant" | 1843 | /* Do not wake up a writer until he can make "significant" |
| 1829 | * progress. --DaveM | 1844 | * progress. --DaveM |
| 1830 | */ | 1845 | */ |
| 1831 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { | 1846 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { |
| 1832 | if (sk_has_sleeper(sk)) | 1847 | wq = rcu_dereference(sk->sk_wq); |
| 1833 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT | | 1848 | if (wq_has_sleeper(wq)) |
| 1849 | wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | | ||
| 1834 | POLLWRNORM | POLLWRBAND); | 1850 | POLLWRNORM | POLLWRBAND); |
| 1835 | 1851 | ||
| 1836 | /* Should agree with poll, otherwise some programs break */ | 1852 | /* Should agree with poll, otherwise some programs break */ |
| @@ -1838,7 +1854,7 @@ static void sock_def_write_space(struct sock *sk) | |||
| 1838 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 1854 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
| 1839 | } | 1855 | } |
| 1840 | 1856 | ||
| 1841 | read_unlock(&sk->sk_callback_lock); | 1857 | rcu_read_unlock(); |
| 1842 | } | 1858 | } |
| 1843 | 1859 | ||
| 1844 | static void sock_def_destruct(struct sock *sk) | 1860 | static void sock_def_destruct(struct sock *sk) |
| @@ -1885,7 +1901,6 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
| 1885 | sk->sk_allocation = GFP_KERNEL; | 1901 | sk->sk_allocation = GFP_KERNEL; |
| 1886 | sk->sk_rcvbuf = sysctl_rmem_default; | 1902 | sk->sk_rcvbuf = sysctl_rmem_default; |
| 1887 | sk->sk_sndbuf = sysctl_wmem_default; | 1903 | sk->sk_sndbuf = sysctl_wmem_default; |
| 1888 | sk->sk_backlog.limit = sk->sk_rcvbuf << 1; | ||
| 1889 | sk->sk_state = TCP_CLOSE; | 1904 | sk->sk_state = TCP_CLOSE; |
| 1890 | sk_set_socket(sk, sock); | 1905 | sk_set_socket(sk, sock); |
| 1891 | 1906 | ||
| @@ -1893,10 +1908,10 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
| 1893 | 1908 | ||
| 1894 | if (sock) { | 1909 | if (sock) { |
| 1895 | sk->sk_type = sock->type; | 1910 | sk->sk_type = sock->type; |
| 1896 | sk->sk_sleep = &sock->wait; | 1911 | sk->sk_wq = sock->wq; |
| 1897 | sock->sk = sk; | 1912 | sock->sk = sk; |
| 1898 | } else | 1913 | } else |
| 1899 | sk->sk_sleep = NULL; | 1914 | sk->sk_wq = NULL; |
| 1900 | 1915 | ||
| 1901 | spin_lock_init(&sk->sk_dst_lock); | 1916 | spin_lock_init(&sk->sk_dst_lock); |
| 1902 | rwlock_init(&sk->sk_callback_lock); | 1917 | rwlock_init(&sk->sk_callback_lock); |
diff --git a/net/core/stream.c b/net/core/stream.c index a37debfeb1b2..cc196f42b8d8 100644 --- a/net/core/stream.c +++ b/net/core/stream.c | |||
| @@ -28,15 +28,19 @@ | |||
| 28 | void sk_stream_write_space(struct sock *sk) | 28 | void sk_stream_write_space(struct sock *sk) |
| 29 | { | 29 | { |
| 30 | struct socket *sock = sk->sk_socket; | 30 | struct socket *sock = sk->sk_socket; |
| 31 | struct socket_wq *wq; | ||
| 31 | 32 | ||
| 32 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock) { | 33 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock) { |
| 33 | clear_bit(SOCK_NOSPACE, &sock->flags); | 34 | clear_bit(SOCK_NOSPACE, &sock->flags); |
| 34 | 35 | ||
| 35 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 36 | rcu_read_lock(); |
| 36 | wake_up_interruptible_poll(sk->sk_sleep, POLLOUT | | 37 | wq = rcu_dereference(sk->sk_wq); |
| 38 | if (wq_has_sleeper(wq)) | ||
| 39 | wake_up_interruptible_poll(&wq->wait, POLLOUT | | ||
| 37 | POLLWRNORM | POLLWRBAND); | 40 | POLLWRNORM | POLLWRBAND); |
| 38 | if (sock->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN)) | 41 | if (wq && wq->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN)) |
| 39 | sock_wake_async(sock, SOCK_WAKE_SPACE, POLL_OUT); | 42 | sock_wake_async(sock, SOCK_WAKE_SPACE, POLL_OUT); |
| 43 | rcu_read_unlock(); | ||
| 40 | } | 44 | } |
| 41 | } | 45 | } |
| 42 | 46 | ||
| @@ -66,13 +70,13 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p) | |||
| 66 | if (signal_pending(tsk)) | 70 | if (signal_pending(tsk)) |
| 67 | return sock_intr_errno(*timeo_p); | 71 | return sock_intr_errno(*timeo_p); |
| 68 | 72 | ||
| 69 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 73 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 70 | sk->sk_write_pending++; | 74 | sk->sk_write_pending++; |
| 71 | done = sk_wait_event(sk, timeo_p, | 75 | done = sk_wait_event(sk, timeo_p, |
| 72 | !sk->sk_err && | 76 | !sk->sk_err && |
| 73 | !((1 << sk->sk_state) & | 77 | !((1 << sk->sk_state) & |
| 74 | ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))); | 78 | ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))); |
| 75 | finish_wait(sk->sk_sleep, &wait); | 79 | finish_wait(sk_sleep(sk), &wait); |
| 76 | sk->sk_write_pending--; | 80 | sk->sk_write_pending--; |
| 77 | } while (!done); | 81 | } while (!done); |
| 78 | return 0; | 82 | return 0; |
| @@ -96,13 +100,13 @@ void sk_stream_wait_close(struct sock *sk, long timeout) | |||
| 96 | DEFINE_WAIT(wait); | 100 | DEFINE_WAIT(wait); |
| 97 | 101 | ||
| 98 | do { | 102 | do { |
| 99 | prepare_to_wait(sk->sk_sleep, &wait, | 103 | prepare_to_wait(sk_sleep(sk), &wait, |
| 100 | TASK_INTERRUPTIBLE); | 104 | TASK_INTERRUPTIBLE); |
| 101 | if (sk_wait_event(sk, &timeout, !sk_stream_closing(sk))) | 105 | if (sk_wait_event(sk, &timeout, !sk_stream_closing(sk))) |
| 102 | break; | 106 | break; |
| 103 | } while (!signal_pending(current) && timeout); | 107 | } while (!signal_pending(current) && timeout); |
| 104 | 108 | ||
| 105 | finish_wait(sk->sk_sleep, &wait); | 109 | finish_wait(sk_sleep(sk), &wait); |
| 106 | } | 110 | } |
| 107 | } | 111 | } |
| 108 | 112 | ||
| @@ -126,7 +130,7 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) | |||
| 126 | while (1) { | 130 | while (1) { |
| 127 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 131 | set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); |
| 128 | 132 | ||
| 129 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 133 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 130 | 134 | ||
| 131 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | 135 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) |
| 132 | goto do_error; | 136 | goto do_error; |
| @@ -157,7 +161,7 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) | |||
| 157 | *timeo_p = current_timeo; | 161 | *timeo_p = current_timeo; |
| 158 | } | 162 | } |
| 159 | out: | 163 | out: |
| 160 | finish_wait(sk->sk_sleep, &wait); | 164 | finish_wait(sk_sleep(sk), &wait); |
| 161 | return err; | 165 | return err; |
| 162 | 166 | ||
| 163 | do_error: | 167 | do_error: |
diff --git a/net/dccp/output.c b/net/dccp/output.c index e98b65e9569f..aadbdb58758b 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
| @@ -195,15 +195,17 @@ EXPORT_SYMBOL_GPL(dccp_sync_mss); | |||
| 195 | 195 | ||
| 196 | void dccp_write_space(struct sock *sk) | 196 | void dccp_write_space(struct sock *sk) |
| 197 | { | 197 | { |
| 198 | read_lock(&sk->sk_callback_lock); | 198 | struct socket_wq *wq; |
| 199 | 199 | ||
| 200 | if (sk_has_sleeper(sk)) | 200 | rcu_read_lock(); |
| 201 | wake_up_interruptible(sk->sk_sleep); | 201 | wq = rcu_dereference(sk->sk_wq); |
| 202 | if (wq_has_sleeper(wq)) | ||
| 203 | wake_up_interruptible(&wq->wait); | ||
| 202 | /* Should agree with poll, otherwise some programs break */ | 204 | /* Should agree with poll, otherwise some programs break */ |
| 203 | if (sock_writeable(sk)) | 205 | if (sock_writeable(sk)) |
| 204 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 206 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
| 205 | 207 | ||
| 206 | read_unlock(&sk->sk_callback_lock); | 208 | rcu_read_unlock(); |
| 207 | } | 209 | } |
| 208 | 210 | ||
| 209 | /** | 211 | /** |
| @@ -225,7 +227,7 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, int delay) | |||
| 225 | dccp_pr_debug("delayed send by %d msec\n", delay); | 227 | dccp_pr_debug("delayed send by %d msec\n", delay); |
| 226 | jiffdelay = msecs_to_jiffies(delay); | 228 | jiffdelay = msecs_to_jiffies(delay); |
| 227 | 229 | ||
| 228 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 230 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 229 | 231 | ||
| 230 | sk->sk_write_pending++; | 232 | sk->sk_write_pending++; |
| 231 | release_sock(sk); | 233 | release_sock(sk); |
| @@ -241,7 +243,7 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, int delay) | |||
| 241 | rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); | 243 | rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb); |
| 242 | } while ((delay = rc) > 0); | 244 | } while ((delay = rc) > 0); |
| 243 | out: | 245 | out: |
| 244 | finish_wait(sk->sk_sleep, &wait); | 246 | finish_wait(sk_sleep(sk), &wait); |
| 245 | return rc; | 247 | return rc; |
| 246 | 248 | ||
| 247 | do_error: | 249 | do_error: |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index a0e38d8018f5..b03ecf6b2bb0 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
| @@ -312,7 +312,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock, | |||
| 312 | unsigned int mask; | 312 | unsigned int mask; |
| 313 | struct sock *sk = sock->sk; | 313 | struct sock *sk = sock->sk; |
| 314 | 314 | ||
| 315 | sock_poll_wait(file, sk->sk_sleep, wait); | 315 | sock_poll_wait(file, sk_sleep(sk), wait); |
| 316 | if (sk->sk_state == DCCP_LISTEN) | 316 | if (sk->sk_state == DCCP_LISTEN) |
| 317 | return inet_csk_listen_poll(sk); | 317 | return inet_csk_listen_poll(sk); |
| 318 | 318 | ||
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 55e3b6b0061a..d6b93d19790f 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
| @@ -832,7 +832,7 @@ static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) | |||
| 832 | scp->segsize_loc = dst_metric(__sk_dst_get(sk), RTAX_ADVMSS); | 832 | scp->segsize_loc = dst_metric(__sk_dst_get(sk), RTAX_ADVMSS); |
| 833 | dn_send_conn_conf(sk, allocation); | 833 | dn_send_conn_conf(sk, allocation); |
| 834 | 834 | ||
| 835 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 835 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 836 | for(;;) { | 836 | for(;;) { |
| 837 | release_sock(sk); | 837 | release_sock(sk); |
| 838 | if (scp->state == DN_CC) | 838 | if (scp->state == DN_CC) |
| @@ -850,9 +850,9 @@ static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) | |||
| 850 | err = -EAGAIN; | 850 | err = -EAGAIN; |
| 851 | if (!*timeo) | 851 | if (!*timeo) |
| 852 | break; | 852 | break; |
| 853 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 853 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 854 | } | 854 | } |
| 855 | finish_wait(sk->sk_sleep, &wait); | 855 | finish_wait(sk_sleep(sk), &wait); |
| 856 | if (err == 0) { | 856 | if (err == 0) { |
| 857 | sk->sk_socket->state = SS_CONNECTED; | 857 | sk->sk_socket->state = SS_CONNECTED; |
| 858 | } else if (scp->state != DN_CC) { | 858 | } else if (scp->state != DN_CC) { |
| @@ -873,7 +873,7 @@ static int dn_wait_run(struct sock *sk, long *timeo) | |||
| 873 | if (!*timeo) | 873 | if (!*timeo) |
| 874 | return -EALREADY; | 874 | return -EALREADY; |
| 875 | 875 | ||
| 876 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 876 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 877 | for(;;) { | 877 | for(;;) { |
| 878 | release_sock(sk); | 878 | release_sock(sk); |
| 879 | if (scp->state == DN_CI || scp->state == DN_CC) | 879 | if (scp->state == DN_CI || scp->state == DN_CC) |
| @@ -891,9 +891,9 @@ static int dn_wait_run(struct sock *sk, long *timeo) | |||
| 891 | err = -ETIMEDOUT; | 891 | err = -ETIMEDOUT; |
| 892 | if (!*timeo) | 892 | if (!*timeo) |
| 893 | break; | 893 | break; |
| 894 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 894 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 895 | } | 895 | } |
| 896 | finish_wait(sk->sk_sleep, &wait); | 896 | finish_wait(sk_sleep(sk), &wait); |
| 897 | out: | 897 | out: |
| 898 | if (err == 0) { | 898 | if (err == 0) { |
| 899 | sk->sk_socket->state = SS_CONNECTED; | 899 | sk->sk_socket->state = SS_CONNECTED; |
| @@ -1040,7 +1040,7 @@ static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo) | |||
| 1040 | struct sk_buff *skb = NULL; | 1040 | struct sk_buff *skb = NULL; |
| 1041 | int err = 0; | 1041 | int err = 0; |
| 1042 | 1042 | ||
| 1043 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1043 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 1044 | for(;;) { | 1044 | for(;;) { |
| 1045 | release_sock(sk); | 1045 | release_sock(sk); |
| 1046 | skb = skb_dequeue(&sk->sk_receive_queue); | 1046 | skb = skb_dequeue(&sk->sk_receive_queue); |
| @@ -1060,9 +1060,9 @@ static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo) | |||
| 1060 | err = -EAGAIN; | 1060 | err = -EAGAIN; |
| 1061 | if (!*timeo) | 1061 | if (!*timeo) |
| 1062 | break; | 1062 | break; |
| 1063 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1063 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 1064 | } | 1064 | } |
| 1065 | finish_wait(sk->sk_sleep, &wait); | 1065 | finish_wait(sk_sleep(sk), &wait); |
| 1066 | 1066 | ||
| 1067 | return skb == NULL ? ERR_PTR(err) : skb; | 1067 | return skb == NULL ? ERR_PTR(err) : skb; |
| 1068 | } | 1068 | } |
| @@ -1746,11 +1746,11 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1746 | goto out; | 1746 | goto out; |
| 1747 | } | 1747 | } |
| 1748 | 1748 | ||
| 1749 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1749 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 1750 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1750 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
| 1751 | sk_wait_event(sk, &timeo, dn_data_ready(sk, queue, flags, target)); | 1751 | sk_wait_event(sk, &timeo, dn_data_ready(sk, queue, flags, target)); |
| 1752 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1752 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
| 1753 | finish_wait(sk->sk_sleep, &wait); | 1753 | finish_wait(sk_sleep(sk), &wait); |
| 1754 | } | 1754 | } |
| 1755 | 1755 | ||
| 1756 | skb_queue_walk_safe(queue, skb, n) { | 1756 | skb_queue_walk_safe(queue, skb, n) { |
| @@ -2003,12 +2003,12 @@ static int dn_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 2003 | goto out; | 2003 | goto out; |
| 2004 | } | 2004 | } |
| 2005 | 2005 | ||
| 2006 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 2006 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 2007 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 2007 | set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
| 2008 | sk_wait_event(sk, &timeo, | 2008 | sk_wait_event(sk, &timeo, |
| 2009 | !dn_queue_too_long(scp, queue, flags)); | 2009 | !dn_queue_too_long(scp, queue, flags)); |
| 2010 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 2010 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
| 2011 | finish_wait(sk->sk_sleep, &wait); | 2011 | finish_wait(sk_sleep(sk), &wait); |
| 2012 | continue; | 2012 | continue; |
| 2013 | } | 2013 | } |
| 2014 | 2014 | ||
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index af28dcc21844..48fdf10be7a1 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c | |||
| @@ -216,8 +216,8 @@ static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops) | |||
| 216 | dn_rt_cache_flush(-1); | 216 | dn_rt_cache_flush(-1); |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | static struct fib_rules_ops dn_fib_rules_ops_template = { | 219 | static const struct fib_rules_ops __net_initdata dn_fib_rules_ops_template = { |
| 220 | .family = FIB_RULES_DECNET, | 220 | .family = AF_DECnet, |
| 221 | .rule_size = sizeof(struct dn_fib_rule), | 221 | .rule_size = sizeof(struct dn_fib_rule), |
| 222 | .addr_size = sizeof(u16), | 222 | .addr_size = sizeof(u16), |
| 223 | .action = dn_fib_rule_action, | 223 | .action = dn_fib_rule_action, |
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 205a1c12f3c0..61ec0329316c 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
| @@ -136,7 +136,7 @@ int eth_rebuild_header(struct sk_buff *skb) | |||
| 136 | default: | 136 | default: |
| 137 | printk(KERN_DEBUG | 137 | printk(KERN_DEBUG |
| 138 | "%s: unable to resolve type %X addresses.\n", | 138 | "%s: unable to resolve type %X addresses.\n", |
| 139 | dev->name, (int)eth->h_proto); | 139 | dev->name, ntohs(eth->h_proto)); |
| 140 | 140 | ||
| 141 | memcpy(eth->h_source, dev->dev_addr, ETH_ALEN); | 141 | memcpy(eth->h_source, dev->dev_addr, ETH_ALEN); |
| 142 | break; | 142 | break; |
| @@ -162,7 +162,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
| 162 | 162 | ||
| 163 | skb->dev = dev; | 163 | skb->dev = dev; |
| 164 | skb_reset_mac_header(skb); | 164 | skb_reset_mac_header(skb); |
| 165 | skb_pull(skb, ETH_HLEN); | 165 | skb_pull_inline(skb, ETH_HLEN); |
| 166 | eth = eth_hdr(skb); | 166 | eth = eth_hdr(skb); |
| 167 | 167 | ||
| 168 | if (unlikely(is_multicast_ether_addr(eth->h_dest))) { | 168 | if (unlikely(is_multicast_ether_addr(eth->h_dest))) { |
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c index c7da600750bb..93c91b633a56 100644 --- a/net/ieee802154/af_ieee802154.c +++ b/net/ieee802154/af_ieee802154.c | |||
| @@ -151,6 +151,9 @@ static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, | |||
| 151 | dev_load(sock_net(sk), ifr.ifr_name); | 151 | dev_load(sock_net(sk), ifr.ifr_name); |
| 152 | dev = dev_get_by_name(sock_net(sk), ifr.ifr_name); | 152 | dev = dev_get_by_name(sock_net(sk), ifr.ifr_name); |
| 153 | 153 | ||
| 154 | if (!dev) | ||
| 155 | return -ENODEV; | ||
| 156 | |||
| 154 | if (dev->type == ARPHRD_IEEE802154 && dev->netdev_ops->ndo_do_ioctl) | 157 | if (dev->type == ARPHRD_IEEE802154 && dev->netdev_ops->ndo_do_ioctl) |
| 155 | ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd); | 158 | ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd); |
| 156 | 159 | ||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index c5376c725503..c6c43bcd1c6f 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -419,7 +419,7 @@ int inet_release(struct socket *sock) | |||
| 419 | if (sk) { | 419 | if (sk) { |
| 420 | long timeout; | 420 | long timeout; |
| 421 | 421 | ||
| 422 | inet_rps_reset_flow(sk); | 422 | sock_rps_reset_flow(sk); |
| 423 | 423 | ||
| 424 | /* Applications forget to leave groups before exiting */ | 424 | /* Applications forget to leave groups before exiting */ |
| 425 | ip_mc_drop_socket(sk); | 425 | ip_mc_drop_socket(sk); |
| @@ -548,7 +548,7 @@ static long inet_wait_for_connect(struct sock *sk, long timeo) | |||
| 548 | { | 548 | { |
| 549 | DEFINE_WAIT(wait); | 549 | DEFINE_WAIT(wait); |
| 550 | 550 | ||
| 551 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 551 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 552 | 552 | ||
| 553 | /* Basic assumption: if someone sets sk->sk_err, he _must_ | 553 | /* Basic assumption: if someone sets sk->sk_err, he _must_ |
| 554 | * change state of the socket from TCP_SYN_*. | 554 | * change state of the socket from TCP_SYN_*. |
| @@ -561,9 +561,9 @@ static long inet_wait_for_connect(struct sock *sk, long timeo) | |||
| 561 | lock_sock(sk); | 561 | lock_sock(sk); |
| 562 | if (signal_pending(current) || !timeo) | 562 | if (signal_pending(current) || !timeo) |
| 563 | break; | 563 | break; |
| 564 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 564 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 565 | } | 565 | } |
| 566 | finish_wait(sk->sk_sleep, &wait); | 566 | finish_wait(sk_sleep(sk), &wait); |
| 567 | return timeo; | 567 | return timeo; |
| 568 | } | 568 | } |
| 569 | 569 | ||
| @@ -722,7 +722,7 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
| 722 | { | 722 | { |
| 723 | struct sock *sk = sock->sk; | 723 | struct sock *sk = sock->sk; |
| 724 | 724 | ||
| 725 | inet_rps_record_flow(sk); | 725 | sock_rps_record_flow(sk); |
| 726 | 726 | ||
| 727 | /* We may need to bind the socket. */ | 727 | /* We may need to bind the socket. */ |
| 728 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) | 728 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) |
| @@ -737,7 +737,7 @@ static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, | |||
| 737 | { | 737 | { |
| 738 | struct sock *sk = sock->sk; | 738 | struct sock *sk = sock->sk; |
| 739 | 739 | ||
| 740 | inet_rps_record_flow(sk); | 740 | sock_rps_record_flow(sk); |
| 741 | 741 | ||
| 742 | /* We may need to bind the socket. */ | 742 | /* We may need to bind the socket. */ |
| 743 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) | 743 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) |
| @@ -755,7 +755,7 @@ int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
| 755 | int addr_len = 0; | 755 | int addr_len = 0; |
| 756 | int err; | 756 | int err; |
| 757 | 757 | ||
| 758 | inet_rps_record_flow(sk); | 758 | sock_rps_record_flow(sk); |
| 759 | 759 | ||
| 760 | err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT, | 760 | err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT, |
| 761 | flags & ~MSG_DONTWAIT, &addr_len); | 761 | flags & ~MSG_DONTWAIT, &addr_len); |
| @@ -1323,8 +1323,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
| 1323 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) | 1323 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) |
| 1324 | goto out_unlock; | 1324 | goto out_unlock; |
| 1325 | 1325 | ||
| 1326 | id = ntohl(*(u32 *)&iph->id); | 1326 | id = ntohl(*(__be32 *)&iph->id); |
| 1327 | flush = (u16)((ntohl(*(u32 *)iph) ^ skb_gro_len(skb)) | (id ^ IP_DF)); | 1327 | flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id ^ IP_DF)); |
| 1328 | id >>= 16; | 1328 | id >>= 16; |
| 1329 | 1329 | ||
| 1330 | for (p = *head; p; p = p->next) { | 1330 | for (p = *head; p; p = p->next) { |
| @@ -1337,8 +1337,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
| 1337 | 1337 | ||
| 1338 | if ((iph->protocol ^ iph2->protocol) | | 1338 | if ((iph->protocol ^ iph2->protocol) | |
| 1339 | (iph->tos ^ iph2->tos) | | 1339 | (iph->tos ^ iph2->tos) | |
| 1340 | (iph->saddr ^ iph2->saddr) | | 1340 | ((__force u32)iph->saddr ^ (__force u32)iph2->saddr) | |
| 1341 | (iph->daddr ^ iph2->daddr)) { | 1341 | ((__force u32)iph->daddr ^ (__force u32)iph2->daddr)) { |
| 1342 | NAPI_GRO_CB(p)->same_flow = 0; | 1342 | NAPI_GRO_CB(p)->same_flow = 0; |
| 1343 | continue; | 1343 | continue; |
| 1344 | } | 1344 | } |
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 3ec84fea5b71..76daeb5ff564 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c | |||
| @@ -245,8 +245,8 @@ static void fib4_rule_flush_cache(struct fib_rules_ops *ops) | |||
| 245 | rt_cache_flush(ops->fro_net, -1); | 245 | rt_cache_flush(ops->fro_net, -1); |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | static struct fib_rules_ops fib4_rules_ops_template = { | 248 | static const struct fib_rules_ops __net_initdata fib4_rules_ops_template = { |
| 249 | .family = FIB_RULES_IPV4, | 249 | .family = AF_INET, |
| 250 | .rule_size = sizeof(struct fib4_rule), | 250 | .rule_size = sizeof(struct fib4_rule), |
| 251 | .addr_size = sizeof(u32), | 251 | .addr_size = sizeof(u32), |
| 252 | .action = fib4_rule_action, | 252 | .action = fib4_rule_action, |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 59a838795e3e..c98f115fb0fd 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
| @@ -209,7 +209,9 @@ static inline struct node *tnode_get_child_rcu(struct tnode *tn, unsigned int i) | |||
| 209 | { | 209 | { |
| 210 | struct node *ret = tnode_get_child(tn, i); | 210 | struct node *ret = tnode_get_child(tn, i); |
| 211 | 211 | ||
| 212 | return rcu_dereference(ret); | 212 | return rcu_dereference_check(ret, |
| 213 | rcu_read_lock_held() || | ||
| 214 | lockdep_rtnl_is_held()); | ||
| 213 | } | 215 | } |
| 214 | 216 | ||
| 215 | static inline int tnode_child_length(const struct tnode *tn) | 217 | static inline int tnode_child_length(const struct tnode *tn) |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 8da6429269dd..e0a3e3537b14 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
| @@ -234,7 +234,7 @@ static int inet_csk_wait_for_connect(struct sock *sk, long timeo) | |||
| 234 | * having to remove and re-insert us on the wait queue. | 234 | * having to remove and re-insert us on the wait queue. |
| 235 | */ | 235 | */ |
| 236 | for (;;) { | 236 | for (;;) { |
| 237 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, | 237 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, |
| 238 | TASK_INTERRUPTIBLE); | 238 | TASK_INTERRUPTIBLE); |
| 239 | release_sock(sk); | 239 | release_sock(sk); |
| 240 | if (reqsk_queue_empty(&icsk->icsk_accept_queue)) | 240 | if (reqsk_queue_empty(&icsk->icsk_accept_queue)) |
| @@ -253,7 +253,7 @@ static int inet_csk_wait_for_connect(struct sock *sk, long timeo) | |||
| 253 | if (!timeo) | 253 | if (!timeo) |
| 254 | break; | 254 | break; |
| 255 | } | 255 | } |
| 256 | finish_wait(sk->sk_sleep, &wait); | 256 | finish_wait(sk_sleep(sk), &wait); |
| 257 | return err; | 257 | return err; |
| 258 | } | 258 | } |
| 259 | 259 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index d979710684b2..252897443ef9 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -120,7 +120,7 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb) | |||
| 120 | newskb->pkt_type = PACKET_LOOPBACK; | 120 | newskb->pkt_type = PACKET_LOOPBACK; |
| 121 | newskb->ip_summed = CHECKSUM_UNNECESSARY; | 121 | newskb->ip_summed = CHECKSUM_UNNECESSARY; |
| 122 | WARN_ON(!skb_dst(newskb)); | 122 | WARN_ON(!skb_dst(newskb)); |
| 123 | netif_rx(newskb); | 123 | netif_rx_ni(newskb); |
| 124 | return 0; | 124 | return 0; |
| 125 | } | 125 | } |
| 126 | 126 | ||
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index b0aa0546a3b3..ce231780a2b1 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
| @@ -954,6 +954,22 @@ e_inval: | |||
| 954 | return -EINVAL; | 954 | return -EINVAL; |
| 955 | } | 955 | } |
| 956 | 956 | ||
| 957 | /** | ||
| 958 | * ip_queue_rcv_skb - Queue an skb into sock receive queue | ||
| 959 | * @sk: socket | ||
| 960 | * @skb: buffer | ||
| 961 | * | ||
| 962 | * Queues an skb into socket receive queue. If IP_CMSG_PKTINFO option | ||
| 963 | * is not set, we drop skb dst entry now, while dst cache line is hot. | ||
| 964 | */ | ||
| 965 | int ip_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | ||
| 966 | { | ||
| 967 | if (!(inet_sk(sk)->cmsg_flags & IP_CMSG_PKTINFO)) | ||
| 968 | skb_dst_drop(skb); | ||
| 969 | return sock_queue_rcv_skb(sk, skb); | ||
| 970 | } | ||
| 971 | EXPORT_SYMBOL(ip_queue_rcv_skb); | ||
| 972 | |||
| 957 | int ip_setsockopt(struct sock *sk, int level, | 973 | int ip_setsockopt(struct sock *sk, int level, |
| 958 | int optname, char __user *optval, unsigned int optlen) | 974 | int optname, char __user *optval, unsigned int optlen) |
| 959 | { | 975 | { |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 1aa498d7a0a5..f3f1c6b5c70c 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
| @@ -128,8 +128,8 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt, | |||
| 128 | int local); | 128 | int local); |
| 129 | static int ipmr_cache_report(struct mr_table *mrt, | 129 | static int ipmr_cache_report(struct mr_table *mrt, |
| 130 | struct sk_buff *pkt, vifi_t vifi, int assert); | 130 | struct sk_buff *pkt, vifi_t vifi, int assert); |
| 131 | static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, | 131 | static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, |
| 132 | struct mfc_cache *c, struct rtmsg *rtm); | 132 | struct mfc_cache *c, struct rtmsg *rtm); |
| 133 | static void ipmr_expire_process(unsigned long arg); | 133 | static void ipmr_expire_process(unsigned long arg); |
| 134 | 134 | ||
| 135 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES | 135 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES |
| @@ -216,8 +216,8 @@ static int ipmr_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | |||
| 216 | return 0; | 216 | return 0; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | static struct fib_rules_ops ipmr_rules_ops_template = { | 219 | static const struct fib_rules_ops __net_initdata ipmr_rules_ops_template = { |
| 220 | .family = FIB_RULES_IPMR, | 220 | .family = RTNL_FAMILY_IPMR, |
| 221 | .rule_size = sizeof(struct ipmr_rule), | 221 | .rule_size = sizeof(struct ipmr_rule), |
| 222 | .addr_size = sizeof(u32), | 222 | .addr_size = sizeof(u32), |
| 223 | .action = ipmr_rule_action, | 223 | .action = ipmr_rule_action, |
| @@ -831,7 +831,7 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt, | |||
| 831 | if (ip_hdr(skb)->version == 0) { | 831 | if (ip_hdr(skb)->version == 0) { |
| 832 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); | 832 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); |
| 833 | 833 | ||
| 834 | if (ipmr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { | 834 | if (__ipmr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { |
| 835 | nlh->nlmsg_len = (skb_tail_pointer(skb) - | 835 | nlh->nlmsg_len = (skb_tail_pointer(skb) - |
| 836 | (u8 *)nlh); | 836 | (u8 *)nlh); |
| 837 | } else { | 837 | } else { |
| @@ -1772,10 +1772,10 @@ int ip_mr_input(struct sk_buff *skb) | |||
| 1772 | 1772 | ||
| 1773 | vif = ipmr_find_vif(mrt, skb->dev); | 1773 | vif = ipmr_find_vif(mrt, skb->dev); |
| 1774 | if (vif >= 0) { | 1774 | if (vif >= 0) { |
| 1775 | int err = ipmr_cache_unresolved(mrt, vif, skb); | 1775 | int err2 = ipmr_cache_unresolved(mrt, vif, skb); |
| 1776 | read_unlock(&mrt_lock); | 1776 | read_unlock(&mrt_lock); |
| 1777 | 1777 | ||
| 1778 | return err; | 1778 | return err2; |
| 1779 | } | 1779 | } |
| 1780 | read_unlock(&mrt_lock); | 1780 | read_unlock(&mrt_lock); |
| 1781 | kfree_skb(skb); | 1781 | kfree_skb(skb); |
| @@ -1904,9 +1904,8 @@ drop: | |||
| 1904 | } | 1904 | } |
| 1905 | #endif | 1905 | #endif |
| 1906 | 1906 | ||
| 1907 | static int | 1907 | static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, |
| 1908 | ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, struct mfc_cache *c, | 1908 | struct mfc_cache *c, struct rtmsg *rtm) |
| 1909 | struct rtmsg *rtm) | ||
| 1910 | { | 1909 | { |
| 1911 | int ct; | 1910 | int ct; |
| 1912 | struct rtnexthop *nhp; | 1911 | struct rtnexthop *nhp; |
| @@ -1994,11 +1993,93 @@ int ipmr_get_route(struct net *net, | |||
| 1994 | 1993 | ||
| 1995 | if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) | 1994 | if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) |
| 1996 | cache->mfc_flags |= MFC_NOTIFY; | 1995 | cache->mfc_flags |= MFC_NOTIFY; |
| 1997 | err = ipmr_fill_mroute(mrt, skb, cache, rtm); | 1996 | err = __ipmr_fill_mroute(mrt, skb, cache, rtm); |
| 1998 | read_unlock(&mrt_lock); | 1997 | read_unlock(&mrt_lock); |
| 1999 | return err; | 1998 | return err; |
| 2000 | } | 1999 | } |
| 2001 | 2000 | ||
| 2001 | static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, | ||
| 2002 | u32 pid, u32 seq, struct mfc_cache *c) | ||
| 2003 | { | ||
| 2004 | struct nlmsghdr *nlh; | ||
| 2005 | struct rtmsg *rtm; | ||
| 2006 | |||
| 2007 | nlh = nlmsg_put(skb, pid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI); | ||
| 2008 | if (nlh == NULL) | ||
| 2009 | return -EMSGSIZE; | ||
| 2010 | |||
| 2011 | rtm = nlmsg_data(nlh); | ||
| 2012 | rtm->rtm_family = RTNL_FAMILY_IPMR; | ||
| 2013 | rtm->rtm_dst_len = 32; | ||
| 2014 | rtm->rtm_src_len = 32; | ||
| 2015 | rtm->rtm_tos = 0; | ||
| 2016 | rtm->rtm_table = mrt->id; | ||
| 2017 | NLA_PUT_U32(skb, RTA_TABLE, mrt->id); | ||
| 2018 | rtm->rtm_type = RTN_MULTICAST; | ||
| 2019 | rtm->rtm_scope = RT_SCOPE_UNIVERSE; | ||
| 2020 | rtm->rtm_protocol = RTPROT_UNSPEC; | ||
| 2021 | rtm->rtm_flags = 0; | ||
| 2022 | |||
| 2023 | NLA_PUT_BE32(skb, RTA_SRC, c->mfc_origin); | ||
| 2024 | NLA_PUT_BE32(skb, RTA_DST, c->mfc_mcastgrp); | ||
| 2025 | |||
| 2026 | if (__ipmr_fill_mroute(mrt, skb, c, rtm) < 0) | ||
| 2027 | goto nla_put_failure; | ||
| 2028 | |||
| 2029 | return nlmsg_end(skb, nlh); | ||
| 2030 | |||
| 2031 | nla_put_failure: | ||
| 2032 | nlmsg_cancel(skb, nlh); | ||
| 2033 | return -EMSGSIZE; | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) | ||
| 2037 | { | ||
| 2038 | struct net *net = sock_net(skb->sk); | ||
| 2039 | struct mr_table *mrt; | ||
| 2040 | struct mfc_cache *mfc; | ||
| 2041 | unsigned int t = 0, s_t; | ||
| 2042 | unsigned int h = 0, s_h; | ||
| 2043 | unsigned int e = 0, s_e; | ||
| 2044 | |||
| 2045 | s_t = cb->args[0]; | ||
| 2046 | s_h = cb->args[1]; | ||
| 2047 | s_e = cb->args[2]; | ||
| 2048 | |||
| 2049 | read_lock(&mrt_lock); | ||
| 2050 | ipmr_for_each_table(mrt, net) { | ||
| 2051 | if (t < s_t) | ||
| 2052 | goto next_table; | ||
| 2053 | if (t > s_t) | ||
| 2054 | s_h = 0; | ||
| 2055 | for (h = s_h; h < MFC_LINES; h++) { | ||
| 2056 | list_for_each_entry(mfc, &mrt->mfc_cache_array[h], list) { | ||
| 2057 | if (e < s_e) | ||
| 2058 | goto next_entry; | ||
| 2059 | if (ipmr_fill_mroute(mrt, skb, | ||
| 2060 | NETLINK_CB(cb->skb).pid, | ||
| 2061 | cb->nlh->nlmsg_seq, | ||
| 2062 | mfc) < 0) | ||
| 2063 | goto done; | ||
| 2064 | next_entry: | ||
| 2065 | e++; | ||
| 2066 | } | ||
| 2067 | e = s_e = 0; | ||
| 2068 | } | ||
| 2069 | s_h = 0; | ||
| 2070 | next_table: | ||
| 2071 | t++; | ||
| 2072 | } | ||
| 2073 | done: | ||
| 2074 | read_unlock(&mrt_lock); | ||
| 2075 | |||
| 2076 | cb->args[2] = e; | ||
| 2077 | cb->args[1] = h; | ||
| 2078 | cb->args[0] = t; | ||
| 2079 | |||
| 2080 | return skb->len; | ||
| 2081 | } | ||
| 2082 | |||
| 2002 | #ifdef CONFIG_PROC_FS | 2083 | #ifdef CONFIG_PROC_FS |
| 2003 | /* | 2084 | /* |
| 2004 | * The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif | 2085 | * The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif |
| @@ -2227,9 +2308,9 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | |||
| 2227 | const struct ipmr_mfc_iter *it = seq->private; | 2308 | const struct ipmr_mfc_iter *it = seq->private; |
| 2228 | const struct mr_table *mrt = it->mrt; | 2309 | const struct mr_table *mrt = it->mrt; |
| 2229 | 2310 | ||
| 2230 | seq_printf(seq, "%08lX %08lX %-3hd", | 2311 | seq_printf(seq, "%08X %08X %-3hd", |
| 2231 | (unsigned long) mfc->mfc_mcastgrp, | 2312 | (__force u32) mfc->mfc_mcastgrp, |
| 2232 | (unsigned long) mfc->mfc_origin, | 2313 | (__force u32) mfc->mfc_origin, |
| 2233 | mfc->mfc_parent); | 2314 | mfc->mfc_parent); |
| 2234 | 2315 | ||
| 2235 | if (it->cache != &mrt->mfc_unres_queue) { | 2316 | if (it->cache != &mrt->mfc_unres_queue) { |
| @@ -2355,6 +2436,7 @@ int __init ip_mr_init(void) | |||
| 2355 | goto add_proto_fail; | 2436 | goto add_proto_fail; |
| 2356 | } | 2437 | } |
| 2357 | #endif | 2438 | #endif |
| 2439 | rtnl_register(RTNL_FAMILY_IPMR, RTM_GETROUTE, NULL, ipmr_rtm_dumproute); | ||
| 2358 | return 0; | 2440 | return 0; |
| 2359 | 2441 | ||
| 2360 | #ifdef CONFIG_IP_PIMSM_V2 | 2442 | #ifdef CONFIG_IP_PIMSM_V2 |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index bbda0d5f9244..2c7a1639388a 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
| @@ -290,7 +290,7 @@ static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb) | |||
| 290 | { | 290 | { |
| 291 | /* Charge it to the socket. */ | 291 | /* Charge it to the socket. */ |
| 292 | 292 | ||
| 293 | if (sock_queue_rcv_skb(sk, skb) < 0) { | 293 | if (ip_queue_rcv_skb(sk, skb) < 0) { |
| 294 | kfree_skb(skb); | 294 | kfree_skb(skb); |
| 295 | return NET_RX_DROP; | 295 | return NET_RX_DROP; |
| 296 | } | 296 | } |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index cb562fdd9b9a..dea3f9264250 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -129,7 +129,6 @@ static int ip_rt_gc_elasticity __read_mostly = 8; | |||
| 129 | static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; | 129 | static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; |
| 130 | static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; | 130 | static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; |
| 131 | static int ip_rt_min_advmss __read_mostly = 256; | 131 | static int ip_rt_min_advmss __read_mostly = 256; |
| 132 | static int ip_rt_secret_interval __read_mostly = 10 * 60 * HZ; | ||
| 133 | static int rt_chain_length_max __read_mostly = 20; | 132 | static int rt_chain_length_max __read_mostly = 20; |
| 134 | 133 | ||
| 135 | static struct delayed_work expires_work; | 134 | static struct delayed_work expires_work; |
| @@ -258,10 +257,9 @@ static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); | |||
| 258 | (__raw_get_cpu_var(rt_cache_stat).field++) | 257 | (__raw_get_cpu_var(rt_cache_stat).field++) |
| 259 | 258 | ||
| 260 | static inline unsigned int rt_hash(__be32 daddr, __be32 saddr, int idx, | 259 | static inline unsigned int rt_hash(__be32 daddr, __be32 saddr, int idx, |
| 261 | int genid) | 260 | int genid) |
| 262 | { | 261 | { |
| 263 | return jhash_3words((__force u32)(__be32)(daddr), | 262 | return jhash_3words((__force u32)daddr, (__force u32)saddr, |
| 264 | (__force u32)(__be32)(saddr), | ||
| 265 | idx, genid) | 263 | idx, genid) |
| 266 | & rt_hash_mask; | 264 | & rt_hash_mask; |
| 267 | } | 265 | } |
| @@ -378,12 +376,13 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) | |||
| 378 | struct rtable *r = v; | 376 | struct rtable *r = v; |
| 379 | int len; | 377 | int len; |
| 380 | 378 | ||
| 381 | seq_printf(seq, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t" | 379 | seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t" |
| 382 | "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", | 380 | "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", |
| 383 | r->u.dst.dev ? r->u.dst.dev->name : "*", | 381 | r->u.dst.dev ? r->u.dst.dev->name : "*", |
| 384 | (unsigned long)r->rt_dst, (unsigned long)r->rt_gateway, | 382 | (__force u32)r->rt_dst, |
| 383 | (__force u32)r->rt_gateway, | ||
| 385 | r->rt_flags, atomic_read(&r->u.dst.__refcnt), | 384 | r->rt_flags, atomic_read(&r->u.dst.__refcnt), |
| 386 | r->u.dst.__use, 0, (unsigned long)r->rt_src, | 385 | r->u.dst.__use, 0, (__force u32)r->rt_src, |
| 387 | (dst_metric(&r->u.dst, RTAX_ADVMSS) ? | 386 | (dst_metric(&r->u.dst, RTAX_ADVMSS) ? |
| 388 | (int)dst_metric(&r->u.dst, RTAX_ADVMSS) + 40 : 0), | 387 | (int)dst_metric(&r->u.dst, RTAX_ADVMSS) + 40 : 0), |
| 389 | dst_metric(&r->u.dst, RTAX_WINDOW), | 388 | dst_metric(&r->u.dst, RTAX_WINDOW), |
| @@ -685,18 +684,17 @@ static inline bool rt_caching(const struct net *net) | |||
| 685 | static inline bool compare_hash_inputs(const struct flowi *fl1, | 684 | static inline bool compare_hash_inputs(const struct flowi *fl1, |
| 686 | const struct flowi *fl2) | 685 | const struct flowi *fl2) |
| 687 | { | 686 | { |
| 688 | return (__force u32)(((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) | | 687 | return ((((__force u32)fl1->nl_u.ip4_u.daddr ^ (__force u32)fl2->nl_u.ip4_u.daddr) | |
| 689 | (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) | | 688 | ((__force u32)fl1->nl_u.ip4_u.saddr ^ (__force u32)fl2->nl_u.ip4_u.saddr) | |
| 690 | (fl1->iif ^ fl2->iif)) == 0); | 689 | (fl1->iif ^ fl2->iif)) == 0); |
| 691 | } | 690 | } |
| 692 | 691 | ||
| 693 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) | 692 | static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) |
| 694 | { | 693 | { |
| 695 | return ((__force u32)((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) | | 694 | return (((__force u32)fl1->nl_u.ip4_u.daddr ^ (__force u32)fl2->nl_u.ip4_u.daddr) | |
| 696 | (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr)) | | 695 | ((__force u32)fl1->nl_u.ip4_u.saddr ^ (__force u32)fl2->nl_u.ip4_u.saddr) | |
| 697 | (fl1->mark ^ fl2->mark) | | 696 | (fl1->mark ^ fl2->mark) | |
| 698 | (*(u16 *)&fl1->nl_u.ip4_u.tos ^ | 697 | (*(u16 *)&fl1->nl_u.ip4_u.tos ^ *(u16 *)&fl2->nl_u.ip4_u.tos) | |
| 699 | *(u16 *)&fl2->nl_u.ip4_u.tos) | | ||
| 700 | (fl1->oif ^ fl2->oif) | | 698 | (fl1->oif ^ fl2->oif) | |
| 701 | (fl1->iif ^ fl2->iif)) == 0; | 699 | (fl1->iif ^ fl2->iif)) == 0; |
| 702 | } | 700 | } |
| @@ -919,32 +917,11 @@ void rt_cache_flush_batch(void) | |||
| 919 | rt_do_flush(!in_softirq()); | 917 | rt_do_flush(!in_softirq()); |
| 920 | } | 918 | } |
| 921 | 919 | ||
| 922 | /* | ||
| 923 | * We change rt_genid and let gc do the cleanup | ||
| 924 | */ | ||
| 925 | static void rt_secret_rebuild(unsigned long __net) | ||
| 926 | { | ||
| 927 | struct net *net = (struct net *)__net; | ||
| 928 | rt_cache_invalidate(net); | ||
| 929 | mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval); | ||
| 930 | } | ||
| 931 | |||
| 932 | static void rt_secret_rebuild_oneshot(struct net *net) | ||
| 933 | { | ||
| 934 | del_timer_sync(&net->ipv4.rt_secret_timer); | ||
| 935 | rt_cache_invalidate(net); | ||
| 936 | if (ip_rt_secret_interval) | ||
| 937 | mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval); | ||
| 938 | } | ||
| 939 | |||
| 940 | static void rt_emergency_hash_rebuild(struct net *net) | 920 | static void rt_emergency_hash_rebuild(struct net *net) |
| 941 | { | 921 | { |
| 942 | if (net_ratelimit()) { | 922 | if (net_ratelimit()) |
| 943 | printk(KERN_WARNING "Route hash chain too long!\n"); | 923 | printk(KERN_WARNING "Route hash chain too long!\n"); |
| 944 | printk(KERN_WARNING "Adjust your secret_interval!\n"); | 924 | rt_cache_invalidate(net); |
| 945 | } | ||
| 946 | |||
| 947 | rt_secret_rebuild_oneshot(net); | ||
| 948 | } | 925 | } |
| 949 | 926 | ||
| 950 | /* | 927 | /* |
| @@ -2319,8 +2296,8 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
| 2319 | rcu_read_lock(); | 2296 | rcu_read_lock(); |
| 2320 | for (rth = rcu_dereference(rt_hash_table[hash].chain); rth; | 2297 | for (rth = rcu_dereference(rt_hash_table[hash].chain); rth; |
| 2321 | rth = rcu_dereference(rth->u.dst.rt_next)) { | 2298 | rth = rcu_dereference(rth->u.dst.rt_next)) { |
| 2322 | if (((rth->fl.fl4_dst ^ daddr) | | 2299 | if ((((__force u32)rth->fl.fl4_dst ^ (__force u32)daddr) | |
| 2323 | (rth->fl.fl4_src ^ saddr) | | 2300 | ((__force u32)rth->fl.fl4_src ^ (__force u32)saddr) | |
| 2324 | (rth->fl.iif ^ iif) | | 2301 | (rth->fl.iif ^ iif) | |
| 2325 | rth->fl.oif | | 2302 | rth->fl.oif | |
| 2326 | (rth->fl.fl4_tos ^ tos)) == 0 && | 2303 | (rth->fl.fl4_tos ^ tos)) == 0 && |
| @@ -3102,48 +3079,6 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write, | |||
| 3102 | return -EINVAL; | 3079 | return -EINVAL; |
| 3103 | } | 3080 | } |
| 3104 | 3081 | ||
| 3105 | static void rt_secret_reschedule(int old) | ||
| 3106 | { | ||
| 3107 | struct net *net; | ||
| 3108 | int new = ip_rt_secret_interval; | ||
| 3109 | int diff = new - old; | ||
| 3110 | |||
| 3111 | if (!diff) | ||
| 3112 | return; | ||
| 3113 | |||
| 3114 | rtnl_lock(); | ||
| 3115 | for_each_net(net) { | ||
| 3116 | int deleted = del_timer_sync(&net->ipv4.rt_secret_timer); | ||
| 3117 | long time; | ||
| 3118 | |||
| 3119 | if (!new) | ||
| 3120 | continue; | ||
| 3121 | |||
| 3122 | if (deleted) { | ||
| 3123 | time = net->ipv4.rt_secret_timer.expires - jiffies; | ||
| 3124 | |||
| 3125 | if (time <= 0 || (time += diff) <= 0) | ||
| 3126 | time = 0; | ||
| 3127 | } else | ||
| 3128 | time = new; | ||
| 3129 | |||
| 3130 | mod_timer(&net->ipv4.rt_secret_timer, jiffies + time); | ||
| 3131 | } | ||
| 3132 | rtnl_unlock(); | ||
| 3133 | } | ||
| 3134 | |||
| 3135 | static int ipv4_sysctl_rt_secret_interval(ctl_table *ctl, int write, | ||
| 3136 | void __user *buffer, size_t *lenp, | ||
| 3137 | loff_t *ppos) | ||
| 3138 | { | ||
| 3139 | int old = ip_rt_secret_interval; | ||
| 3140 | int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos); | ||
| 3141 | |||
| 3142 | rt_secret_reschedule(old); | ||
| 3143 | |||
| 3144 | return ret; | ||
| 3145 | } | ||
| 3146 | |||
| 3147 | static ctl_table ipv4_route_table[] = { | 3082 | static ctl_table ipv4_route_table[] = { |
| 3148 | { | 3083 | { |
| 3149 | .procname = "gc_thresh", | 3084 | .procname = "gc_thresh", |
| @@ -3252,13 +3187,6 @@ static ctl_table ipv4_route_table[] = { | |||
| 3252 | .mode = 0644, | 3187 | .mode = 0644, |
| 3253 | .proc_handler = proc_dointvec, | 3188 | .proc_handler = proc_dointvec, |
| 3254 | }, | 3189 | }, |
| 3255 | { | ||
| 3256 | .procname = "secret_interval", | ||
| 3257 | .data = &ip_rt_secret_interval, | ||
| 3258 | .maxlen = sizeof(int), | ||
| 3259 | .mode = 0644, | ||
| 3260 | .proc_handler = ipv4_sysctl_rt_secret_interval, | ||
| 3261 | }, | ||
| 3262 | { } | 3190 | { } |
| 3263 | }; | 3191 | }; |
| 3264 | 3192 | ||
| @@ -3337,34 +3265,15 @@ static __net_initdata struct pernet_operations sysctl_route_ops = { | |||
| 3337 | }; | 3265 | }; |
| 3338 | #endif | 3266 | #endif |
| 3339 | 3267 | ||
| 3340 | 3268 | static __net_init int rt_genid_init(struct net *net) | |
| 3341 | static __net_init int rt_secret_timer_init(struct net *net) | ||
| 3342 | { | 3269 | { |
| 3343 | atomic_set(&net->ipv4.rt_genid, | 3270 | get_random_bytes(&net->ipv4.rt_genid, |
| 3344 | (int) ((num_physpages ^ (num_physpages>>8)) ^ | 3271 | sizeof(net->ipv4.rt_genid)); |
| 3345 | (jiffies ^ (jiffies >> 7)))); | ||
| 3346 | |||
| 3347 | net->ipv4.rt_secret_timer.function = rt_secret_rebuild; | ||
| 3348 | net->ipv4.rt_secret_timer.data = (unsigned long)net; | ||
| 3349 | init_timer_deferrable(&net->ipv4.rt_secret_timer); | ||
| 3350 | |||
| 3351 | if (ip_rt_secret_interval) { | ||
| 3352 | net->ipv4.rt_secret_timer.expires = | ||
| 3353 | jiffies + net_random() % ip_rt_secret_interval + | ||
| 3354 | ip_rt_secret_interval; | ||
| 3355 | add_timer(&net->ipv4.rt_secret_timer); | ||
| 3356 | } | ||
| 3357 | return 0; | 3272 | return 0; |
| 3358 | } | 3273 | } |
| 3359 | 3274 | ||
| 3360 | static __net_exit void rt_secret_timer_exit(struct net *net) | 3275 | static __net_initdata struct pernet_operations rt_genid_ops = { |
| 3361 | { | 3276 | .init = rt_genid_init, |
| 3362 | del_timer_sync(&net->ipv4.rt_secret_timer); | ||
| 3363 | } | ||
| 3364 | |||
| 3365 | static __net_initdata struct pernet_operations rt_secret_timer_ops = { | ||
| 3366 | .init = rt_secret_timer_init, | ||
| 3367 | .exit = rt_secret_timer_exit, | ||
| 3368 | }; | 3277 | }; |
| 3369 | 3278 | ||
| 3370 | 3279 | ||
| @@ -3425,9 +3334,6 @@ int __init ip_rt_init(void) | |||
| 3425 | schedule_delayed_work(&expires_work, | 3334 | schedule_delayed_work(&expires_work, |
| 3426 | net_random() % ip_rt_gc_interval + ip_rt_gc_interval); | 3335 | net_random() % ip_rt_gc_interval + ip_rt_gc_interval); |
| 3427 | 3336 | ||
| 3428 | if (register_pernet_subsys(&rt_secret_timer_ops)) | ||
| 3429 | printk(KERN_ERR "Unable to setup rt_secret_timer\n"); | ||
| 3430 | |||
| 3431 | if (ip_rt_proc_init()) | 3337 | if (ip_rt_proc_init()) |
| 3432 | printk(KERN_ERR "Unable to create route proc files\n"); | 3338 | printk(KERN_ERR "Unable to create route proc files\n"); |
| 3433 | #ifdef CONFIG_XFRM | 3339 | #ifdef CONFIG_XFRM |
| @@ -3439,6 +3345,7 @@ int __init ip_rt_init(void) | |||
| 3439 | #ifdef CONFIG_SYSCTL | 3345 | #ifdef CONFIG_SYSCTL |
| 3440 | register_pernet_subsys(&sysctl_route_ops); | 3346 | register_pernet_subsys(&sysctl_route_ops); |
| 3441 | #endif | 3347 | #endif |
| 3348 | register_pernet_subsys(&rt_genid_ops); | ||
| 3442 | return rc; | 3349 | return rc; |
| 3443 | } | 3350 | } |
| 3444 | 3351 | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 0f8caf64caa3..8ce29747ad9b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -378,7 +378,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
| 378 | struct sock *sk = sock->sk; | 378 | struct sock *sk = sock->sk; |
| 379 | struct tcp_sock *tp = tcp_sk(sk); | 379 | struct tcp_sock *tp = tcp_sk(sk); |
| 380 | 380 | ||
| 381 | sock_poll_wait(file, sk->sk_sleep, wait); | 381 | sock_poll_wait(file, sk_sleep(sk), wait); |
| 382 | if (sk->sk_state == TCP_LISTEN) | 382 | if (sk->sk_state == TCP_LISTEN) |
| 383 | return inet_csk_listen_poll(sk); | 383 | return inet_csk_listen_poll(sk); |
| 384 | 384 | ||
| @@ -2298,7 +2298,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
| 2298 | if (sock_flag(sk, SOCK_KEEPOPEN) && | 2298 | if (sock_flag(sk, SOCK_KEEPOPEN) && |
| 2299 | !((1 << sk->sk_state) & | 2299 | !((1 << sk->sk_state) & |
| 2300 | (TCPF_CLOSE | TCPF_LISTEN))) { | 2300 | (TCPF_CLOSE | TCPF_LISTEN))) { |
| 2301 | __u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; | 2301 | u32 elapsed = keepalive_time_elapsed(tp); |
| 2302 | if (tp->keepalive_time > elapsed) | 2302 | if (tp->keepalive_time > elapsed) |
| 2303 | elapsed = tp->keepalive_time - elapsed; | 2303 | elapsed = tp->keepalive_time - elapsed; |
| 2304 | else | 2304 | else |
| @@ -2721,7 +2721,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
| 2721 | struct tcphdr *th2; | 2721 | struct tcphdr *th2; |
| 2722 | unsigned int len; | 2722 | unsigned int len; |
| 2723 | unsigned int thlen; | 2723 | unsigned int thlen; |
| 2724 | unsigned int flags; | 2724 | __be32 flags; |
| 2725 | unsigned int mss = 1; | 2725 | unsigned int mss = 1; |
| 2726 | unsigned int hlen; | 2726 | unsigned int hlen; |
| 2727 | unsigned int off; | 2727 | unsigned int off; |
| @@ -2771,10 +2771,10 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
| 2771 | 2771 | ||
| 2772 | found: | 2772 | found: |
| 2773 | flush = NAPI_GRO_CB(p)->flush; | 2773 | flush = NAPI_GRO_CB(p)->flush; |
| 2774 | flush |= flags & TCP_FLAG_CWR; | 2774 | flush |= (__force int)(flags & TCP_FLAG_CWR); |
| 2775 | flush |= (flags ^ tcp_flag_word(th2)) & | 2775 | flush |= (__force int)((flags ^ tcp_flag_word(th2)) & |
| 2776 | ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH); | 2776 | ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH)); |
| 2777 | flush |= th->ack_seq ^ th2->ack_seq; | 2777 | flush |= (__force int)(th->ack_seq ^ th2->ack_seq); |
| 2778 | for (i = sizeof(*th); i < thlen; i += 4) | 2778 | for (i = sizeof(*th); i < thlen; i += 4) |
| 2779 | flush |= *(u32 *)((u8 *)th + i) ^ | 2779 | flush |= *(u32 *)((u8 *)th + i) ^ |
| 2780 | *(u32 *)((u8 *)th2 + i); | 2780 | *(u32 *)((u8 *)th2 + i); |
| @@ -2795,8 +2795,9 @@ found: | |||
| 2795 | 2795 | ||
| 2796 | out_check_final: | 2796 | out_check_final: |
| 2797 | flush = len < mss; | 2797 | flush = len < mss; |
| 2798 | flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | | 2798 | flush |= (__force int)(flags & (TCP_FLAG_URG | TCP_FLAG_PSH | |
| 2799 | TCP_FLAG_SYN | TCP_FLAG_FIN); | 2799 | TCP_FLAG_RST | TCP_FLAG_SYN | |
| 2800 | TCP_FLAG_FIN)); | ||
| 2800 | 2801 | ||
| 2801 | if (p && (!NAPI_GRO_CB(skb)->same_flow || flush)) | 2802 | if (p && (!NAPI_GRO_CB(skb)->same_flow || flush)) |
| 2802 | pp = head; | 2803 | pp = head; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index ae3ec15fb630..e82162c211bf 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -4367,6 +4367,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) | |||
| 4367 | if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) | 4367 | if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) |
| 4368 | goto drop; | 4368 | goto drop; |
| 4369 | 4369 | ||
| 4370 | skb_dst_drop(skb); | ||
| 4370 | __skb_pull(skb, th->doff * 4); | 4371 | __skb_pull(skb, th->doff * 4); |
| 4371 | 4372 | ||
| 4372 | TCP_ECN_accept_cwr(tp, skb); | 4373 | TCP_ECN_accept_cwr(tp, skb); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ad08392a738c..771f8146a2e5 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -1286,8 +1286,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
| 1286 | goto drop_and_release; | 1286 | goto drop_and_release; |
| 1287 | 1287 | ||
| 1288 | /* Secret recipe starts with IP addresses */ | 1288 | /* Secret recipe starts with IP addresses */ |
| 1289 | *mess++ ^= daddr; | 1289 | *mess++ ^= (__force u32)daddr; |
| 1290 | *mess++ ^= saddr; | 1290 | *mess++ ^= (__force u32)saddr; |
| 1291 | 1291 | ||
| 1292 | /* plus variable length Initiator Cookie */ | 1292 | /* plus variable length Initiator Cookie */ |
| 1293 | c = (u8 *)mess; | 1293 | c = (u8 *)mess; |
| @@ -1672,7 +1672,7 @@ process: | |||
| 1672 | 1672 | ||
| 1673 | skb->dev = NULL; | 1673 | skb->dev = NULL; |
| 1674 | 1674 | ||
| 1675 | inet_rps_save_rxhash(sk, skb->rxhash); | 1675 | sock_rps_save_rxhash(sk, skb->rxhash); |
| 1676 | 1676 | ||
| 1677 | bh_lock_sock_nested(sk); | 1677 | bh_lock_sock_nested(sk); |
| 1678 | ret = 0; | 1678 | ret = 0; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 2b7d71fb8439..5db3a2c6cb33 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -861,7 +861,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 861 | th->urg_ptr = htons(tp->snd_up - tcb->seq); | 861 | th->urg_ptr = htons(tp->snd_up - tcb->seq); |
| 862 | th->urg = 1; | 862 | th->urg = 1; |
| 863 | } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) { | 863 | } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) { |
| 864 | th->urg_ptr = 0xFFFF; | 864 | th->urg_ptr = htons(0xFFFF); |
| 865 | th->urg = 1; | 865 | th->urg = 1; |
| 866 | } | 866 | } |
| 867 | } | 867 | } |
| @@ -888,7 +888,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 888 | tcp_event_data_sent(tp, skb, sk); | 888 | tcp_event_data_sent(tp, skb, sk); |
| 889 | 889 | ||
| 890 | if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq) | 890 | if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq) |
| 891 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); | 891 | TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS, |
| 892 | tcp_skb_pcount(skb)); | ||
| 892 | 893 | ||
| 893 | err = icsk->icsk_af_ops->queue_xmit(skb); | 894 | err = icsk->icsk_af_ops->queue_xmit(skb); |
| 894 | if (likely(err <= 0)) | 895 | if (likely(err <= 0)) |
| @@ -2485,7 +2486,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
| 2485 | *tail-- ^= TCP_SKB_CB(skb)->seq + 1; | 2486 | *tail-- ^= TCP_SKB_CB(skb)->seq + 1; |
| 2486 | 2487 | ||
| 2487 | /* recommended */ | 2488 | /* recommended */ |
| 2488 | *tail-- ^= ((th->dest << 16) | th->source); | 2489 | *tail-- ^= (((__force u32)th->dest << 16) | (__force u32)th->source); |
| 2489 | *tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */ | 2490 | *tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */ |
| 2490 | 2491 | ||
| 2491 | sha_transform((__u32 *)&xvp->cookie_bakery[0], | 2492 | sha_transform((__u32 *)&xvp->cookie_bakery[0], |
| @@ -2503,7 +2504,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
| 2503 | th->window = htons(min(req->rcv_wnd, 65535U)); | 2504 | th->window = htons(min(req->rcv_wnd, 65535U)); |
| 2504 | tcp_options_write((__be32 *)(th + 1), tp, &opts); | 2505 | tcp_options_write((__be32 *)(th + 1), tp, &opts); |
| 2505 | th->doff = (tcp_header_size >> 2); | 2506 | th->doff = (tcp_header_size >> 2); |
| 2506 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); | 2507 | TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS, tcp_skb_pcount(skb)); |
| 2507 | 2508 | ||
| 2508 | #ifdef CONFIG_TCP_MD5SIG | 2509 | #ifdef CONFIG_TCP_MD5SIG |
| 2509 | /* Okay, we have all we need - do the md5 hash if needed */ | 2510 | /* Okay, we have all we need - do the md5 hash if needed */ |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index c732be00606b..440a5c6004f6 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
| @@ -517,7 +517,7 @@ static void tcp_keepalive_timer (unsigned long data) | |||
| 517 | struct sock *sk = (struct sock *) data; | 517 | struct sock *sk = (struct sock *) data; |
| 518 | struct inet_connection_sock *icsk = inet_csk(sk); | 518 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 519 | struct tcp_sock *tp = tcp_sk(sk); | 519 | struct tcp_sock *tp = tcp_sk(sk); |
| 520 | __u32 elapsed; | 520 | u32 elapsed; |
| 521 | 521 | ||
| 522 | /* Only process if socket is not in use. */ | 522 | /* Only process if socket is not in use. */ |
| 523 | bh_lock_sock(sk); | 523 | bh_lock_sock(sk); |
| @@ -554,7 +554,7 @@ static void tcp_keepalive_timer (unsigned long data) | |||
| 554 | if (tp->packets_out || tcp_send_head(sk)) | 554 | if (tp->packets_out || tcp_send_head(sk)) |
| 555 | goto resched; | 555 | goto resched; |
| 556 | 556 | ||
| 557 | elapsed = tcp_time_stamp - tp->rcv_tstamp; | 557 | elapsed = keepalive_time_elapsed(tp); |
| 558 | 558 | ||
| 559 | if (elapsed >= keepalive_time_when(tp)) { | 559 | if (elapsed >= keepalive_time_when(tp)) { |
| 560 | if (icsk->icsk_probes_out >= keepalive_probes(tp)) { | 560 | if (icsk->icsk_probes_out >= keepalive_probes(tp)) { |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 666b963496ff..4560b291180b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -307,13 +307,13 @@ static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) | |||
| 307 | static unsigned int udp4_portaddr_hash(struct net *net, __be32 saddr, | 307 | static unsigned int udp4_portaddr_hash(struct net *net, __be32 saddr, |
| 308 | unsigned int port) | 308 | unsigned int port) |
| 309 | { | 309 | { |
| 310 | return jhash_1word(saddr, net_hash_mix(net)) ^ port; | 310 | return jhash_1word((__force u32)saddr, net_hash_mix(net)) ^ port; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | int udp_v4_get_port(struct sock *sk, unsigned short snum) | 313 | int udp_v4_get_port(struct sock *sk, unsigned short snum) |
| 314 | { | 314 | { |
| 315 | unsigned int hash2_nulladdr = | 315 | unsigned int hash2_nulladdr = |
| 316 | udp4_portaddr_hash(sock_net(sk), INADDR_ANY, snum); | 316 | udp4_portaddr_hash(sock_net(sk), htonl(INADDR_ANY), snum); |
| 317 | unsigned int hash2_partial = | 317 | unsigned int hash2_partial = |
| 318 | udp4_portaddr_hash(sock_net(sk), inet_sk(sk)->inet_rcv_saddr, 0); | 318 | udp4_portaddr_hash(sock_net(sk), inet_sk(sk)->inet_rcv_saddr, 0); |
| 319 | 319 | ||
| @@ -466,14 +466,14 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
| 466 | daddr, hnum, dif, | 466 | daddr, hnum, dif, |
| 467 | hslot2, slot2); | 467 | hslot2, slot2); |
| 468 | if (!result) { | 468 | if (!result) { |
| 469 | hash2 = udp4_portaddr_hash(net, INADDR_ANY, hnum); | 469 | hash2 = udp4_portaddr_hash(net, htonl(INADDR_ANY), hnum); |
| 470 | slot2 = hash2 & udptable->mask; | 470 | slot2 = hash2 & udptable->mask; |
| 471 | hslot2 = &udptable->hash2[slot2]; | 471 | hslot2 = &udptable->hash2[slot2]; |
| 472 | if (hslot->count < hslot2->count) | 472 | if (hslot->count < hslot2->count) |
| 473 | goto begin; | 473 | goto begin; |
| 474 | 474 | ||
| 475 | result = udp4_lib_lookup2(net, saddr, sport, | 475 | result = udp4_lib_lookup2(net, saddr, sport, |
| 476 | INADDR_ANY, hnum, dif, | 476 | htonl(INADDR_ANY), hnum, dif, |
| 477 | hslot2, slot2); | 477 | hslot2, slot2); |
| 478 | } | 478 | } |
| 479 | rcu_read_unlock(); | 479 | rcu_read_unlock(); |
| @@ -1062,10 +1062,10 @@ static unsigned int first_packet_length(struct sock *sk) | |||
| 1062 | spin_unlock_bh(&rcvq->lock); | 1062 | spin_unlock_bh(&rcvq->lock); |
| 1063 | 1063 | ||
| 1064 | if (!skb_queue_empty(&list_kill)) { | 1064 | if (!skb_queue_empty(&list_kill)) { |
| 1065 | lock_sock(sk); | 1065 | lock_sock_bh(sk); |
| 1066 | __skb_queue_purge(&list_kill); | 1066 | __skb_queue_purge(&list_kill); |
| 1067 | sk_mem_reclaim_partial(sk); | 1067 | sk_mem_reclaim_partial(sk); |
| 1068 | release_sock(sk); | 1068 | unlock_sock_bh(sk); |
| 1069 | } | 1069 | } |
| 1070 | return res; | 1070 | return res; |
| 1071 | } | 1071 | } |
| @@ -1196,10 +1196,10 @@ out: | |||
| 1196 | return err; | 1196 | return err; |
| 1197 | 1197 | ||
| 1198 | csum_copy_err: | 1198 | csum_copy_err: |
| 1199 | lock_sock(sk); | 1199 | lock_sock_bh(sk); |
| 1200 | if (!skb_kill_datagram(sk, skb, flags)) | 1200 | if (!skb_kill_datagram(sk, skb, flags)) |
| 1201 | UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); | 1201 | UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); |
| 1202 | release_sock(sk); | 1202 | unlock_sock_bh(sk); |
| 1203 | 1203 | ||
| 1204 | if (noblock) | 1204 | if (noblock) |
| 1205 | return -EAGAIN; | 1205 | return -EAGAIN; |
| @@ -1217,7 +1217,7 @@ int udp_disconnect(struct sock *sk, int flags) | |||
| 1217 | sk->sk_state = TCP_CLOSE; | 1217 | sk->sk_state = TCP_CLOSE; |
| 1218 | inet->inet_daddr = 0; | 1218 | inet->inet_daddr = 0; |
| 1219 | inet->inet_dport = 0; | 1219 | inet->inet_dport = 0; |
| 1220 | inet_rps_save_rxhash(sk, 0); | 1220 | sock_rps_save_rxhash(sk, 0); |
| 1221 | sk->sk_bound_dev_if = 0; | 1221 | sk->sk_bound_dev_if = 0; |
| 1222 | if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) | 1222 | if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) |
| 1223 | inet_reset_saddr(sk); | 1223 | inet_reset_saddr(sk); |
| @@ -1262,9 +1262,9 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 1262 | int rc; | 1262 | int rc; |
| 1263 | 1263 | ||
| 1264 | if (inet_sk(sk)->inet_daddr) | 1264 | if (inet_sk(sk)->inet_daddr) |
| 1265 | inet_rps_save_rxhash(sk, skb->rxhash); | 1265 | sock_rps_save_rxhash(sk, skb->rxhash); |
| 1266 | 1266 | ||
| 1267 | rc = sock_queue_rcv_skb(sk, skb); | 1267 | rc = ip_queue_rcv_skb(sk, skb); |
| 1268 | if (rc < 0) { | 1268 | if (rc < 0) { |
| 1269 | int is_udplite = IS_UDPLITE(sk); | 1269 | int is_udplite = IS_UDPLITE(sk); |
| 1270 | 1270 | ||
| @@ -1372,6 +1372,10 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 1372 | goto drop; | 1372 | goto drop; |
| 1373 | } | 1373 | } |
| 1374 | 1374 | ||
| 1375 | |||
| 1376 | if (sk_rcvqueues_full(sk, skb)) | ||
| 1377 | goto drop; | ||
| 1378 | |||
| 1375 | rc = 0; | 1379 | rc = 0; |
| 1376 | 1380 | ||
| 1377 | bh_lock_sock(sk); | 1381 | bh_lock_sock(sk); |
| @@ -1620,9 +1624,9 @@ int udp_rcv(struct sk_buff *skb) | |||
| 1620 | 1624 | ||
| 1621 | void udp_destroy_sock(struct sock *sk) | 1625 | void udp_destroy_sock(struct sock *sk) |
| 1622 | { | 1626 | { |
| 1623 | lock_sock(sk); | 1627 | lock_sock_bh(sk); |
| 1624 | udp_flush_pending_frames(sk); | 1628 | udp_flush_pending_frames(sk); |
| 1625 | release_sock(sk); | 1629 | unlock_sock_bh(sk); |
| 1626 | } | 1630 | } |
| 1627 | 1631 | ||
| 1628 | /* | 1632 | /* |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 7cba8845242f..3984f52181f4 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -588,7 +588,8 @@ static u32 ipv6_addr_hash(const struct in6_addr *addr) | |||
| 588 | * We perform the hash function over the last 64 bits of the address | 588 | * We perform the hash function over the last 64 bits of the address |
| 589 | * This will include the IEEE address token on links that support it. | 589 | * This will include the IEEE address token on links that support it. |
| 590 | */ | 590 | */ |
| 591 | return jhash_2words(addr->s6_addr32[2], addr->s6_addr32[3], 0) | 591 | return jhash_2words((__force u32)addr->s6_addr32[2], |
| 592 | (__force u32)addr->s6_addr32[3], 0) | ||
| 592 | & (IN6_ADDR_HSIZE - 1); | 593 | & (IN6_ADDR_HSIZE - 1); |
| 593 | } | 594 | } |
| 594 | 595 | ||
| @@ -1345,7 +1346,7 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add | |||
| 1345 | struct hlist_node *node; | 1346 | struct hlist_node *node; |
| 1346 | 1347 | ||
| 1347 | rcu_read_lock_bh(); | 1348 | rcu_read_lock_bh(); |
| 1348 | hlist_for_each_entry_rcu(ifp, node, &inet6_addr_lst[hash], addr_lst) { | 1349 | hlist_for_each_entry_rcu_bh(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
| 1349 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1350 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
| 1350 | continue; | 1351 | continue; |
| 1351 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1352 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
| @@ -2958,7 +2959,7 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
| 2958 | 2959 | ||
| 2959 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { | 2960 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { |
| 2960 | struct hlist_node *n; | 2961 | struct hlist_node *n; |
| 2961 | hlist_for_each_entry_rcu(ifa, n, &inet6_addr_lst[state->bucket], | 2962 | hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], |
| 2962 | addr_lst) | 2963 | addr_lst) |
| 2963 | if (net_eq(dev_net(ifa->idev->dev), net)) | 2964 | if (net_eq(dev_net(ifa->idev->dev), net)) |
| 2964 | return ifa; | 2965 | return ifa; |
| @@ -2973,12 +2974,12 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, | |||
| 2973 | struct net *net = seq_file_net(seq); | 2974 | struct net *net = seq_file_net(seq); |
| 2974 | struct hlist_node *n = &ifa->addr_lst; | 2975 | struct hlist_node *n = &ifa->addr_lst; |
| 2975 | 2976 | ||
| 2976 | hlist_for_each_entry_continue_rcu(ifa, n, addr_lst) | 2977 | hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) |
| 2977 | if (net_eq(dev_net(ifa->idev->dev), net)) | 2978 | if (net_eq(dev_net(ifa->idev->dev), net)) |
| 2978 | return ifa; | 2979 | return ifa; |
| 2979 | 2980 | ||
| 2980 | while (++state->bucket < IN6_ADDR_HSIZE) { | 2981 | while (++state->bucket < IN6_ADDR_HSIZE) { |
| 2981 | hlist_for_each_entry(ifa, n, | 2982 | hlist_for_each_entry_rcu_bh(ifa, n, |
| 2982 | &inet6_addr_lst[state->bucket], addr_lst) { | 2983 | &inet6_addr_lst[state->bucket], addr_lst) { |
| 2983 | if (net_eq(dev_net(ifa->idev->dev), net)) | 2984 | if (net_eq(dev_net(ifa->idev->dev), net)) |
| 2984 | return ifa; | 2985 | return ifa; |
| @@ -2999,7 +3000,7 @@ static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | |||
| 2999 | } | 3000 | } |
| 3000 | 3001 | ||
| 3001 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) | 3002 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) |
| 3002 | __acquires(rcu) | 3003 | __acquires(rcu_bh) |
| 3003 | { | 3004 | { |
| 3004 | rcu_read_lock_bh(); | 3005 | rcu_read_lock_bh(); |
| 3005 | return if6_get_idx(seq, *pos); | 3006 | return if6_get_idx(seq, *pos); |
| @@ -3015,7 +3016,7 @@ static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
| 3015 | } | 3016 | } |
| 3016 | 3017 | ||
| 3017 | static void if6_seq_stop(struct seq_file *seq, void *v) | 3018 | static void if6_seq_stop(struct seq_file *seq, void *v) |
| 3018 | __releases(rcu) | 3019 | __releases(rcu_bh) |
| 3019 | { | 3020 | { |
| 3020 | rcu_read_unlock_bh(); | 3021 | rcu_read_unlock_bh(); |
| 3021 | } | 3022 | } |
| @@ -3092,7 +3093,7 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
| 3092 | unsigned int hash = ipv6_addr_hash(addr); | 3093 | unsigned int hash = ipv6_addr_hash(addr); |
| 3093 | 3094 | ||
| 3094 | rcu_read_lock_bh(); | 3095 | rcu_read_lock_bh(); |
| 3095 | hlist_for_each_entry_rcu(ifp, n, &inet6_addr_lst[hash], addr_lst) { | 3096 | hlist_for_each_entry_rcu_bh(ifp, n, &inet6_addr_lst[hash], addr_lst) { |
| 3096 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 3097 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
| 3097 | continue; | 3098 | continue; |
| 3098 | if (ipv6_addr_equal(&ifp->addr, addr) && | 3099 | if (ipv6_addr_equal(&ifp->addr, addr) && |
| @@ -3126,7 +3127,7 @@ static void addrconf_verify(unsigned long foo) | |||
| 3126 | 3127 | ||
| 3127 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { | 3128 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { |
| 3128 | restart: | 3129 | restart: |
| 3129 | hlist_for_each_entry_rcu(ifp, node, | 3130 | hlist_for_each_entry_rcu_bh(ifp, node, |
| 3130 | &inet6_addr_lst[i], addr_lst) { | 3131 | &inet6_addr_lst[i], addr_lst) { |
| 3131 | unsigned long age; | 3132 | unsigned long age; |
| 3132 | 3133 | ||
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3192aa02ba5d..d2df3144429b 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
| @@ -417,6 +417,9 @@ void inet6_destroy_sock(struct sock *sk) | |||
| 417 | if ((skb = xchg(&np->pktoptions, NULL)) != NULL) | 417 | if ((skb = xchg(&np->pktoptions, NULL)) != NULL) |
| 418 | kfree_skb(skb); | 418 | kfree_skb(skb); |
| 419 | 419 | ||
| 420 | if ((skb = xchg(&np->rxpmtu, NULL)) != NULL) | ||
| 421 | kfree_skb(skb); | ||
| 422 | |||
| 420 | /* Free flowlabels */ | 423 | /* Free flowlabels */ |
| 421 | fl6_free_socklist(sk); | 424 | fl6_free_socklist(sk); |
| 422 | 425 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 622dc7939a1b..5959230bc6c1 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
| @@ -278,6 +278,45 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) | |||
| 278 | kfree_skb(skb); | 278 | kfree_skb(skb); |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | void ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu) | ||
| 282 | { | ||
| 283 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
| 284 | struct ipv6hdr *iph; | ||
| 285 | struct sk_buff *skb; | ||
| 286 | struct ip6_mtuinfo *mtu_info; | ||
| 287 | |||
| 288 | if (!np->rxopt.bits.rxpmtu) | ||
| 289 | return; | ||
| 290 | |||
| 291 | skb = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC); | ||
| 292 | if (!skb) | ||
| 293 | return; | ||
| 294 | |||
| 295 | skb_put(skb, sizeof(struct ipv6hdr)); | ||
| 296 | skb_reset_network_header(skb); | ||
| 297 | iph = ipv6_hdr(skb); | ||
| 298 | ipv6_addr_copy(&iph->daddr, &fl->fl6_dst); | ||
| 299 | |||
| 300 | mtu_info = IP6CBMTU(skb); | ||
| 301 | if (!mtu_info) { | ||
| 302 | kfree_skb(skb); | ||
| 303 | return; | ||
| 304 | } | ||
| 305 | |||
| 306 | mtu_info->ip6m_mtu = mtu; | ||
| 307 | mtu_info->ip6m_addr.sin6_family = AF_INET6; | ||
| 308 | mtu_info->ip6m_addr.sin6_port = 0; | ||
| 309 | mtu_info->ip6m_addr.sin6_flowinfo = 0; | ||
| 310 | mtu_info->ip6m_addr.sin6_scope_id = fl->oif; | ||
| 311 | ipv6_addr_copy(&mtu_info->ip6m_addr.sin6_addr, &ipv6_hdr(skb)->daddr); | ||
| 312 | |||
| 313 | __skb_pull(skb, skb_tail_pointer(skb) - skb->data); | ||
| 314 | skb_reset_transport_header(skb); | ||
| 315 | |||
| 316 | skb = xchg(&np->rxpmtu, skb); | ||
| 317 | kfree_skb(skb); | ||
| 318 | } | ||
| 319 | |||
| 281 | /* | 320 | /* |
| 282 | * Handle MSG_ERRQUEUE | 321 | * Handle MSG_ERRQUEUE |
| 283 | */ | 322 | */ |
| @@ -381,6 +420,54 @@ out: | |||
| 381 | return err; | 420 | return err; |
| 382 | } | 421 | } |
| 383 | 422 | ||
| 423 | /* | ||
| 424 | * Handle IPV6_RECVPATHMTU | ||
| 425 | */ | ||
| 426 | int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) | ||
| 427 | { | ||
| 428 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
| 429 | struct sk_buff *skb; | ||
| 430 | struct sockaddr_in6 *sin; | ||
| 431 | struct ip6_mtuinfo mtu_info; | ||
| 432 | int err; | ||
| 433 | int copied; | ||
| 434 | |||
| 435 | err = -EAGAIN; | ||
| 436 | skb = xchg(&np->rxpmtu, NULL); | ||
| 437 | if (skb == NULL) | ||
| 438 | goto out; | ||
| 439 | |||
| 440 | copied = skb->len; | ||
| 441 | if (copied > len) { | ||
| 442 | msg->msg_flags |= MSG_TRUNC; | ||
| 443 | copied = len; | ||
| 444 | } | ||
| 445 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | ||
| 446 | if (err) | ||
| 447 | goto out_free_skb; | ||
| 448 | |||
| 449 | sock_recv_timestamp(msg, sk, skb); | ||
| 450 | |||
| 451 | memcpy(&mtu_info, IP6CBMTU(skb), sizeof(mtu_info)); | ||
| 452 | |||
| 453 | sin = (struct sockaddr_in6 *)msg->msg_name; | ||
| 454 | if (sin) { | ||
| 455 | sin->sin6_family = AF_INET6; | ||
| 456 | sin->sin6_flowinfo = 0; | ||
| 457 | sin->sin6_port = 0; | ||
| 458 | sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id; | ||
| 459 | ipv6_addr_copy(&sin->sin6_addr, &mtu_info.ip6m_addr.sin6_addr); | ||
| 460 | } | ||
| 461 | |||
| 462 | put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info); | ||
| 463 | |||
| 464 | err = copied; | ||
| 465 | |||
| 466 | out_free_skb: | ||
| 467 | kfree_skb(skb); | ||
| 468 | out: | ||
| 469 | return err; | ||
| 470 | } | ||
| 384 | 471 | ||
| 385 | 472 | ||
| 386 | int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | 473 | int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) |
| @@ -497,7 +584,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
| 497 | int datagram_send_ctl(struct net *net, | 584 | int datagram_send_ctl(struct net *net, |
| 498 | struct msghdr *msg, struct flowi *fl, | 585 | struct msghdr *msg, struct flowi *fl, |
| 499 | struct ipv6_txoptions *opt, | 586 | struct ipv6_txoptions *opt, |
| 500 | int *hlimit, int *tclass) | 587 | int *hlimit, int *tclass, int *dontfrag) |
| 501 | { | 588 | { |
| 502 | struct in6_pktinfo *src_info; | 589 | struct in6_pktinfo *src_info; |
| 503 | struct cmsghdr *cmsg; | 590 | struct cmsghdr *cmsg; |
| @@ -737,6 +824,25 @@ int datagram_send_ctl(struct net *net, | |||
| 737 | 824 | ||
| 738 | break; | 825 | break; |
| 739 | } | 826 | } |
| 827 | |||
| 828 | case IPV6_DONTFRAG: | ||
| 829 | { | ||
| 830 | int df; | ||
| 831 | |||
| 832 | err = -EINVAL; | ||
| 833 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { | ||
| 834 | goto exit_f; | ||
| 835 | } | ||
| 836 | |||
| 837 | df = *(int *)CMSG_DATA(cmsg); | ||
| 838 | if (df < 0 || df > 1) | ||
| 839 | goto exit_f; | ||
| 840 | |||
| 841 | err = 0; | ||
| 842 | *dontfrag = df; | ||
| 843 | |||
| 844 | break; | ||
| 845 | } | ||
| 740 | default: | 846 | default: |
| 741 | LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", | 847 | LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", |
| 742 | cmsg->cmsg_type); | 848 | cmsg->cmsg_type); |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 8124f16f2ac2..8e44f8f9c188 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
| @@ -237,8 +237,8 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) | |||
| 237 | + nla_total_size(16); /* src */ | 237 | + nla_total_size(16); /* src */ |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | static struct fib_rules_ops fib6_rules_ops_template = { | 240 | static const struct fib_rules_ops __net_initdata fib6_rules_ops_template = { |
| 241 | .family = FIB_RULES_IPV6, | 241 | .family = AF_INET6, |
| 242 | .rule_size = sizeof(struct fib6_rule), | 242 | .rule_size = sizeof(struct fib6_rule), |
| 243 | .addr_size = sizeof(struct in6_addr), | 243 | .addr_size = sizeof(struct in6_addr), |
| 244 | .action = fib6_rule_action, | 244 | .action = fib6_rule_action, |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 12d2fa42657d..ce7992982557 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -481,7 +481,7 @@ route_done: | |||
| 481 | len + sizeof(struct icmp6hdr), | 481 | len + sizeof(struct icmp6hdr), |
| 482 | sizeof(struct icmp6hdr), hlimit, | 482 | sizeof(struct icmp6hdr), hlimit, |
| 483 | np->tclass, NULL, &fl, (struct rt6_info*)dst, | 483 | np->tclass, NULL, &fl, (struct rt6_info*)dst, |
| 484 | MSG_DONTWAIT); | 484 | MSG_DONTWAIT, np->dontfrag); |
| 485 | if (err) { | 485 | if (err) { |
| 486 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); | 486 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); |
| 487 | ip6_flush_pending_frames(sk); | 487 | ip6_flush_pending_frames(sk); |
| @@ -561,7 +561,8 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
| 561 | 561 | ||
| 562 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), | 562 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), |
| 563 | sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl, | 563 | sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl, |
| 564 | (struct rt6_info*)dst, MSG_DONTWAIT); | 564 | (struct rt6_info*)dst, MSG_DONTWAIT, |
| 565 | np->dontfrag); | ||
| 565 | 566 | ||
| 566 | if (err) { | 567 | if (err) { |
| 567 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); | 568 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index dc6e0b8f260d..92a122b7795d 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
| @@ -144,7 +144,8 @@ static __inline__ __be32 addr_bit_set(void *token, int fn_bit) | |||
| 144 | * htonl(1 << ((~fn_bit)&0x1F)) | 144 | * htonl(1 << ((~fn_bit)&0x1F)) |
| 145 | * See include/asm-generic/bitops/le.h. | 145 | * See include/asm-generic/bitops/le.h. |
| 146 | */ | 146 | */ |
| 147 | return (1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) & addr[fn_bit >> 5]; | 147 | return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) & |
| 148 | addr[fn_bit >> 5]; | ||
| 148 | } | 149 | } |
| 149 | 150 | ||
| 150 | static __inline__ struct fib6_node * node_alloc(void) | 151 | static __inline__ struct fib6_node * node_alloc(void) |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 14e23216eb28..13654686aeab 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
| @@ -360,7 +360,8 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | |||
| 360 | msg.msg_control = (void*)(fl->opt+1); | 360 | msg.msg_control = (void*)(fl->opt+1); |
| 361 | flowi.oif = 0; | 361 | flowi.oif = 0; |
| 362 | 362 | ||
| 363 | err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk, &junk); | 363 | err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk, |
| 364 | &junk, &junk); | ||
| 364 | if (err) | 365 | if (err) |
| 365 | goto done; | 366 | goto done; |
| 366 | err = -EINVAL; | 367 | err = -EINVAL; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 7f12e30cfa73..5173acaeb501 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -92,7 +92,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | |||
| 92 | newskb->ip_summed = CHECKSUM_UNNECESSARY; | 92 | newskb->ip_summed = CHECKSUM_UNNECESSARY; |
| 93 | WARN_ON(!skb_dst(newskb)); | 93 | WARN_ON(!skb_dst(newskb)); |
| 94 | 94 | ||
| 95 | netif_rx(newskb); | 95 | netif_rx_ni(newskb); |
| 96 | return 0; | 96 | return 0; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| @@ -216,8 +216,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
| 216 | } | 216 | } |
| 217 | kfree_skb(skb); | 217 | kfree_skb(skb); |
| 218 | skb = skb2; | 218 | skb = skb2; |
| 219 | if (sk) | 219 | skb_set_owner_w(skb, sk); |
| 220 | skb_set_owner_w(skb, sk); | ||
| 221 | } | 220 | } |
| 222 | if (opt->opt_flen) | 221 | if (opt->opt_flen) |
| 223 | ipv6_push_frag_opts(skb, opt, &proto); | 222 | ipv6_push_frag_opts(skb, opt, &proto); |
| @@ -623,7 +622,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 623 | /* We must not fragment if the socket is set to force MTU discovery | 622 | /* We must not fragment if the socket is set to force MTU discovery |
| 624 | * or if the skb it not generated by a local socket. | 623 | * or if the skb it not generated by a local socket. |
| 625 | */ | 624 | */ |
| 626 | if (!skb->local_df) { | 625 | if (!skb->local_df && skb->len > mtu) { |
| 627 | skb->dev = skb_dst(skb)->dev; | 626 | skb->dev = skb_dst(skb)->dev; |
| 628 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 627 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
| 629 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 628 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), |
| @@ -1103,7 +1102,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1103 | int offset, int len, int odd, struct sk_buff *skb), | 1102 | int offset, int len, int odd, struct sk_buff *skb), |
| 1104 | void *from, int length, int transhdrlen, | 1103 | void *from, int length, int transhdrlen, |
| 1105 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, | 1104 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, |
| 1106 | struct rt6_info *rt, unsigned int flags) | 1105 | struct rt6_info *rt, unsigned int flags, int dontfrag) |
| 1107 | { | 1106 | { |
| 1108 | struct inet_sock *inet = inet_sk(sk); | 1107 | struct inet_sock *inet = inet_sk(sk); |
| 1109 | struct ipv6_pinfo *np = inet6_sk(sk); | 1108 | struct ipv6_pinfo *np = inet6_sk(sk); |
| @@ -1217,15 +1216,23 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1217 | */ | 1216 | */ |
| 1218 | 1217 | ||
| 1219 | inet->cork.length += length; | 1218 | inet->cork.length += length; |
| 1220 | if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && | 1219 | if (length > mtu) { |
| 1221 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | 1220 | int proto = sk->sk_protocol; |
| 1221 | if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ | ||
| 1222 | ipv6_local_rxpmtu(sk, fl, mtu-exthdrlen); | ||
| 1223 | return -EMSGSIZE; | ||
| 1224 | } | ||
| 1222 | 1225 | ||
| 1223 | err = ip6_ufo_append_data(sk, getfrag, from, length, hh_len, | 1226 | if (proto == IPPROTO_UDP && |
| 1224 | fragheaderlen, transhdrlen, mtu, | 1227 | (rt->u.dst.dev->features & NETIF_F_UFO)) { |
| 1225 | flags); | 1228 | |
| 1226 | if (err) | 1229 | err = ip6_ufo_append_data(sk, getfrag, from, length, |
| 1227 | goto error; | 1230 | hh_len, fragheaderlen, |
| 1228 | return 0; | 1231 | transhdrlen, mtu, flags); |
| 1232 | if (err) | ||
| 1233 | goto error; | ||
| 1234 | return 0; | ||
| 1235 | } | ||
| 1229 | } | 1236 | } |
| 1230 | 1237 | ||
| 1231 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) | 1238 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 1160400e9dbd..bd43f0152c21 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
| @@ -337,6 +337,13 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 337 | retv = 0; | 337 | retv = 0; |
| 338 | break; | 338 | break; |
| 339 | 339 | ||
| 340 | case IPV6_RECVPATHMTU: | ||
| 341 | if (optlen < sizeof(int)) | ||
| 342 | goto e_inval; | ||
| 343 | np->rxopt.bits.rxpmtu = valbool; | ||
| 344 | retv = 0; | ||
| 345 | break; | ||
| 346 | |||
| 340 | case IPV6_HOPOPTS: | 347 | case IPV6_HOPOPTS: |
| 341 | case IPV6_RTHDRDSTOPTS: | 348 | case IPV6_RTHDRDSTOPTS: |
| 342 | case IPV6_RTHDR: | 349 | case IPV6_RTHDR: |
| @@ -451,7 +458,8 @@ sticky_done: | |||
| 451 | msg.msg_controllen = optlen; | 458 | msg.msg_controllen = optlen; |
| 452 | msg.msg_control = (void*)(opt+1); | 459 | msg.msg_control = (void*)(opt+1); |
| 453 | 460 | ||
| 454 | retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk); | 461 | retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk, |
| 462 | &junk); | ||
| 455 | if (retv) | 463 | if (retv) |
| 456 | goto done; | 464 | goto done; |
| 457 | update: | 465 | update: |
| @@ -767,6 +775,17 @@ pref_skip_coa: | |||
| 767 | 775 | ||
| 768 | break; | 776 | break; |
| 769 | } | 777 | } |
| 778 | case IPV6_MINHOPCOUNT: | ||
| 779 | if (optlen < sizeof(int)) | ||
| 780 | goto e_inval; | ||
| 781 | if (val < 0 || val > 255) | ||
| 782 | goto e_inval; | ||
| 783 | np->min_hopcount = val; | ||
| 784 | break; | ||
| 785 | case IPV6_DONTFRAG: | ||
| 786 | np->dontfrag = valbool; | ||
| 787 | retv = 0; | ||
| 788 | break; | ||
| 770 | } | 789 | } |
| 771 | 790 | ||
| 772 | release_sock(sk); | 791 | release_sock(sk); |
| @@ -1055,6 +1074,38 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
| 1055 | val = np->rxopt.bits.rxflow; | 1074 | val = np->rxopt.bits.rxflow; |
| 1056 | break; | 1075 | break; |
| 1057 | 1076 | ||
| 1077 | case IPV6_RECVPATHMTU: | ||
| 1078 | val = np->rxopt.bits.rxpmtu; | ||
| 1079 | break; | ||
| 1080 | |||
| 1081 | case IPV6_PATHMTU: | ||
| 1082 | { | ||
| 1083 | struct dst_entry *dst; | ||
| 1084 | struct ip6_mtuinfo mtuinfo; | ||
| 1085 | |||
| 1086 | if (len < sizeof(mtuinfo)) | ||
| 1087 | return -EINVAL; | ||
| 1088 | |||
| 1089 | len = sizeof(mtuinfo); | ||
| 1090 | memset(&mtuinfo, 0, sizeof(mtuinfo)); | ||
| 1091 | |||
| 1092 | rcu_read_lock(); | ||
| 1093 | dst = __sk_dst_get(sk); | ||
| 1094 | if (dst) | ||
| 1095 | mtuinfo.ip6m_mtu = dst_mtu(dst); | ||
| 1096 | rcu_read_unlock(); | ||
| 1097 | if (!mtuinfo.ip6m_mtu) | ||
| 1098 | return -ENOTCONN; | ||
| 1099 | |||
| 1100 | if (put_user(len, optlen)) | ||
| 1101 | return -EFAULT; | ||
| 1102 | if (copy_to_user(optval, &mtuinfo, len)) | ||
| 1103 | return -EFAULT; | ||
| 1104 | |||
| 1105 | return 0; | ||
| 1106 | break; | ||
| 1107 | } | ||
| 1108 | |||
| 1058 | case IPV6_UNICAST_HOPS: | 1109 | case IPV6_UNICAST_HOPS: |
| 1059 | case IPV6_MULTICAST_HOPS: | 1110 | case IPV6_MULTICAST_HOPS: |
| 1060 | { | 1111 | { |
| @@ -1116,6 +1167,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
| 1116 | val |= IPV6_PREFER_SRC_HOME; | 1167 | val |= IPV6_PREFER_SRC_HOME; |
| 1117 | break; | 1168 | break; |
| 1118 | 1169 | ||
| 1170 | case IPV6_MINHOPCOUNT: | ||
| 1171 | val = np->min_hopcount; | ||
| 1172 | break; | ||
| 1173 | |||
| 1174 | case IPV6_DONTFRAG: | ||
| 1175 | val = np->dontfrag; | ||
| 1176 | break; | ||
| 1177 | |||
| 1119 | default: | 1178 | default: |
| 1120 | return -ENOPROTOOPT; | 1179 | return -ENOPROTOOPT; |
| 1121 | } | 1180 | } |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index f9d05ce4e03a..59f1881968c7 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include <linux/proc_fs.h> | 44 | #include <linux/proc_fs.h> |
| 45 | #include <linux/seq_file.h> | 45 | #include <linux/seq_file.h> |
| 46 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
| 47 | #include <net/mld.h> | ||
| 47 | 48 | ||
| 48 | #include <linux/netfilter.h> | 49 | #include <linux/netfilter.h> |
| 49 | #include <linux/netfilter_ipv6.h> | 50 | #include <linux/netfilter_ipv6.h> |
| @@ -71,54 +72,11 @@ | |||
| 71 | #define MDBG(x) | 72 | #define MDBG(x) |
| 72 | #endif | 73 | #endif |
| 73 | 74 | ||
| 74 | /* | 75 | /* Ensure that we have struct in6_addr aligned on 32bit word. */ |
| 75 | * These header formats should be in a separate include file, but icmpv6.h | 76 | static void *__mld2_query_bugs[] __attribute__((__unused__)) = { |
| 76 | * doesn't have in6_addr defined in all cases, there is no __u128, and no | 77 | BUILD_BUG_ON_NULL(offsetof(struct mld2_query, mld2q_srcs) % 4), |
| 77 | * other files reference these. | 78 | BUILD_BUG_ON_NULL(offsetof(struct mld2_report, mld2r_grec) % 4), |
| 78 | * | 79 | BUILD_BUG_ON_NULL(offsetof(struct mld2_grec, grec_mca) % 4) |
| 79 | * +-DLS 4/14/03 | ||
| 80 | */ | ||
| 81 | |||
| 82 | /* Multicast Listener Discovery version 2 headers */ | ||
| 83 | |||
| 84 | struct mld2_grec { | ||
| 85 | __u8 grec_type; | ||
| 86 | __u8 grec_auxwords; | ||
| 87 | __be16 grec_nsrcs; | ||
| 88 | struct in6_addr grec_mca; | ||
| 89 | struct in6_addr grec_src[0]; | ||
| 90 | }; | ||
| 91 | |||
| 92 | struct mld2_report { | ||
| 93 | __u8 type; | ||
| 94 | __u8 resv1; | ||
| 95 | __sum16 csum; | ||
| 96 | __be16 resv2; | ||
| 97 | __be16 ngrec; | ||
| 98 | struct mld2_grec grec[0]; | ||
| 99 | }; | ||
| 100 | |||
| 101 | struct mld2_query { | ||
| 102 | __u8 type; | ||
| 103 | __u8 code; | ||
| 104 | __sum16 csum; | ||
| 105 | __be16 mrc; | ||
| 106 | __be16 resv1; | ||
| 107 | struct in6_addr mca; | ||
| 108 | #if defined(__LITTLE_ENDIAN_BITFIELD) | ||
| 109 | __u8 qrv:3, | ||
| 110 | suppress:1, | ||
| 111 | resv2:4; | ||
| 112 | #elif defined(__BIG_ENDIAN_BITFIELD) | ||
| 113 | __u8 resv2:4, | ||
| 114 | suppress:1, | ||
| 115 | qrv:3; | ||
| 116 | #else | ||
| 117 | #error "Please fix <asm/byteorder.h>" | ||
| 118 | #endif | ||
| 119 | __u8 qqic; | ||
| 120 | __be16 nsrcs; | ||
| 121 | struct in6_addr srcs[0]; | ||
| 122 | }; | 80 | }; |
| 123 | 81 | ||
| 124 | static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; | 82 | static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; |
| @@ -157,14 +115,6 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, | |||
| 157 | ((idev)->mc_v1_seen && \ | 115 | ((idev)->mc_v1_seen && \ |
| 158 | time_before(jiffies, (idev)->mc_v1_seen))) | 116 | time_before(jiffies, (idev)->mc_v1_seen))) |
| 159 | 117 | ||
| 160 | #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) | ||
| 161 | #define MLDV2_EXP(thresh, nbmant, nbexp, value) \ | ||
| 162 | ((value) < (thresh) ? (value) : \ | ||
| 163 | ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ | ||
| 164 | (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) | ||
| 165 | |||
| 166 | #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) | ||
| 167 | |||
| 168 | #define IPV6_MLD_MAX_MSF 64 | 118 | #define IPV6_MLD_MAX_MSF 64 |
| 169 | 119 | ||
| 170 | int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; | 120 | int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; |
| @@ -1161,7 +1111,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1161 | struct in6_addr *group; | 1111 | struct in6_addr *group; |
| 1162 | unsigned long max_delay; | 1112 | unsigned long max_delay; |
| 1163 | struct inet6_dev *idev; | 1113 | struct inet6_dev *idev; |
| 1164 | struct icmp6hdr *hdr; | 1114 | struct mld_msg *mld; |
| 1165 | int group_type; | 1115 | int group_type; |
| 1166 | int mark = 0; | 1116 | int mark = 0; |
| 1167 | int len; | 1117 | int len; |
| @@ -1182,8 +1132,8 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1182 | if (idev == NULL) | 1132 | if (idev == NULL) |
| 1183 | return 0; | 1133 | return 0; |
| 1184 | 1134 | ||
| 1185 | hdr = icmp6_hdr(skb); | 1135 | mld = (struct mld_msg *)icmp6_hdr(skb); |
| 1186 | group = (struct in6_addr *) (hdr + 1); | 1136 | group = &mld->mld_mca; |
| 1187 | group_type = ipv6_addr_type(group); | 1137 | group_type = ipv6_addr_type(group); |
| 1188 | 1138 | ||
| 1189 | if (group_type != IPV6_ADDR_ANY && | 1139 | if (group_type != IPV6_ADDR_ANY && |
| @@ -1197,7 +1147,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1197 | /* MLDv1 router present */ | 1147 | /* MLDv1 router present */ |
| 1198 | 1148 | ||
| 1199 | /* Translate milliseconds to jiffies */ | 1149 | /* Translate milliseconds to jiffies */ |
| 1200 | max_delay = (ntohs(hdr->icmp6_maxdelay)*HZ)/1000; | 1150 | max_delay = (ntohs(mld->mld_maxdelay)*HZ)/1000; |
| 1201 | 1151 | ||
| 1202 | switchback = (idev->mc_qrv + 1) * max_delay; | 1152 | switchback = (idev->mc_qrv + 1) * max_delay; |
| 1203 | idev->mc_v1_seen = jiffies + switchback; | 1153 | idev->mc_v1_seen = jiffies + switchback; |
| @@ -1216,14 +1166,14 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1216 | return -EINVAL; | 1166 | return -EINVAL; |
| 1217 | } | 1167 | } |
| 1218 | mlh2 = (struct mld2_query *)skb_transport_header(skb); | 1168 | mlh2 = (struct mld2_query *)skb_transport_header(skb); |
| 1219 | max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; | 1169 | max_delay = (MLDV2_MRC(ntohs(mlh2->mld2q_mrc))*HZ)/1000; |
| 1220 | if (!max_delay) | 1170 | if (!max_delay) |
| 1221 | max_delay = 1; | 1171 | max_delay = 1; |
| 1222 | idev->mc_maxdelay = max_delay; | 1172 | idev->mc_maxdelay = max_delay; |
| 1223 | if (mlh2->qrv) | 1173 | if (mlh2->mld2q_qrv) |
| 1224 | idev->mc_qrv = mlh2->qrv; | 1174 | idev->mc_qrv = mlh2->mld2q_qrv; |
| 1225 | if (group_type == IPV6_ADDR_ANY) { /* general query */ | 1175 | if (group_type == IPV6_ADDR_ANY) { /* general query */ |
| 1226 | if (mlh2->nsrcs) { | 1176 | if (mlh2->mld2q_nsrcs) { |
| 1227 | in6_dev_put(idev); | 1177 | in6_dev_put(idev); |
| 1228 | return -EINVAL; /* no sources allowed */ | 1178 | return -EINVAL; /* no sources allowed */ |
| 1229 | } | 1179 | } |
| @@ -1232,9 +1182,9 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1232 | return 0; | 1182 | return 0; |
| 1233 | } | 1183 | } |
| 1234 | /* mark sources to include, if group & source-specific */ | 1184 | /* mark sources to include, if group & source-specific */ |
| 1235 | if (mlh2->nsrcs != 0) { | 1185 | if (mlh2->mld2q_nsrcs != 0) { |
| 1236 | if (!pskb_may_pull(skb, srcs_offset + | 1186 | if (!pskb_may_pull(skb, srcs_offset + |
| 1237 | ntohs(mlh2->nsrcs) * sizeof(struct in6_addr))) { | 1187 | ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) { |
| 1238 | in6_dev_put(idev); | 1188 | in6_dev_put(idev); |
| 1239 | return -EINVAL; | 1189 | return -EINVAL; |
| 1240 | } | 1190 | } |
| @@ -1270,7 +1220,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1270 | ma->mca_flags &= ~MAF_GSQUERY; | 1220 | ma->mca_flags &= ~MAF_GSQUERY; |
| 1271 | } | 1221 | } |
| 1272 | if (!(ma->mca_flags & MAF_GSQUERY) || | 1222 | if (!(ma->mca_flags & MAF_GSQUERY) || |
| 1273 | mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs)) | 1223 | mld_marksources(ma, ntohs(mlh2->mld2q_nsrcs), mlh2->mld2q_srcs)) |
| 1274 | igmp6_group_queried(ma, max_delay); | 1224 | igmp6_group_queried(ma, max_delay); |
| 1275 | spin_unlock_bh(&ma->mca_lock); | 1225 | spin_unlock_bh(&ma->mca_lock); |
| 1276 | break; | 1226 | break; |
| @@ -1286,9 +1236,8 @@ int igmp6_event_query(struct sk_buff *skb) | |||
| 1286 | int igmp6_event_report(struct sk_buff *skb) | 1236 | int igmp6_event_report(struct sk_buff *skb) |
| 1287 | { | 1237 | { |
| 1288 | struct ifmcaddr6 *ma; | 1238 | struct ifmcaddr6 *ma; |
| 1289 | struct in6_addr *addrp; | ||
| 1290 | struct inet6_dev *idev; | 1239 | struct inet6_dev *idev; |
| 1291 | struct icmp6hdr *hdr; | 1240 | struct mld_msg *mld; |
| 1292 | int addr_type; | 1241 | int addr_type; |
| 1293 | 1242 | ||
| 1294 | /* Our own report looped back. Ignore it. */ | 1243 | /* Our own report looped back. Ignore it. */ |
| @@ -1300,10 +1249,10 @@ int igmp6_event_report(struct sk_buff *skb) | |||
| 1300 | skb->pkt_type != PACKET_BROADCAST) | 1249 | skb->pkt_type != PACKET_BROADCAST) |
| 1301 | return 0; | 1250 | return 0; |
| 1302 | 1251 | ||
| 1303 | if (!pskb_may_pull(skb, sizeof(struct in6_addr))) | 1252 | if (!pskb_may_pull(skb, sizeof(*mld) - sizeof(struct icmp6hdr))) |
| 1304 | return -EINVAL; | 1253 | return -EINVAL; |
| 1305 | 1254 | ||
| 1306 | hdr = icmp6_hdr(skb); | 1255 | mld = (struct mld_msg *)icmp6_hdr(skb); |
| 1307 | 1256 | ||
| 1308 | /* Drop reports with not link local source */ | 1257 | /* Drop reports with not link local source */ |
| 1309 | addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); | 1258 | addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); |
| @@ -1311,8 +1260,6 @@ int igmp6_event_report(struct sk_buff *skb) | |||
| 1311 | !(addr_type&IPV6_ADDR_LINKLOCAL)) | 1260 | !(addr_type&IPV6_ADDR_LINKLOCAL)) |
| 1312 | return -EINVAL; | 1261 | return -EINVAL; |
| 1313 | 1262 | ||
| 1314 | addrp = (struct in6_addr *) (hdr + 1); | ||
| 1315 | |||
| 1316 | idev = in6_dev_get(skb->dev); | 1263 | idev = in6_dev_get(skb->dev); |
| 1317 | if (idev == NULL) | 1264 | if (idev == NULL) |
| 1318 | return -ENODEV; | 1265 | return -ENODEV; |
| @@ -1323,7 +1270,7 @@ int igmp6_event_report(struct sk_buff *skb) | |||
| 1323 | 1270 | ||
| 1324 | read_lock_bh(&idev->lock); | 1271 | read_lock_bh(&idev->lock); |
| 1325 | for (ma = idev->mc_list; ma; ma=ma->next) { | 1272 | for (ma = idev->mc_list; ma; ma=ma->next) { |
| 1326 | if (ipv6_addr_equal(&ma->mca_addr, addrp)) { | 1273 | if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) { |
| 1327 | spin_lock(&ma->mca_lock); | 1274 | spin_lock(&ma->mca_lock); |
| 1328 | if (del_timer(&ma->mca_timer)) | 1275 | if (del_timer(&ma->mca_timer)) |
| 1329 | atomic_dec(&ma->mca_refcnt); | 1276 | atomic_dec(&ma->mca_refcnt); |
| @@ -1432,11 +1379,11 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
| 1432 | skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); | 1379 | skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); |
| 1433 | skb_put(skb, sizeof(*pmr)); | 1380 | skb_put(skb, sizeof(*pmr)); |
| 1434 | pmr = (struct mld2_report *)skb_transport_header(skb); | 1381 | pmr = (struct mld2_report *)skb_transport_header(skb); |
| 1435 | pmr->type = ICMPV6_MLD2_REPORT; | 1382 | pmr->mld2r_type = ICMPV6_MLD2_REPORT; |
| 1436 | pmr->resv1 = 0; | 1383 | pmr->mld2r_resv1 = 0; |
| 1437 | pmr->csum = 0; | 1384 | pmr->mld2r_cksum = 0; |
| 1438 | pmr->resv2 = 0; | 1385 | pmr->mld2r_resv2 = 0; |
| 1439 | pmr->ngrec = 0; | 1386 | pmr->mld2r_ngrec = 0; |
| 1440 | return skb; | 1387 | return skb; |
| 1441 | } | 1388 | } |
| 1442 | 1389 | ||
| @@ -1458,9 +1405,10 @@ static void mld_sendpack(struct sk_buff *skb) | |||
| 1458 | mldlen = skb->tail - skb->transport_header; | 1405 | mldlen = skb->tail - skb->transport_header; |
| 1459 | pip6->payload_len = htons(payload_len); | 1406 | pip6->payload_len = htons(payload_len); |
| 1460 | 1407 | ||
| 1461 | pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, | 1408 | pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, |
| 1462 | IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), | 1409 | IPPROTO_ICMPV6, |
| 1463 | mldlen, 0)); | 1410 | csum_partial(skb_transport_header(skb), |
| 1411 | mldlen, 0)); | ||
| 1464 | 1412 | ||
| 1465 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); | 1413 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); |
| 1466 | 1414 | ||
| @@ -1521,7 +1469,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
| 1521 | pgr->grec_nsrcs = 0; | 1469 | pgr->grec_nsrcs = 0; |
| 1522 | pgr->grec_mca = pmc->mca_addr; /* structure copy */ | 1470 | pgr->grec_mca = pmc->mca_addr; /* structure copy */ |
| 1523 | pmr = (struct mld2_report *)skb_transport_header(skb); | 1471 | pmr = (struct mld2_report *)skb_transport_header(skb); |
| 1524 | pmr->ngrec = htons(ntohs(pmr->ngrec)+1); | 1472 | pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1); |
| 1525 | *ppgr = pgr; | 1473 | *ppgr = pgr; |
| 1526 | return skb; | 1474 | return skb; |
| 1527 | } | 1475 | } |
| @@ -1557,7 +1505,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
| 1557 | 1505 | ||
| 1558 | /* EX and TO_EX get a fresh packet, if needed */ | 1506 | /* EX and TO_EX get a fresh packet, if needed */ |
| 1559 | if (truncate) { | 1507 | if (truncate) { |
| 1560 | if (pmr && pmr->ngrec && | 1508 | if (pmr && pmr->mld2r_ngrec && |
| 1561 | AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { | 1509 | AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { |
| 1562 | if (skb) | 1510 | if (skb) |
| 1563 | mld_sendpack(skb); | 1511 | mld_sendpack(skb); |
| @@ -1770,9 +1718,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
| 1770 | struct sock *sk = net->ipv6.igmp_sk; | 1718 | struct sock *sk = net->ipv6.igmp_sk; |
| 1771 | struct inet6_dev *idev; | 1719 | struct inet6_dev *idev; |
| 1772 | struct sk_buff *skb; | 1720 | struct sk_buff *skb; |
| 1773 | struct icmp6hdr *hdr; | 1721 | struct mld_msg *hdr; |
| 1774 | const struct in6_addr *snd_addr, *saddr; | 1722 | const struct in6_addr *snd_addr, *saddr; |
| 1775 | struct in6_addr *addrp; | ||
| 1776 | struct in6_addr addr_buf; | 1723 | struct in6_addr addr_buf; |
| 1777 | int err, len, payload_len, full_len; | 1724 | int err, len, payload_len, full_len; |
| 1778 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1725 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
| @@ -1820,16 +1767,14 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
| 1820 | 1767 | ||
| 1821 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); | 1768 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); |
| 1822 | 1769 | ||
| 1823 | hdr = (struct icmp6hdr *) skb_put(skb, sizeof(struct icmp6hdr)); | 1770 | hdr = (struct mld_msg *) skb_put(skb, sizeof(struct mld_msg)); |
| 1824 | memset(hdr, 0, sizeof(struct icmp6hdr)); | 1771 | memset(hdr, 0, sizeof(struct mld_msg)); |
| 1825 | hdr->icmp6_type = type; | 1772 | hdr->mld_type = type; |
| 1773 | ipv6_addr_copy(&hdr->mld_mca, addr); | ||
| 1826 | 1774 | ||
| 1827 | addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr)); | 1775 | hdr->mld_cksum = csum_ipv6_magic(saddr, snd_addr, len, |
| 1828 | ipv6_addr_copy(addrp, addr); | 1776 | IPPROTO_ICMPV6, |
| 1829 | 1777 | csum_partial(hdr, len, 0)); | |
| 1830 | hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len, | ||
| 1831 | IPPROTO_ICMPV6, | ||
| 1832 | csum_partial(hdr, len, 0)); | ||
| 1833 | 1778 | ||
| 1834 | idev = in6_dev_get(skb->dev); | 1779 | idev = in6_dev_get(skb->dev); |
| 1835 | 1780 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 554b48b6e993..4a4dcbe4f8b2 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
| @@ -381,7 +381,7 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) | |||
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | /* Charge it to the socket. */ | 383 | /* Charge it to the socket. */ |
| 384 | if (sock_queue_rcv_skb(sk, skb) < 0) { | 384 | if (ip_queue_rcv_skb(sk, skb) < 0) { |
| 385 | kfree_skb(skb); | 385 | kfree_skb(skb); |
| 386 | return NET_RX_DROP; | 386 | return NET_RX_DROP; |
| 387 | } | 387 | } |
| @@ -461,6 +461,9 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
| 461 | if (flags & MSG_ERRQUEUE) | 461 | if (flags & MSG_ERRQUEUE) |
| 462 | return ipv6_recv_error(sk, msg, len); | 462 | return ipv6_recv_error(sk, msg, len); |
| 463 | 463 | ||
| 464 | if (np->rxpmtu && np->rxopt.bits.rxpmtu) | ||
| 465 | return ipv6_recv_rxpmtu(sk, msg, len); | ||
| 466 | |||
| 464 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 467 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
| 465 | if (!skb) | 468 | if (!skb) |
| 466 | goto out; | 469 | goto out; |
| @@ -733,6 +736,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 733 | int addr_len = msg->msg_namelen; | 736 | int addr_len = msg->msg_namelen; |
| 734 | int hlimit = -1; | 737 | int hlimit = -1; |
| 735 | int tclass = -1; | 738 | int tclass = -1; |
| 739 | int dontfrag = -1; | ||
| 736 | u16 proto; | 740 | u16 proto; |
| 737 | int err; | 741 | int err; |
| 738 | 742 | ||
| @@ -811,7 +815,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 811 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 815 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
| 812 | opt->tot_len = sizeof(struct ipv6_txoptions); | 816 | opt->tot_len = sizeof(struct ipv6_txoptions); |
| 813 | 817 | ||
| 814 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, &tclass); | 818 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, |
| 819 | &tclass, &dontfrag); | ||
| 815 | if (err < 0) { | 820 | if (err < 0) { |
| 816 | fl6_sock_release(flowlabel); | 821 | fl6_sock_release(flowlabel); |
| 817 | return err; | 822 | return err; |
| @@ -880,6 +885,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 880 | if (tclass < 0) | 885 | if (tclass < 0) |
| 881 | tclass = np->tclass; | 886 | tclass = np->tclass; |
| 882 | 887 | ||
| 888 | if (dontfrag < 0) | ||
| 889 | dontfrag = np->dontfrag; | ||
| 890 | |||
| 883 | if (msg->msg_flags&MSG_CONFIRM) | 891 | if (msg->msg_flags&MSG_CONFIRM) |
| 884 | goto do_confirm; | 892 | goto do_confirm; |
| 885 | 893 | ||
| @@ -890,7 +898,7 @@ back_from_confirm: | |||
| 890 | lock_sock(sk); | 898 | lock_sock(sk); |
| 891 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, | 899 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, |
| 892 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, | 900 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, |
| 893 | msg->msg_flags); | 901 | msg->msg_flags, dontfrag); |
| 894 | 902 | ||
| 895 | if (err) | 903 | if (err) |
| 896 | ip6_flush_pending_frames(sk); | 904 | ip6_flush_pending_frames(sk); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c2438e8cb9d0..05ebd7833043 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -815,7 +815,7 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, | |||
| 815 | { | 815 | { |
| 816 | int flags = 0; | 816 | int flags = 0; |
| 817 | 817 | ||
| 818 | if (rt6_need_strict(&fl->fl6_dst)) | 818 | if (fl->oif || rt6_need_strict(&fl->fl6_dst)) |
| 819 | flags |= RT6_LOOKUP_F_IFACE; | 819 | flags |= RT6_LOOKUP_F_IFACE; |
| 820 | 820 | ||
| 821 | if (!ipv6_addr_any(&fl->fl6_src)) | 821 | if (!ipv6_addr_any(&fl->fl6_src)) |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index bd5ef7b6e48e..6603511e3673 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -353,6 +353,11 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 353 | if (sk->sk_state == TCP_CLOSE) | 353 | if (sk->sk_state == TCP_CLOSE) |
| 354 | goto out; | 354 | goto out; |
| 355 | 355 | ||
| 356 | if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) { | ||
| 357 | NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); | ||
| 358 | goto out; | ||
| 359 | } | ||
| 360 | |||
| 356 | tp = tcp_sk(sk); | 361 | tp = tcp_sk(sk); |
| 357 | seq = ntohl(th->seq); | 362 | seq = ntohl(th->seq); |
| 358 | if (sk->sk_state != TCP_LISTEN && | 363 | if (sk->sk_state != TCP_LISTEN && |
| @@ -1018,7 +1023,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
| 1018 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); | 1023 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); |
| 1019 | 1024 | ||
| 1020 | t1 = (struct tcphdr *) skb_push(buff, tot_len); | 1025 | t1 = (struct tcphdr *) skb_push(buff, tot_len); |
| 1021 | skb_reset_transport_header(skb); | 1026 | skb_reset_transport_header(buff); |
| 1022 | 1027 | ||
| 1023 | /* Swap the send and the receive. */ | 1028 | /* Swap the send and the receive. */ |
| 1024 | memset(t1, 0, sizeof(*t1)); | 1029 | memset(t1, 0, sizeof(*t1)); |
| @@ -1050,12 +1055,13 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
| 1050 | } | 1055 | } |
| 1051 | #endif | 1056 | #endif |
| 1052 | 1057 | ||
| 1053 | buff->csum = csum_partial(t1, tot_len, 0); | ||
| 1054 | |||
| 1055 | memset(&fl, 0, sizeof(fl)); | 1058 | memset(&fl, 0, sizeof(fl)); |
| 1056 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); | 1059 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); |
| 1057 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); | 1060 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); |
| 1058 | 1061 | ||
| 1062 | buff->ip_summed = CHECKSUM_PARTIAL; | ||
| 1063 | buff->csum = 0; | ||
| 1064 | |||
| 1059 | __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst); | 1065 | __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst); |
| 1060 | 1066 | ||
| 1061 | fl.proto = IPPROTO_TCP; | 1067 | fl.proto = IPPROTO_TCP; |
| @@ -1234,12 +1240,12 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
| 1234 | goto drop_and_free; | 1240 | goto drop_and_free; |
| 1235 | 1241 | ||
| 1236 | /* Secret recipe starts with IP addresses */ | 1242 | /* Secret recipe starts with IP addresses */ |
| 1237 | d = &ipv6_hdr(skb)->daddr.s6_addr32[0]; | 1243 | d = (__force u32 *)&ipv6_hdr(skb)->daddr.s6_addr32[0]; |
| 1238 | *mess++ ^= *d++; | 1244 | *mess++ ^= *d++; |
| 1239 | *mess++ ^= *d++; | 1245 | *mess++ ^= *d++; |
| 1240 | *mess++ ^= *d++; | 1246 | *mess++ ^= *d++; |
| 1241 | *mess++ ^= *d++; | 1247 | *mess++ ^= *d++; |
| 1242 | d = &ipv6_hdr(skb)->saddr.s6_addr32[0]; | 1248 | d = (__force u32 *)&ipv6_hdr(skb)->saddr.s6_addr32[0]; |
| 1243 | *mess++ ^= *d++; | 1249 | *mess++ ^= *d++; |
| 1244 | *mess++ ^= *d++; | 1250 | *mess++ ^= *d++; |
| 1245 | *mess++ ^= *d++; | 1251 | *mess++ ^= *d++; |
| @@ -1677,6 +1683,7 @@ ipv6_pktoptions: | |||
| 1677 | static int tcp_v6_rcv(struct sk_buff *skb) | 1683 | static int tcp_v6_rcv(struct sk_buff *skb) |
| 1678 | { | 1684 | { |
| 1679 | struct tcphdr *th; | 1685 | struct tcphdr *th; |
| 1686 | struct ipv6hdr *hdr; | ||
| 1680 | struct sock *sk; | 1687 | struct sock *sk; |
| 1681 | int ret; | 1688 | int ret; |
| 1682 | struct net *net = dev_net(skb->dev); | 1689 | struct net *net = dev_net(skb->dev); |
| @@ -1703,12 +1710,13 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
| 1703 | goto bad_packet; | 1710 | goto bad_packet; |
| 1704 | 1711 | ||
| 1705 | th = tcp_hdr(skb); | 1712 | th = tcp_hdr(skb); |
| 1713 | hdr = ipv6_hdr(skb); | ||
| 1706 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | 1714 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); |
| 1707 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + | 1715 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + |
| 1708 | skb->len - th->doff*4); | 1716 | skb->len - th->doff*4); |
| 1709 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | 1717 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); |
| 1710 | TCP_SKB_CB(skb)->when = 0; | 1718 | TCP_SKB_CB(skb)->when = 0; |
| 1711 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); | 1719 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(hdr); |
| 1712 | TCP_SKB_CB(skb)->sacked = 0; | 1720 | TCP_SKB_CB(skb)->sacked = 0; |
| 1713 | 1721 | ||
| 1714 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); | 1722 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); |
| @@ -1719,6 +1727,11 @@ process: | |||
| 1719 | if (sk->sk_state == TCP_TIME_WAIT) | 1727 | if (sk->sk_state == TCP_TIME_WAIT) |
| 1720 | goto do_time_wait; | 1728 | goto do_time_wait; |
| 1721 | 1729 | ||
| 1730 | if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) { | ||
| 1731 | NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); | ||
| 1732 | goto discard_and_relse; | ||
| 1733 | } | ||
| 1734 | |||
| 1722 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 1735 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
| 1723 | goto discard_and_relse; | 1736 | goto discard_and_relse; |
| 1724 | 1737 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 90824852f598..3d7a2c0b836a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -91,9 +91,9 @@ static unsigned int udp6_portaddr_hash(struct net *net, | |||
| 91 | if (ipv6_addr_any(addr6)) | 91 | if (ipv6_addr_any(addr6)) |
| 92 | hash = jhash_1word(0, mix); | 92 | hash = jhash_1word(0, mix); |
| 93 | else if (ipv6_addr_v4mapped(addr6)) | 93 | else if (ipv6_addr_v4mapped(addr6)) |
| 94 | hash = jhash_1word(addr6->s6_addr32[3], mix); | 94 | hash = jhash_1word((__force u32)addr6->s6_addr32[3], mix); |
| 95 | else | 95 | else |
| 96 | hash = jhash2(addr6->s6_addr32, 4, mix); | 96 | hash = jhash2((__force u32 *)addr6->s6_addr32, 4, mix); |
| 97 | 97 | ||
| 98 | return hash ^ port; | 98 | return hash ^ port; |
| 99 | } | 99 | } |
| @@ -335,6 +335,9 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
| 335 | if (flags & MSG_ERRQUEUE) | 335 | if (flags & MSG_ERRQUEUE) |
| 336 | return ipv6_recv_error(sk, msg, len); | 336 | return ipv6_recv_error(sk, msg, len); |
| 337 | 337 | ||
| 338 | if (np->rxpmtu && np->rxopt.bits.rxpmtu) | ||
| 339 | return ipv6_recv_rxpmtu(sk, msg, len); | ||
| 340 | |||
| 338 | try_again: | 341 | try_again: |
| 339 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), | 342 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), |
| 340 | &peeked, &err); | 343 | &peeked, &err); |
| @@ -421,7 +424,7 @@ out: | |||
| 421 | return err; | 424 | return err; |
| 422 | 425 | ||
| 423 | csum_copy_err: | 426 | csum_copy_err: |
| 424 | lock_sock(sk); | 427 | lock_sock_bh(sk); |
| 425 | if (!skb_kill_datagram(sk, skb, flags)) { | 428 | if (!skb_kill_datagram(sk, skb, flags)) { |
| 426 | if (is_udp4) | 429 | if (is_udp4) |
| 427 | UDP_INC_STATS_USER(sock_net(sk), | 430 | UDP_INC_STATS_USER(sock_net(sk), |
| @@ -430,7 +433,7 @@ csum_copy_err: | |||
| 430 | UDP6_INC_STATS_USER(sock_net(sk), | 433 | UDP6_INC_STATS_USER(sock_net(sk), |
| 431 | UDP_MIB_INERRORS, is_udplite); | 434 | UDP_MIB_INERRORS, is_udplite); |
| 432 | } | 435 | } |
| 433 | release_sock(sk); | 436 | unlock_sock_bh(sk); |
| 434 | 437 | ||
| 435 | if (flags & MSG_DONTWAIT) | 438 | if (flags & MSG_DONTWAIT) |
| 436 | return -EAGAIN; | 439 | return -EAGAIN; |
| @@ -511,7 +514,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
| 511 | goto drop; | 514 | goto drop; |
| 512 | } | 515 | } |
| 513 | 516 | ||
| 514 | if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { | 517 | if ((rc = ip_queue_rcv_skb(sk, skb)) < 0) { |
| 515 | /* Note that an ENOMEM error is charged twice */ | 518 | /* Note that an ENOMEM error is charged twice */ |
| 516 | if (rc == -ENOMEM) | 519 | if (rc == -ENOMEM) |
| 517 | UDP6_INC_STATS_BH(sock_net(sk), | 520 | UDP6_INC_STATS_BH(sock_net(sk), |
| @@ -581,6 +584,10 @@ static void flush_stack(struct sock **stack, unsigned int count, | |||
| 581 | 584 | ||
| 582 | sk = stack[i]; | 585 | sk = stack[i]; |
| 583 | if (skb1) { | 586 | if (skb1) { |
| 587 | if (sk_rcvqueues_full(sk, skb)) { | ||
| 588 | kfree_skb(skb1); | ||
| 589 | goto drop; | ||
| 590 | } | ||
| 584 | bh_lock_sock(sk); | 591 | bh_lock_sock(sk); |
| 585 | if (!sock_owned_by_user(sk)) | 592 | if (!sock_owned_by_user(sk)) |
| 586 | udpv6_queue_rcv_skb(sk, skb1); | 593 | udpv6_queue_rcv_skb(sk, skb1); |
| @@ -692,7 +699,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
| 692 | u32 ulen = 0; | 699 | u32 ulen = 0; |
| 693 | 700 | ||
| 694 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) | 701 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) |
| 695 | goto short_packet; | 702 | goto discard; |
| 696 | 703 | ||
| 697 | saddr = &ipv6_hdr(skb)->saddr; | 704 | saddr = &ipv6_hdr(skb)->saddr; |
| 698 | daddr = &ipv6_hdr(skb)->daddr; | 705 | daddr = &ipv6_hdr(skb)->daddr; |
| @@ -756,6 +763,10 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
| 756 | 763 | ||
| 757 | /* deliver */ | 764 | /* deliver */ |
| 758 | 765 | ||
| 766 | if (sk_rcvqueues_full(sk, skb)) { | ||
| 767 | sock_put(sk); | ||
| 768 | goto discard; | ||
| 769 | } | ||
| 759 | bh_lock_sock(sk); | 770 | bh_lock_sock(sk); |
| 760 | if (!sock_owned_by_user(sk)) | 771 | if (!sock_owned_by_user(sk)) |
| 761 | udpv6_queue_rcv_skb(sk, skb); | 772 | udpv6_queue_rcv_skb(sk, skb); |
| @@ -770,9 +781,14 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
| 770 | return 0; | 781 | return 0; |
| 771 | 782 | ||
| 772 | short_packet: | 783 | short_packet: |
| 773 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n", | 784 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: From [%pI6c]:%u %d/%d to [%pI6c]:%u\n", |
| 774 | proto == IPPROTO_UDPLITE ? "-Lite" : "", | 785 | proto == IPPROTO_UDPLITE ? "-Lite" : "", |
| 775 | ulen, skb->len); | 786 | saddr, |
| 787 | ntohs(uh->source), | ||
| 788 | ulen, | ||
| 789 | skb->len, | ||
| 790 | daddr, | ||
| 791 | ntohs(uh->dest)); | ||
| 776 | 792 | ||
| 777 | discard: | 793 | discard: |
| 778 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); | 794 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); |
| @@ -919,6 +935,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 919 | int ulen = len; | 935 | int ulen = len; |
| 920 | int hlimit = -1; | 936 | int hlimit = -1; |
| 921 | int tclass = -1; | 937 | int tclass = -1; |
| 938 | int dontfrag = -1; | ||
| 922 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 939 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; |
| 923 | int err; | 940 | int err; |
| 924 | int connected = 0; | 941 | int connected = 0; |
| @@ -1049,7 +1066,8 @@ do_udp_sendmsg: | |||
| 1049 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 1066 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
| 1050 | opt->tot_len = sizeof(*opt); | 1067 | opt->tot_len = sizeof(*opt); |
| 1051 | 1068 | ||
| 1052 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, &tclass); | 1069 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, |
| 1070 | &tclass, &dontfrag); | ||
| 1053 | if (err < 0) { | 1071 | if (err < 0) { |
| 1054 | fl6_sock_release(flowlabel); | 1072 | fl6_sock_release(flowlabel); |
| 1055 | return err; | 1073 | return err; |
| @@ -1120,6 +1138,9 @@ do_udp_sendmsg: | |||
| 1120 | if (tclass < 0) | 1138 | if (tclass < 0) |
| 1121 | tclass = np->tclass; | 1139 | tclass = np->tclass; |
| 1122 | 1140 | ||
| 1141 | if (dontfrag < 0) | ||
| 1142 | dontfrag = np->dontfrag; | ||
| 1143 | |||
| 1123 | if (msg->msg_flags&MSG_CONFIRM) | 1144 | if (msg->msg_flags&MSG_CONFIRM) |
| 1124 | goto do_confirm; | 1145 | goto do_confirm; |
| 1125 | back_from_confirm: | 1146 | back_from_confirm: |
| @@ -1143,7 +1164,7 @@ do_append_data: | |||
| 1143 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, | 1164 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, |
| 1144 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, | 1165 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, |
| 1145 | (struct rt6_info*)dst, | 1166 | (struct rt6_info*)dst, |
| 1146 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); | 1167 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); |
| 1147 | if (err) | 1168 | if (err) |
| 1148 | udp_v6_flush_pending_frames(sk); | 1169 | udp_v6_flush_pending_frames(sk); |
| 1149 | else if (!corkreq) | 1170 | else if (!corkreq) |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 8c452fd5ceae..4a0e77e14468 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
| @@ -94,7 +94,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
| 94 | xdst->u.dst.dev = dev; | 94 | xdst->u.dst.dev = dev; |
| 95 | dev_hold(dev); | 95 | dev_hold(dev); |
| 96 | 96 | ||
| 97 | xdst->u.rt6.rt6i_idev = in6_dev_get(rt->u.dst.dev); | 97 | xdst->u.rt6.rt6i_idev = in6_dev_get(dev); |
| 98 | if (!xdst->u.rt6.rt6i_idev) | 98 | if (!xdst->u.rt6.rt6i_idev) |
| 99 | return -ENODEV; | 99 | return -ENODEV; |
| 100 | 100 | ||
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 2a4efcea3423..79986a674f6e 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
| @@ -347,7 +347,7 @@ static void irda_flow_indication(void *instance, void *sap, LOCAL_FLOW flow) | |||
| 347 | self->tx_flow = flow; | 347 | self->tx_flow = flow; |
| 348 | IRDA_DEBUG(1, "%s(), IrTTP wants us to start again\n", | 348 | IRDA_DEBUG(1, "%s(), IrTTP wants us to start again\n", |
| 349 | __func__); | 349 | __func__); |
| 350 | wake_up_interruptible(sk->sk_sleep); | 350 | wake_up_interruptible(sk_sleep(sk)); |
| 351 | break; | 351 | break; |
| 352 | default: | 352 | default: |
| 353 | IRDA_DEBUG(0, "%s(), Unknown flow command!\n", __func__); | 353 | IRDA_DEBUG(0, "%s(), Unknown flow command!\n", __func__); |
| @@ -900,7 +900,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 900 | if (flags & O_NONBLOCK) | 900 | if (flags & O_NONBLOCK) |
| 901 | goto out; | 901 | goto out; |
| 902 | 902 | ||
| 903 | err = wait_event_interruptible(*(sk->sk_sleep), | 903 | err = wait_event_interruptible(*(sk_sleep(sk)), |
| 904 | skb_peek(&sk->sk_receive_queue)); | 904 | skb_peek(&sk->sk_receive_queue)); |
| 905 | if (err) | 905 | if (err) |
| 906 | goto out; | 906 | goto out; |
| @@ -1066,7 +1066,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
| 1066 | goto out; | 1066 | goto out; |
| 1067 | 1067 | ||
| 1068 | err = -ERESTARTSYS; | 1068 | err = -ERESTARTSYS; |
| 1069 | if (wait_event_interruptible(*(sk->sk_sleep), | 1069 | if (wait_event_interruptible(*(sk_sleep(sk)), |
| 1070 | (sk->sk_state != TCP_SYN_SENT))) | 1070 | (sk->sk_state != TCP_SYN_SENT))) |
| 1071 | goto out; | 1071 | goto out; |
| 1072 | 1072 | ||
| @@ -1318,7 +1318,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1318 | 1318 | ||
| 1319 | /* Check if IrTTP is wants us to slow down */ | 1319 | /* Check if IrTTP is wants us to slow down */ |
| 1320 | 1320 | ||
| 1321 | if (wait_event_interruptible(*(sk->sk_sleep), | 1321 | if (wait_event_interruptible(*(sk_sleep(sk)), |
| 1322 | (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) { | 1322 | (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) { |
| 1323 | err = -ERESTARTSYS; | 1323 | err = -ERESTARTSYS; |
| 1324 | goto out; | 1324 | goto out; |
| @@ -1477,7 +1477,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
| 1477 | if (copied >= target) | 1477 | if (copied >= target) |
| 1478 | break; | 1478 | break; |
| 1479 | 1479 | ||
| 1480 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1480 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 1481 | 1481 | ||
| 1482 | /* | 1482 | /* |
| 1483 | * POSIX 1003.1g mandates this order. | 1483 | * POSIX 1003.1g mandates this order. |
| @@ -1497,7 +1497,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
| 1497 | /* Wait process until data arrives */ | 1497 | /* Wait process until data arrives */ |
| 1498 | schedule(); | 1498 | schedule(); |
| 1499 | 1499 | ||
| 1500 | finish_wait(sk->sk_sleep, &wait); | 1500 | finish_wait(sk_sleep(sk), &wait); |
| 1501 | 1501 | ||
| 1502 | if (err) | 1502 | if (err) |
| 1503 | goto out; | 1503 | goto out; |
| @@ -1787,7 +1787,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, | |||
| 1787 | IRDA_DEBUG(4, "%s()\n", __func__); | 1787 | IRDA_DEBUG(4, "%s()\n", __func__); |
| 1788 | 1788 | ||
| 1789 | lock_kernel(); | 1789 | lock_kernel(); |
| 1790 | poll_wait(file, sk->sk_sleep, wait); | 1790 | poll_wait(file, sk_sleep(sk), wait); |
| 1791 | mask = 0; | 1791 | mask = 0; |
| 1792 | 1792 | ||
| 1793 | /* Exceptional events? */ | 1793 | /* Exceptional events? */ |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index c18286a2167b..8be324fe08b9 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
| @@ -59,7 +59,7 @@ do { \ | |||
| 59 | DEFINE_WAIT(__wait); \ | 59 | DEFINE_WAIT(__wait); \ |
| 60 | long __timeo = timeo; \ | 60 | long __timeo = timeo; \ |
| 61 | ret = 0; \ | 61 | ret = 0; \ |
| 62 | prepare_to_wait(sk->sk_sleep, &__wait, TASK_INTERRUPTIBLE); \ | 62 | prepare_to_wait(sk_sleep(sk), &__wait, TASK_INTERRUPTIBLE); \ |
| 63 | while (!(condition)) { \ | 63 | while (!(condition)) { \ |
| 64 | if (!__timeo) { \ | 64 | if (!__timeo) { \ |
| 65 | ret = -EAGAIN; \ | 65 | ret = -EAGAIN; \ |
| @@ -76,7 +76,7 @@ do { \ | |||
| 76 | if (ret) \ | 76 | if (ret) \ |
| 77 | break; \ | 77 | break; \ |
| 78 | } \ | 78 | } \ |
| 79 | finish_wait(sk->sk_sleep, &__wait); \ | 79 | finish_wait(sk_sleep(sk), &__wait); \ |
| 80 | } while (0) | 80 | } while (0) |
| 81 | 81 | ||
| 82 | #define iucv_sock_wait(sk, condition, timeo) \ | 82 | #define iucv_sock_wait(sk, condition, timeo) \ |
| @@ -305,11 +305,14 @@ static inline int iucv_below_msglim(struct sock *sk) | |||
| 305 | */ | 305 | */ |
| 306 | static void iucv_sock_wake_msglim(struct sock *sk) | 306 | static void iucv_sock_wake_msglim(struct sock *sk) |
| 307 | { | 307 | { |
| 308 | read_lock(&sk->sk_callback_lock); | 308 | struct socket_wq *wq; |
| 309 | if (sk_has_sleeper(sk)) | 309 | |
| 310 | wake_up_interruptible_all(sk->sk_sleep); | 310 | rcu_read_lock(); |
| 311 | wq = rcu_dereference(sk->sk_wq); | ||
| 312 | if (wq_has_sleeper(wq)) | ||
| 313 | wake_up_interruptible_all(&wq->wait); | ||
| 311 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 314 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
| 312 | read_unlock(&sk->sk_callback_lock); | 315 | rcu_read_unlock(); |
| 313 | } | 316 | } |
| 314 | 317 | ||
| 315 | /* Timers */ | 318 | /* Timers */ |
| @@ -795,7 +798,7 @@ static int iucv_sock_accept(struct socket *sock, struct socket *newsock, | |||
| 795 | timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); | 798 | timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); |
| 796 | 799 | ||
| 797 | /* Wait for an incoming connection */ | 800 | /* Wait for an incoming connection */ |
| 798 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 801 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
| 799 | while (!(nsk = iucv_accept_dequeue(sk, newsock))) { | 802 | while (!(nsk = iucv_accept_dequeue(sk, newsock))) { |
| 800 | set_current_state(TASK_INTERRUPTIBLE); | 803 | set_current_state(TASK_INTERRUPTIBLE); |
| 801 | if (!timeo) { | 804 | if (!timeo) { |
| @@ -819,7 +822,7 @@ static int iucv_sock_accept(struct socket *sock, struct socket *newsock, | |||
| 819 | } | 822 | } |
| 820 | 823 | ||
| 821 | set_current_state(TASK_RUNNING); | 824 | set_current_state(TASK_RUNNING); |
| 822 | remove_wait_queue(sk->sk_sleep, &wait); | 825 | remove_wait_queue(sk_sleep(sk), &wait); |
| 823 | 826 | ||
| 824 | if (err) | 827 | if (err) |
| 825 | goto done; | 828 | goto done; |
| @@ -1269,7 +1272,7 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock, | |||
| 1269 | struct sock *sk = sock->sk; | 1272 | struct sock *sk = sock->sk; |
| 1270 | unsigned int mask = 0; | 1273 | unsigned int mask = 0; |
| 1271 | 1274 | ||
| 1272 | sock_poll_wait(file, sk->sk_sleep, wait); | 1275 | sock_poll_wait(file, sk_sleep(sk), wait); |
| 1273 | 1276 | ||
| 1274 | if (sk->sk_state == IUCV_LISTEN) | 1277 | if (sk->sk_state == IUCV_LISTEN) |
| 1275 | return iucv_accept_poll(sk); | 1278 | return iucv_accept_poll(sk); |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index ecc7aea9efe4..1712af1c7b3f 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
| @@ -1617,14 +1617,9 @@ EXPORT_SYMBOL_GPL(l2tp_session_create); | |||
| 1617 | 1617 | ||
| 1618 | static __net_init int l2tp_init_net(struct net *net) | 1618 | static __net_init int l2tp_init_net(struct net *net) |
| 1619 | { | 1619 | { |
| 1620 | struct l2tp_net *pn; | 1620 | struct l2tp_net *pn = net_generic(net, l2tp_net_id); |
| 1621 | int err; | ||
| 1622 | int hash; | 1621 | int hash; |
| 1623 | 1622 | ||
| 1624 | pn = kzalloc(sizeof(*pn), GFP_KERNEL); | ||
| 1625 | if (!pn) | ||
| 1626 | return -ENOMEM; | ||
| 1627 | |||
| 1628 | INIT_LIST_HEAD(&pn->l2tp_tunnel_list); | 1623 | INIT_LIST_HEAD(&pn->l2tp_tunnel_list); |
| 1629 | spin_lock_init(&pn->l2tp_tunnel_list_lock); | 1624 | spin_lock_init(&pn->l2tp_tunnel_list_lock); |
| 1630 | 1625 | ||
| @@ -1633,33 +1628,11 @@ static __net_init int l2tp_init_net(struct net *net) | |||
| 1633 | 1628 | ||
| 1634 | spin_lock_init(&pn->l2tp_session_hlist_lock); | 1629 | spin_lock_init(&pn->l2tp_session_hlist_lock); |
| 1635 | 1630 | ||
| 1636 | err = net_assign_generic(net, l2tp_net_id, pn); | ||
| 1637 | if (err) | ||
| 1638 | goto out; | ||
| 1639 | |||
| 1640 | return 0; | 1631 | return 0; |
| 1641 | |||
| 1642 | out: | ||
| 1643 | kfree(pn); | ||
| 1644 | return err; | ||
| 1645 | } | ||
| 1646 | |||
| 1647 | static __net_exit void l2tp_exit_net(struct net *net) | ||
| 1648 | { | ||
| 1649 | struct l2tp_net *pn; | ||
| 1650 | |||
| 1651 | pn = net_generic(net, l2tp_net_id); | ||
| 1652 | /* | ||
| 1653 | * if someone has cached our net then | ||
| 1654 | * further net_generic call will return NULL | ||
| 1655 | */ | ||
| 1656 | net_assign_generic(net, l2tp_net_id, NULL); | ||
| 1657 | kfree(pn); | ||
| 1658 | } | 1632 | } |
| 1659 | 1633 | ||
| 1660 | static struct pernet_operations l2tp_net_ops = { | 1634 | static struct pernet_operations l2tp_net_ops = { |
| 1661 | .init = l2tp_init_net, | 1635 | .init = l2tp_init_net, |
| 1662 | .exit = l2tp_exit_net, | ||
| 1663 | .id = &l2tp_net_id, | 1636 | .id = &l2tp_net_id, |
| 1664 | .size = sizeof(struct l2tp_net), | 1637 | .size = sizeof(struct l2tp_net), |
| 1665 | }; | 1638 | }; |
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index ca1164afeb74..58c6c4cda73b 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c | |||
| @@ -276,43 +276,16 @@ out: | |||
| 276 | 276 | ||
| 277 | static __net_init int l2tp_eth_init_net(struct net *net) | 277 | static __net_init int l2tp_eth_init_net(struct net *net) |
| 278 | { | 278 | { |
| 279 | struct l2tp_eth_net *pn; | 279 | struct l2tp_eth_net *pn = net_generic(net, l2tp_eth_net_id); |
| 280 | int err; | ||
| 281 | |||
| 282 | pn = kzalloc(sizeof(*pn), GFP_KERNEL); | ||
| 283 | if (!pn) | ||
| 284 | return -ENOMEM; | ||
| 285 | 280 | ||
| 286 | INIT_LIST_HEAD(&pn->l2tp_eth_dev_list); | 281 | INIT_LIST_HEAD(&pn->l2tp_eth_dev_list); |
| 287 | spin_lock_init(&pn->l2tp_eth_lock); | 282 | spin_lock_init(&pn->l2tp_eth_lock); |
| 288 | 283 | ||
| 289 | err = net_assign_generic(net, l2tp_eth_net_id, pn); | ||
| 290 | if (err) | ||
| 291 | goto out; | ||
| 292 | |||
| 293 | return 0; | 284 | return 0; |
| 294 | |||
| 295 | out: | ||
| 296 | kfree(pn); | ||
| 297 | return err; | ||
| 298 | } | ||
| 299 | |||
| 300 | static __net_exit void l2tp_eth_exit_net(struct net *net) | ||
| 301 | { | ||
| 302 | struct l2tp_eth_net *pn; | ||
| 303 | |||
| 304 | pn = net_generic(net, l2tp_eth_net_id); | ||
| 305 | /* | ||
| 306 | * if someone has cached our net then | ||
| 307 | * further net_generic call will return NULL | ||
| 308 | */ | ||
| 309 | net_assign_generic(net, l2tp_eth_net_id, NULL); | ||
| 310 | kfree(pn); | ||
| 311 | } | 285 | } |
| 312 | 286 | ||
| 313 | static __net_initdata struct pernet_operations l2tp_eth_net_ops = { | 287 | static __net_initdata struct pernet_operations l2tp_eth_net_ops = { |
| 314 | .init = l2tp_eth_init_net, | 288 | .init = l2tp_eth_init_net, |
| 315 | .exit = l2tp_eth_exit_net, | ||
| 316 | .id = &l2tp_eth_net_id, | 289 | .id = &l2tp_eth_net_id, |
| 317 | .size = sizeof(struct l2tp_eth_net), | 290 | .size = sizeof(struct l2tp_eth_net), |
| 318 | }; | 291 | }; |
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 2db6a9f75913..023ba820236f 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
| @@ -536,7 +536,7 @@ static int llc_ui_wait_for_disc(struct sock *sk, long timeout) | |||
| 536 | int rc = 0; | 536 | int rc = 0; |
| 537 | 537 | ||
| 538 | while (1) { | 538 | while (1) { |
| 539 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 539 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 540 | if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE)) | 540 | if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE)) |
| 541 | break; | 541 | break; |
| 542 | rc = -ERESTARTSYS; | 542 | rc = -ERESTARTSYS; |
| @@ -547,7 +547,7 @@ static int llc_ui_wait_for_disc(struct sock *sk, long timeout) | |||
| 547 | break; | 547 | break; |
| 548 | rc = 0; | 548 | rc = 0; |
| 549 | } | 549 | } |
| 550 | finish_wait(sk->sk_sleep, &wait); | 550 | finish_wait(sk_sleep(sk), &wait); |
| 551 | return rc; | 551 | return rc; |
| 552 | } | 552 | } |
| 553 | 553 | ||
| @@ -556,13 +556,13 @@ static int llc_ui_wait_for_conn(struct sock *sk, long timeout) | |||
| 556 | DEFINE_WAIT(wait); | 556 | DEFINE_WAIT(wait); |
| 557 | 557 | ||
| 558 | while (1) { | 558 | while (1) { |
| 559 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 559 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 560 | if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT)) | 560 | if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT)) |
| 561 | break; | 561 | break; |
| 562 | if (signal_pending(current) || !timeout) | 562 | if (signal_pending(current) || !timeout) |
| 563 | break; | 563 | break; |
| 564 | } | 564 | } |
| 565 | finish_wait(sk->sk_sleep, &wait); | 565 | finish_wait(sk_sleep(sk), &wait); |
| 566 | return timeout; | 566 | return timeout; |
| 567 | } | 567 | } |
| 568 | 568 | ||
| @@ -573,7 +573,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout) | |||
| 573 | int rc; | 573 | int rc; |
| 574 | 574 | ||
| 575 | while (1) { | 575 | while (1) { |
| 576 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 576 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 577 | rc = 0; | 577 | rc = 0; |
| 578 | if (sk_wait_event(sk, &timeout, | 578 | if (sk_wait_event(sk, &timeout, |
| 579 | (sk->sk_shutdown & RCV_SHUTDOWN) || | 579 | (sk->sk_shutdown & RCV_SHUTDOWN) || |
| @@ -588,7 +588,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout) | |||
| 588 | if (!timeout) | 588 | if (!timeout) |
| 589 | break; | 589 | break; |
| 590 | } | 590 | } |
| 591 | finish_wait(sk->sk_sleep, &wait); | 591 | finish_wait(sk_sleep(sk), &wait); |
| 592 | return rc; | 592 | return rc; |
| 593 | } | 593 | } |
| 594 | 594 | ||
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 9598fdb4ad01..6bb9a9a94960 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
| @@ -19,8 +19,9 @@ | |||
| 19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
| 20 | #include "driver-ops.h" | 20 | #include "driver-ops.h" |
| 21 | 21 | ||
| 22 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 22 | static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
| 23 | u16 initiator, u16 reason) | 23 | u16 initiator, u16 reason, |
| 24 | bool from_timer) | ||
| 24 | { | 25 | { |
| 25 | struct ieee80211_local *local = sta->local; | 26 | struct ieee80211_local *local = sta->local; |
| 26 | struct tid_ampdu_rx *tid_rx; | 27 | struct tid_ampdu_rx *tid_rx; |
| @@ -70,10 +71,17 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
| 70 | 71 | ||
| 71 | spin_unlock_bh(&sta->lock); | 72 | spin_unlock_bh(&sta->lock); |
| 72 | 73 | ||
| 73 | del_timer_sync(&tid_rx->session_timer); | 74 | if (!from_timer) |
| 75 | del_timer_sync(&tid_rx->session_timer); | ||
| 74 | kfree(tid_rx); | 76 | kfree(tid_rx); |
| 75 | } | 77 | } |
| 76 | 78 | ||
| 79 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | ||
| 80 | u16 initiator, u16 reason) | ||
| 81 | { | ||
| 82 | ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, false); | ||
| 83 | } | ||
| 84 | |||
| 77 | /* | 85 | /* |
| 78 | * After accepting the AddBA Request we activated a timer, | 86 | * After accepting the AddBA Request we activated a timer, |
| 79 | * resetting it after each frame that arrives from the originator. | 87 | * resetting it after each frame that arrives from the originator. |
| @@ -92,8 +100,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
| 92 | #ifdef CONFIG_MAC80211_HT_DEBUG | 100 | #ifdef CONFIG_MAC80211_HT_DEBUG |
| 93 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 101 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); |
| 94 | #endif | 102 | #endif |
| 95 | __ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT, | 103 | ___ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT, |
| 96 | WLAN_REASON_QSTA_TIMEOUT); | 104 | WLAN_REASON_QSTA_TIMEOUT, true); |
| 97 | } | 105 | } |
| 98 | 106 | ||
| 99 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | 107 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 608063f11797..c163d0a149f4 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
| @@ -184,10 +184,9 @@ static void sta_addba_resp_timer_expired(unsigned long data) | |||
| 184 | HT_AGG_STATE_REQ_STOP_BA_MSK)) != | 184 | HT_AGG_STATE_REQ_STOP_BA_MSK)) != |
| 185 | HT_ADDBA_REQUESTED_MSK) { | 185 | HT_ADDBA_REQUESTED_MSK) { |
| 186 | spin_unlock_bh(&sta->lock); | 186 | spin_unlock_bh(&sta->lock); |
| 187 | *state = HT_AGG_STATE_IDLE; | ||
| 188 | #ifdef CONFIG_MAC80211_HT_DEBUG | 187 | #ifdef CONFIG_MAC80211_HT_DEBUG |
| 189 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | 188 | printk(KERN_DEBUG "timer expired on tid %d but we are not " |
| 190 | "(or no longer) expecting addBA response there", | 189 | "(or no longer) expecting addBA response there\n", |
| 191 | tid); | 190 | tid); |
| 192 | #endif | 191 | #endif |
| 193 | return; | 192 | return; |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 7dd7cda75cfa..ae37270a0633 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -97,9 +97,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
| 97 | params->mesh_id_len, | 97 | params->mesh_id_len, |
| 98 | params->mesh_id); | 98 | params->mesh_id); |
| 99 | 99 | ||
| 100 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) | ||
| 101 | return 0; | ||
| 102 | |||
| 103 | if (type == NL80211_IFTYPE_AP_VLAN && | 100 | if (type == NL80211_IFTYPE_AP_VLAN && |
| 104 | params && params->use_4addr == 0) | 101 | params && params->use_4addr == 0) |
| 105 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | 102 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); |
| @@ -107,7 +104,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
| 107 | params && params->use_4addr >= 0) | 104 | params && params->use_4addr >= 0) |
| 108 | sdata->u.mgd.use_4addr = params->use_4addr; | 105 | sdata->u.mgd.use_4addr = params->use_4addr; |
| 109 | 106 | ||
| 110 | sdata->u.mntr_flags = *flags; | 107 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR && flags) |
| 108 | sdata->u.mntr_flags = *flags; | ||
| 109 | |||
| 111 | return 0; | 110 | return 0; |
| 112 | } | 111 | } |
| 113 | 112 | ||
| @@ -411,6 +410,17 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 411 | return ret; | 410 | return ret; |
| 412 | } | 411 | } |
| 413 | 412 | ||
| 413 | static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, | ||
| 414 | int idx, struct survey_info *survey) | ||
| 415 | { | ||
| 416 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
| 417 | |||
| 418 | if (!local->ops->get_survey) | ||
| 419 | return -EOPNOTSUPP; | ||
| 420 | |||
| 421 | return drv_get_survey(local, idx, survey); | ||
| 422 | } | ||
| 423 | |||
| 414 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 424 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, |
| 415 | u8 *mac, struct station_info *sinfo) | 425 | u8 *mac, struct station_info *sinfo) |
| 416 | { | 426 | { |
| @@ -1104,6 +1114,13 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
| 1104 | changed |= BSS_CHANGED_BASIC_RATES; | 1114 | changed |= BSS_CHANGED_BASIC_RATES; |
| 1105 | } | 1115 | } |
| 1106 | 1116 | ||
| 1117 | if (params->ap_isolate >= 0) { | ||
| 1118 | if (params->ap_isolate) | ||
| 1119 | sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS; | ||
| 1120 | else | ||
| 1121 | sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; | ||
| 1122 | } | ||
| 1123 | |||
| 1107 | ieee80211_bss_info_change_notify(sdata, changed); | 1124 | ieee80211_bss_info_change_notify(sdata, changed); |
| 1108 | 1125 | ||
| 1109 | return 0; | 1126 | return 0; |
| @@ -1388,11 +1405,11 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
| 1388 | return -EOPNOTSUPP; | 1405 | return -EOPNOTSUPP; |
| 1389 | 1406 | ||
| 1390 | if (enabled == sdata->u.mgd.powersave && | 1407 | if (enabled == sdata->u.mgd.powersave && |
| 1391 | timeout == conf->dynamic_ps_timeout) | 1408 | timeout == conf->dynamic_ps_forced_timeout) |
| 1392 | return 0; | 1409 | return 0; |
| 1393 | 1410 | ||
| 1394 | sdata->u.mgd.powersave = enabled; | 1411 | sdata->u.mgd.powersave = enabled; |
| 1395 | conf->dynamic_ps_timeout = timeout; | 1412 | conf->dynamic_ps_forced_timeout = timeout; |
| 1396 | 1413 | ||
| 1397 | /* no change, but if automatic follow powersave */ | 1414 | /* no change, but if automatic follow powersave */ |
| 1398 | mutex_lock(&sdata->u.mgd.mtx); | 1415 | mutex_lock(&sdata->u.mgd.mtx); |
| @@ -1508,6 +1525,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
| 1508 | .change_station = ieee80211_change_station, | 1525 | .change_station = ieee80211_change_station, |
| 1509 | .get_station = ieee80211_get_station, | 1526 | .get_station = ieee80211_get_station, |
| 1510 | .dump_station = ieee80211_dump_station, | 1527 | .dump_station = ieee80211_dump_station, |
| 1528 | .dump_survey = ieee80211_dump_survey, | ||
| 1511 | #ifdef CONFIG_MAC80211_MESH | 1529 | #ifdef CONFIG_MAC80211_MESH |
| 1512 | .add_mpath = ieee80211_add_mpath, | 1530 | .add_mpath = ieee80211_add_mpath, |
| 1513 | .del_mpath = ieee80211_del_mpath, | 1531 | .del_mpath = ieee80211_del_mpath, |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 6bc9b07c3eda..e763f1529ddb 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
| @@ -39,6 +39,13 @@ static const struct file_operations sta_ ##name## _ops = { \ | |||
| 39 | .open = mac80211_open_file_generic, \ | 39 | .open = mac80211_open_file_generic, \ |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | #define STA_OPS_RW(name) \ | ||
| 43 | static const struct file_operations sta_ ##name## _ops = { \ | ||
| 44 | .read = sta_##name##_read, \ | ||
| 45 | .write = sta_##name##_write, \ | ||
| 46 | .open = mac80211_open_file_generic, \ | ||
| 47 | } | ||
| 48 | |||
| 42 | #define STA_FILE(name, field, format) \ | 49 | #define STA_FILE(name, field, format) \ |
| 43 | STA_READ_##format(name, field) \ | 50 | STA_READ_##format(name, field) \ |
| 44 | STA_OPS(name) | 51 | STA_OPS(name) |
| @@ -156,7 +163,63 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
| 156 | 163 | ||
| 157 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | 164 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); |
| 158 | } | 165 | } |
| 159 | STA_OPS(agg_status); | 166 | |
| 167 | static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, | ||
| 168 | size_t count, loff_t *ppos) | ||
| 169 | { | ||
| 170 | char _buf[12], *buf = _buf; | ||
| 171 | struct sta_info *sta = file->private_data; | ||
| 172 | bool start, tx; | ||
| 173 | unsigned long tid; | ||
| 174 | int ret; | ||
| 175 | |||
| 176 | if (count > sizeof(_buf)) | ||
| 177 | return -EINVAL; | ||
| 178 | |||
| 179 | if (copy_from_user(buf, userbuf, count)) | ||
| 180 | return -EFAULT; | ||
| 181 | |||
| 182 | buf[sizeof(_buf) - 1] = '\0'; | ||
| 183 | |||
| 184 | if (strncmp(buf, "tx ", 3) == 0) { | ||
| 185 | buf += 3; | ||
| 186 | tx = true; | ||
| 187 | } else if (strncmp(buf, "rx ", 3) == 0) { | ||
| 188 | buf += 3; | ||
| 189 | tx = false; | ||
| 190 | } else | ||
| 191 | return -EINVAL; | ||
| 192 | |||
| 193 | if (strncmp(buf, "start ", 6) == 0) { | ||
| 194 | buf += 6; | ||
| 195 | start = true; | ||
| 196 | if (!tx) | ||
| 197 | return -EINVAL; | ||
| 198 | } else if (strncmp(buf, "stop ", 5) == 0) { | ||
| 199 | buf += 5; | ||
| 200 | start = false; | ||
| 201 | } else | ||
| 202 | return -EINVAL; | ||
| 203 | |||
| 204 | tid = simple_strtoul(buf, NULL, 0); | ||
| 205 | |||
| 206 | if (tid >= STA_TID_NUM) | ||
| 207 | return -EINVAL; | ||
| 208 | |||
| 209 | if (tx) { | ||
| 210 | if (start) | ||
| 211 | ret = ieee80211_start_tx_ba_session(&sta->sta, tid); | ||
| 212 | else | ||
| 213 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid, | ||
| 214 | WLAN_BACK_RECIPIENT); | ||
| 215 | } else { | ||
| 216 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, 3); | ||
| 217 | ret = 0; | ||
| 218 | } | ||
| 219 | |||
| 220 | return ret ?: count; | ||
| 221 | } | ||
| 222 | STA_OPS_RW(agg_status); | ||
| 160 | 223 | ||
| 161 | static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | 224 | static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, |
| 162 | size_t count, loff_t *ppos) | 225 | size_t count, loff_t *ppos) |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 9179196da264..ee8b63f92f71 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
| @@ -152,14 +152,15 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | static inline int drv_hw_scan(struct ieee80211_local *local, | 154 | static inline int drv_hw_scan(struct ieee80211_local *local, |
| 155 | struct ieee80211_sub_if_data *sdata, | ||
| 155 | struct cfg80211_scan_request *req) | 156 | struct cfg80211_scan_request *req) |
| 156 | { | 157 | { |
| 157 | int ret; | 158 | int ret; |
| 158 | 159 | ||
| 159 | might_sleep(); | 160 | might_sleep(); |
| 160 | 161 | ||
| 161 | ret = local->ops->hw_scan(&local->hw, req); | 162 | ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); |
| 162 | trace_drv_hw_scan(local, req, ret); | 163 | trace_drv_hw_scan(local, sdata, req, ret); |
| 163 | return ret; | 164 | return ret; |
| 164 | } | 165 | } |
| 165 | 166 | ||
| @@ -344,6 +345,15 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, | |||
| 344 | return ret; | 345 | return ret; |
| 345 | } | 346 | } |
| 346 | 347 | ||
| 348 | static inline int drv_get_survey(struct ieee80211_local *local, int idx, | ||
| 349 | struct survey_info *survey) | ||
| 350 | { | ||
| 351 | int ret = -EOPNOTSUPP; | ||
| 352 | if (local->ops->conf_tx) | ||
| 353 | ret = local->ops->get_survey(&local->hw, idx, survey); | ||
| 354 | /* trace_drv_get_survey(local, idx, survey, ret); */ | ||
| 355 | return ret; | ||
| 356 | } | ||
| 347 | 357 | ||
| 348 | static inline void drv_rfkill_poll(struct ieee80211_local *local) | 358 | static inline void drv_rfkill_poll(struct ieee80211_local *local) |
| 349 | { | 359 | { |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index e209cb82ff29..ce734b58d07a 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
| @@ -363,23 +363,26 @@ TRACE_EVENT(drv_update_tkip_key, | |||
| 363 | 363 | ||
| 364 | TRACE_EVENT(drv_hw_scan, | 364 | TRACE_EVENT(drv_hw_scan, |
| 365 | TP_PROTO(struct ieee80211_local *local, | 365 | TP_PROTO(struct ieee80211_local *local, |
| 366 | struct ieee80211_sub_if_data *sdata, | ||
| 366 | struct cfg80211_scan_request *req, int ret), | 367 | struct cfg80211_scan_request *req, int ret), |
| 367 | 368 | ||
| 368 | TP_ARGS(local, req, ret), | 369 | TP_ARGS(local, sdata, req, ret), |
| 369 | 370 | ||
| 370 | TP_STRUCT__entry( | 371 | TP_STRUCT__entry( |
| 371 | LOCAL_ENTRY | 372 | LOCAL_ENTRY |
| 373 | VIF_ENTRY | ||
| 372 | __field(int, ret) | 374 | __field(int, ret) |
| 373 | ), | 375 | ), |
| 374 | 376 | ||
| 375 | TP_fast_assign( | 377 | TP_fast_assign( |
| 376 | LOCAL_ASSIGN; | 378 | LOCAL_ASSIGN; |
| 379 | VIF_ASSIGN; | ||
| 377 | __entry->ret = ret; | 380 | __entry->ret = ret; |
| 378 | ), | 381 | ), |
| 379 | 382 | ||
| 380 | TP_printk( | 383 | TP_printk( |
| 381 | LOCAL_PR_FMT " ret:%d", | 384 | LOCAL_PR_FMT VIF_PR_FMT " ret:%d", |
| 382 | LOCAL_PR_ARG, __entry->ret | 385 | LOCAL_PR_ARG,VIF_PR_ARG, __entry->ret |
| 383 | ) | 386 | ) |
| 384 | ); | 387 | ); |
| 385 | 388 | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index e6f3b0c7a71f..b72ee6435fa3 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
| @@ -92,6 +92,12 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 92 | if (memcmp(ifibss->bssid, bssid, ETH_ALEN)) | 92 | if (memcmp(ifibss->bssid, bssid, ETH_ALEN)) |
| 93 | sta_info_flush(sdata->local, sdata); | 93 | sta_info_flush(sdata->local, sdata); |
| 94 | 94 | ||
| 95 | /* if merging, indicate to driver that we leave the old IBSS */ | ||
| 96 | if (sdata->vif.bss_conf.ibss_joined) { | ||
| 97 | sdata->vif.bss_conf.ibss_joined = false; | ||
| 98 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS); | ||
| 99 | } | ||
| 100 | |||
| 95 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | 101 | memcpy(ifibss->bssid, bssid, ETH_ALEN); |
| 96 | 102 | ||
| 97 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 103 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
| @@ -171,6 +177,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 171 | bss_change |= BSS_CHANGED_BSSID; | 177 | bss_change |= BSS_CHANGED_BSSID; |
| 172 | bss_change |= BSS_CHANGED_BEACON; | 178 | bss_change |= BSS_CHANGED_BEACON; |
| 173 | bss_change |= BSS_CHANGED_BEACON_ENABLED; | 179 | bss_change |= BSS_CHANGED_BEACON_ENABLED; |
| 180 | bss_change |= BSS_CHANGED_IBSS; | ||
| 181 | sdata->vif.bss_conf.ibss_joined = true; | ||
| 174 | ieee80211_bss_info_change_notify(sdata, bss_change); | 182 | ieee80211_bss_info_change_notify(sdata, bss_change); |
| 175 | 183 | ||
| 176 | ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); | 184 | ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); |
| @@ -481,7 +489,9 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
| 481 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " | 489 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " |
| 482 | "IBSS networks with same SSID (merge)\n", sdata->name); | 490 | "IBSS networks with same SSID (merge)\n", sdata->name); |
| 483 | 491 | ||
| 484 | ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); | 492 | ieee80211_request_internal_scan(sdata, |
| 493 | ifibss->ssid, ifibss->ssid_len, | ||
| 494 | ifibss->fixed_channel ? ifibss->channel : NULL); | ||
| 485 | } | 495 | } |
| 486 | 496 | ||
| 487 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | 497 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) |
| @@ -588,8 +598,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
| 588 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " | 598 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " |
| 589 | "join\n", sdata->name); | 599 | "join\n", sdata->name); |
| 590 | 600 | ||
| 591 | ieee80211_request_internal_scan(sdata, ifibss->ssid, | 601 | ieee80211_request_internal_scan(sdata, |
| 592 | ifibss->ssid_len); | 602 | ifibss->ssid, ifibss->ssid_len, |
| 603 | ifibss->fixed_channel ? ifibss->channel : NULL); | ||
| 593 | } else { | 604 | } else { |
| 594 | int interval = IEEE80211_SCAN_INTERVAL; | 605 | int interval = IEEE80211_SCAN_INTERVAL; |
| 595 | 606 | ||
| @@ -897,6 +908,12 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
| 897 | sdata->u.ibss.channel = params->channel; | 908 | sdata->u.ibss.channel = params->channel; |
| 898 | sdata->u.ibss.fixed_channel = params->channel_fixed; | 909 | sdata->u.ibss.fixed_channel = params->channel_fixed; |
| 899 | 910 | ||
| 911 | /* fix ourselves to that channel now already */ | ||
| 912 | if (params->channel_fixed) { | ||
| 913 | sdata->local->oper_channel = params->channel; | ||
| 914 | sdata->local->oper_channel_type = NL80211_CHAN_NO_HT; | ||
| 915 | } | ||
| 916 | |||
| 900 | if (params->ie) { | 917 | if (params->ie) { |
| 901 | sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len, | 918 | sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len, |
| 902 | GFP_KERNEL); | 919 | GFP_KERNEL); |
| @@ -951,7 +968,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
| 951 | kfree(sdata->u.ibss.ie); | 968 | kfree(sdata->u.ibss.ie); |
| 952 | skb = sdata->u.ibss.presp; | 969 | skb = sdata->u.ibss.presp; |
| 953 | rcu_assign_pointer(sdata->u.ibss.presp, NULL); | 970 | rcu_assign_pointer(sdata->u.ibss.presp, NULL); |
| 954 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 971 | sdata->vif.bss_conf.ibss_joined = false; |
| 972 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | ||
| 973 | BSS_CHANGED_IBSS); | ||
| 955 | synchronize_rcu(); | 974 | synchronize_rcu(); |
| 956 | kfree_skb(skb); | 975 | kfree_skb(skb); |
| 957 | 976 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c9712f35e596..cbaf4981e110 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -1019,7 +1019,8 @@ void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata); | |||
| 1019 | /* scan/BSS handling */ | 1019 | /* scan/BSS handling */ |
| 1020 | void ieee80211_scan_work(struct work_struct *work); | 1020 | void ieee80211_scan_work(struct work_struct *work); |
| 1021 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | 1021 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, |
| 1022 | const u8 *ssid, u8 ssid_len); | 1022 | const u8 *ssid, u8 ssid_len, |
| 1023 | struct ieee80211_channel *chan); | ||
| 1023 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 1024 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
| 1024 | struct cfg80211_scan_request *req); | 1025 | struct cfg80211_scan_request *req); |
| 1025 | void ieee80211_scan_cancel(struct ieee80211_local *local); | 1026 | void ieee80211_scan_cancel(struct ieee80211_local *local); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index e8f6e3b252d8..8d4b41787dcf 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
| @@ -140,6 +140,7 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
| 140 | struct ieee80211_sub_if_data, | 140 | struct ieee80211_sub_if_data, |
| 141 | u.ap); | 141 | u.ap); |
| 142 | 142 | ||
| 143 | key->conf.ap_addr = sdata->dev->dev_addr; | ||
| 143 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); | 144 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); |
| 144 | 145 | ||
| 145 | if (!ret) { | 146 | if (!ret) { |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 011ee85bcd57..bd632e1ee2c5 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -442,7 +442,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 442 | struct ieee80211_local *local = hw_to_local(hw); | 442 | struct ieee80211_local *local = hw_to_local(hw); |
| 443 | int result; | 443 | int result; |
| 444 | enum ieee80211_band band; | 444 | enum ieee80211_band band; |
| 445 | int channels, i, j, max_bitrates; | 445 | int channels, max_bitrates; |
| 446 | bool supp_ht; | 446 | bool supp_ht; |
| 447 | static const u32 cipher_suites[] = { | 447 | static const u32 cipher_suites[] = { |
| 448 | WLAN_CIPHER_SUITE_WEP40, | 448 | WLAN_CIPHER_SUITE_WEP40, |
| @@ -572,6 +572,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 572 | 572 | ||
| 573 | local->hw.conf.listen_interval = local->hw.max_listen_interval; | 573 | local->hw.conf.listen_interval = local->hw.max_listen_interval; |
| 574 | 574 | ||
| 575 | local->hw.conf.dynamic_ps_forced_timeout = -1; | ||
| 576 | |||
| 575 | result = sta_info_start(local); | 577 | result = sta_info_start(local); |
| 576 | if (result < 0) | 578 | if (result < 0) |
| 577 | goto fail_sta_info; | 579 | goto fail_sta_info; |
| @@ -606,21 +608,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 606 | 608 | ||
| 607 | ieee80211_led_init(local); | 609 | ieee80211_led_init(local); |
| 608 | 610 | ||
| 609 | /* alloc internal scan request */ | ||
| 610 | i = 0; | ||
| 611 | local->int_scan_req->ssids = &local->scan_ssid; | ||
| 612 | local->int_scan_req->n_ssids = 1; | ||
| 613 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
| 614 | if (!hw->wiphy->bands[band]) | ||
| 615 | continue; | ||
| 616 | for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) { | ||
| 617 | local->int_scan_req->channels[i] = | ||
| 618 | &hw->wiphy->bands[band]->channels[j]; | ||
| 619 | i++; | ||
| 620 | } | ||
| 621 | } | ||
| 622 | local->int_scan_req->n_channels = i; | ||
| 623 | |||
| 624 | local->network_latency_notifier.notifier_call = | 611 | local->network_latency_notifier.notifier_call = |
| 625 | ieee80211_max_network_latency; | 612 | ieee80211_max_network_latency; |
| 626 | result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, | 613 | result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 35d850223a75..358226f63b81 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -175,6 +175,8 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
| 175 | ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || | 175 | ht_changed = conf_is_ht(&local->hw.conf) != enable_ht || |
| 176 | channel_type != local->hw.conf.channel_type; | 176 | channel_type != local->hw.conf.channel_type; |
| 177 | 177 | ||
| 178 | if (local->tmp_channel) | ||
| 179 | local->tmp_channel_type = channel_type; | ||
| 178 | local->oper_channel_type = channel_type; | 180 | local->oper_channel_type = channel_type; |
| 179 | 181 | ||
| 180 | if (ht_changed) { | 182 | if (ht_changed) { |
| @@ -476,6 +478,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
| 476 | { | 478 | { |
| 477 | struct ieee80211_sub_if_data *sdata, *found = NULL; | 479 | struct ieee80211_sub_if_data *sdata, *found = NULL; |
| 478 | int count = 0; | 480 | int count = 0; |
| 481 | int timeout; | ||
| 479 | 482 | ||
| 480 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) { | 483 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) { |
| 481 | local->ps_sdata = NULL; | 484 | local->ps_sdata = NULL; |
| @@ -509,6 +512,26 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
| 509 | beaconint_us = ieee80211_tu_to_usec( | 512 | beaconint_us = ieee80211_tu_to_usec( |
| 510 | found->vif.bss_conf.beacon_int); | 513 | found->vif.bss_conf.beacon_int); |
| 511 | 514 | ||
| 515 | timeout = local->hw.conf.dynamic_ps_forced_timeout; | ||
| 516 | if (timeout < 0) { | ||
| 517 | /* | ||
| 518 | * The 2 second value is there for compatibility until | ||
| 519 | * the PM_QOS_NETWORK_LATENCY is configured with real | ||
| 520 | * values. | ||
| 521 | */ | ||
| 522 | if (latency == 2000000000) | ||
| 523 | timeout = 100; | ||
| 524 | else if (latency <= 50000) | ||
| 525 | timeout = 300; | ||
| 526 | else if (latency <= 100000) | ||
| 527 | timeout = 100; | ||
| 528 | else if (latency <= 500000) | ||
| 529 | timeout = 50; | ||
| 530 | else | ||
| 531 | timeout = 0; | ||
| 532 | } | ||
| 533 | local->hw.conf.dynamic_ps_timeout = timeout; | ||
| 534 | |||
| 512 | if (beaconint_us > latency) { | 535 | if (beaconint_us > latency) { |
| 513 | local->ps_sdata = NULL; | 536 | local->ps_sdata = NULL; |
| 514 | } else { | 537 | } else { |
| @@ -1331,12 +1354,17 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
| 1331 | mutex_lock(&sdata->local->iflist_mtx); | 1354 | mutex_lock(&sdata->local->iflist_mtx); |
| 1332 | ieee80211_recalc_ps(sdata->local, -1); | 1355 | ieee80211_recalc_ps(sdata->local, -1); |
| 1333 | mutex_unlock(&sdata->local->iflist_mtx); | 1356 | mutex_unlock(&sdata->local->iflist_mtx); |
| 1357 | |||
| 1358 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
| 1359 | return; | ||
| 1360 | |||
| 1334 | /* | 1361 | /* |
| 1335 | * We've received a probe response, but are not sure whether | 1362 | * We've received a probe response, but are not sure whether |
| 1336 | * we have or will be receiving any beacons or data, so let's | 1363 | * we have or will be receiving any beacons or data, so let's |
| 1337 | * schedule the timers again, just in case. | 1364 | * schedule the timers again, just in case. |
| 1338 | */ | 1365 | */ |
| 1339 | mod_beacon_timer(sdata); | 1366 | mod_beacon_timer(sdata); |
| 1367 | |||
| 1340 | mod_timer(&ifmgd->conn_mon_timer, | 1368 | mod_timer(&ifmgd->conn_mon_timer, |
| 1341 | round_jiffies_up(jiffies + | 1369 | round_jiffies_up(jiffies + |
| 1342 | IEEE80211_CONNECTION_IDLE_TIME)); | 1370 | IEEE80211_CONNECTION_IDLE_TIME)); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 72efbd87c1eb..9a08f2c446c6 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -81,8 +81,6 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
| 81 | len += 8; | 81 | len += 8; |
| 82 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 82 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
| 83 | len += 1; | 83 | len += 1; |
| 84 | if (local->hw.flags & IEEE80211_HW_NOISE_DBM) | ||
| 85 | len += 1; | ||
| 86 | 84 | ||
| 87 | if (len & 1) /* padding for RX_FLAGS if necessary */ | 85 | if (len & 1) /* padding for RX_FLAGS if necessary */ |
| 88 | len++; | 86 | len++; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index e1a3defdf581..e14c44195ae9 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
| @@ -85,7 +85,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
| 85 | { | 85 | { |
| 86 | struct cfg80211_bss *cbss; | 86 | struct cfg80211_bss *cbss; |
| 87 | struct ieee80211_bss *bss; | 87 | struct ieee80211_bss *bss; |
| 88 | int clen; | 88 | int clen, srlen; |
| 89 | s32 signal = 0; | 89 | s32 signal = 0; |
| 90 | 90 | ||
| 91 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 91 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
| @@ -114,23 +114,24 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
| 114 | bss->dtim_period = tim_ie->dtim_period; | 114 | bss->dtim_period = tim_ie->dtim_period; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | bss->supp_rates_len = 0; | 117 | /* replace old supported rates if we get new values */ |
| 118 | srlen = 0; | ||
| 118 | if (elems->supp_rates) { | 119 | if (elems->supp_rates) { |
| 119 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | 120 | clen = IEEE80211_MAX_SUPP_RATES; |
| 120 | if (clen > elems->supp_rates_len) | 121 | if (clen > elems->supp_rates_len) |
| 121 | clen = elems->supp_rates_len; | 122 | clen = elems->supp_rates_len; |
| 122 | memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, | 123 | memcpy(bss->supp_rates, elems->supp_rates, clen); |
| 123 | clen); | 124 | srlen += clen; |
| 124 | bss->supp_rates_len += clen; | ||
| 125 | } | 125 | } |
| 126 | if (elems->ext_supp_rates) { | 126 | if (elems->ext_supp_rates) { |
| 127 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | 127 | clen = IEEE80211_MAX_SUPP_RATES - srlen; |
| 128 | if (clen > elems->ext_supp_rates_len) | 128 | if (clen > elems->ext_supp_rates_len) |
| 129 | clen = elems->ext_supp_rates_len; | 129 | clen = elems->ext_supp_rates_len; |
| 130 | memcpy(&bss->supp_rates[bss->supp_rates_len], | 130 | memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen); |
| 131 | elems->ext_supp_rates, clen); | 131 | srlen += clen; |
| 132 | bss->supp_rates_len += clen; | ||
| 133 | } | 132 | } |
| 133 | if (srlen) | ||
| 134 | bss->supp_rates_len = srlen; | ||
| 134 | 135 | ||
| 135 | bss->wmm_used = elems->wmm_param || elems->wmm_info; | 136 | bss->wmm_used = elems->wmm_param || elems->wmm_info; |
| 136 | bss->uapsd_supported = is_uapsd_supported(elems); | 137 | bss->uapsd_supported = is_uapsd_supported(elems); |
| @@ -411,7 +412,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
| 411 | 412 | ||
| 412 | if (local->ops->hw_scan) { | 413 | if (local->ops->hw_scan) { |
| 413 | WARN_ON(!ieee80211_prep_hw_scan(local)); | 414 | WARN_ON(!ieee80211_prep_hw_scan(local)); |
| 414 | rc = drv_hw_scan(local, local->hw_scan_req); | 415 | rc = drv_hw_scan(local, sdata, local->hw_scan_req); |
| 415 | } else | 416 | } else |
| 416 | rc = ieee80211_start_sw_scan(local); | 417 | rc = ieee80211_start_sw_scan(local); |
| 417 | 418 | ||
| @@ -655,7 +656,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
| 655 | } | 656 | } |
| 656 | 657 | ||
| 657 | if (local->hw_scan_req) { | 658 | if (local->hw_scan_req) { |
| 658 | int rc = drv_hw_scan(local, local->hw_scan_req); | 659 | int rc = drv_hw_scan(local, sdata, local->hw_scan_req); |
| 659 | mutex_unlock(&local->scan_mtx); | 660 | mutex_unlock(&local->scan_mtx); |
| 660 | if (rc) | 661 | if (rc) |
| 661 | ieee80211_scan_completed(&local->hw, true); | 662 | ieee80211_scan_completed(&local->hw, true); |
| @@ -728,10 +729,12 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |||
| 728 | } | 729 | } |
| 729 | 730 | ||
| 730 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | 731 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, |
| 731 | const u8 *ssid, u8 ssid_len) | 732 | const u8 *ssid, u8 ssid_len, |
| 733 | struct ieee80211_channel *chan) | ||
| 732 | { | 734 | { |
| 733 | struct ieee80211_local *local = sdata->local; | 735 | struct ieee80211_local *local = sdata->local; |
| 734 | int ret = -EBUSY; | 736 | int ret = -EBUSY; |
| 737 | enum nl80211_band band; | ||
| 735 | 738 | ||
| 736 | mutex_lock(&local->scan_mtx); | 739 | mutex_lock(&local->scan_mtx); |
| 737 | 740 | ||
| @@ -739,6 +742,30 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
| 739 | if (local->scan_req) | 742 | if (local->scan_req) |
| 740 | goto unlock; | 743 | goto unlock; |
| 741 | 744 | ||
| 745 | /* fill internal scan request */ | ||
| 746 | if (!chan) { | ||
| 747 | int i, nchan = 0; | ||
| 748 | |||
| 749 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
| 750 | if (!local->hw.wiphy->bands[band]) | ||
| 751 | continue; | ||
| 752 | for (i = 0; | ||
| 753 | i < local->hw.wiphy->bands[band]->n_channels; | ||
| 754 | i++) { | ||
| 755 | local->int_scan_req->channels[nchan] = | ||
| 756 | &local->hw.wiphy->bands[band]->channels[i]; | ||
| 757 | nchan++; | ||
| 758 | } | ||
| 759 | } | ||
| 760 | |||
| 761 | local->int_scan_req->n_channels = nchan; | ||
| 762 | } else { | ||
| 763 | local->int_scan_req->channels[0] = chan; | ||
| 764 | local->int_scan_req->n_channels = 1; | ||
| 765 | } | ||
| 766 | |||
| 767 | local->int_scan_req->ssids = &local->scan_ssid; | ||
| 768 | local->int_scan_req->n_ssids = 1; | ||
| 742 | memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); | 769 | memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); |
| 743 | local->int_scan_req->ssids[0].ssid_len = ssid_len; | 770 | local->int_scan_req->ssids[0].ssid_len = ssid_len; |
| 744 | 771 | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ff0eb948917b..730197591ab5 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
| @@ -575,7 +575,7 @@ static int sta_info_buffer_expired(struct sta_info *sta, | |||
| 575 | } | 575 | } |
| 576 | 576 | ||
| 577 | 577 | ||
| 578 | static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | 578 | static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, |
| 579 | struct sta_info *sta) | 579 | struct sta_info *sta) |
| 580 | { | 580 | { |
| 581 | unsigned long flags; | 581 | unsigned long flags; |
| @@ -583,7 +583,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
| 583 | struct ieee80211_sub_if_data *sdata; | 583 | struct ieee80211_sub_if_data *sdata; |
| 584 | 584 | ||
| 585 | if (skb_queue_empty(&sta->ps_tx_buf)) | 585 | if (skb_queue_empty(&sta->ps_tx_buf)) |
| 586 | return; | 586 | return false; |
| 587 | 587 | ||
| 588 | for (;;) { | 588 | for (;;) { |
| 589 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); | 589 | spin_lock_irqsave(&sta->ps_tx_buf.lock, flags); |
| @@ -608,6 +608,8 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
| 608 | if (skb_queue_empty(&sta->ps_tx_buf)) | 608 | if (skb_queue_empty(&sta->ps_tx_buf)) |
| 609 | sta_info_clear_tim_bit(sta); | 609 | sta_info_clear_tim_bit(sta); |
| 610 | } | 610 | } |
| 611 | |||
| 612 | return true; | ||
| 611 | } | 613 | } |
| 612 | 614 | ||
| 613 | static int __must_check __sta_info_destroy(struct sta_info *sta) | 615 | static int __must_check __sta_info_destroy(struct sta_info *sta) |
| @@ -755,15 +757,20 @@ static void sta_info_cleanup(unsigned long data) | |||
| 755 | { | 757 | { |
| 756 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 758 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
| 757 | struct sta_info *sta; | 759 | struct sta_info *sta; |
| 760 | bool timer_needed = false; | ||
| 758 | 761 | ||
| 759 | rcu_read_lock(); | 762 | rcu_read_lock(); |
| 760 | list_for_each_entry_rcu(sta, &local->sta_list, list) | 763 | list_for_each_entry_rcu(sta, &local->sta_list, list) |
| 761 | sta_info_cleanup_expire_buffered(local, sta); | 764 | if (sta_info_cleanup_expire_buffered(local, sta)) |
| 765 | timer_needed = true; | ||
| 762 | rcu_read_unlock(); | 766 | rcu_read_unlock(); |
| 763 | 767 | ||
| 764 | if (local->quiescing) | 768 | if (local->quiescing) |
| 765 | return; | 769 | return; |
| 766 | 770 | ||
| 771 | if (!timer_needed) | ||
| 772 | return; | ||
| 773 | |||
| 767 | local->sta_cleanup.expires = | 774 | local->sta_cleanup.expires = |
| 768 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); | 775 | round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); |
| 769 | add_timer(&local->sta_cleanup); | 776 | add_timer(&local->sta_cleanup); |
| @@ -848,8 +855,12 @@ struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, | |||
| 848 | struct sta_info *sta, *nxt; | 855 | struct sta_info *sta, *nxt; |
| 849 | 856 | ||
| 850 | /* Just return a random station ... first in list ... */ | 857 | /* Just return a random station ... first in list ... */ |
| 851 | for_each_sta_info(hw_to_local(hw), addr, sta, nxt) | 858 | for_each_sta_info(hw_to_local(hw), addr, sta, nxt) { |
| 859 | if (!sta->uploaded) | ||
| 860 | return NULL; | ||
| 852 | return &sta->sta; | 861 | return &sta->sta; |
| 862 | } | ||
| 863 | |||
| 853 | return NULL; | 864 | return NULL; |
| 854 | } | 865 | } |
| 855 | EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); | 866 | EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); |
| @@ -857,14 +868,19 @@ EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); | |||
| 857 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, | 868 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif, |
| 858 | const u8 *addr) | 869 | const u8 *addr) |
| 859 | { | 870 | { |
| 860 | struct ieee80211_sub_if_data *sdata; | 871 | struct sta_info *sta; |
| 861 | 872 | ||
| 862 | if (!vif) | 873 | if (!vif) |
| 863 | return NULL; | 874 | return NULL; |
| 864 | 875 | ||
| 865 | sdata = vif_to_sdata(vif); | 876 | sta = sta_info_get_bss(vif_to_sdata(vif), addr); |
| 877 | if (!sta) | ||
| 878 | return NULL; | ||
| 879 | |||
| 880 | if (!sta->uploaded) | ||
| 881 | return NULL; | ||
| 866 | 882 | ||
| 867 | return ieee80211_find_sta_by_hw(&sdata->local->hw, addr); | 883 | return &sta->sta; |
| 868 | } | 884 | } |
| 869 | EXPORT_SYMBOL(ieee80211_find_sta); | 885 | EXPORT_SYMBOL(ieee80211_find_sta); |
| 870 | 886 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 11805a3a626f..94613af009f3 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
| @@ -171,6 +171,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 171 | struct net_device *prev_dev = NULL; | 171 | struct net_device *prev_dev = NULL; |
| 172 | struct sta_info *sta, *tmp; | 172 | struct sta_info *sta, *tmp; |
| 173 | int retry_count = -1, i; | 173 | int retry_count = -1, i; |
| 174 | int rates_idx = -1; | ||
| 174 | bool send_to_cooked; | 175 | bool send_to_cooked; |
| 175 | 176 | ||
| 176 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 177 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
| @@ -178,6 +179,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 178 | if (i >= hw->max_rates) { | 179 | if (i >= hw->max_rates) { |
| 179 | info->status.rates[i].idx = -1; | 180 | info->status.rates[i].idx = -1; |
| 180 | info->status.rates[i].count = 0; | 181 | info->status.rates[i].count = 0; |
| 182 | } else if (info->status.rates[i].idx >= 0) { | ||
| 183 | rates_idx = i; | ||
| 181 | } | 184 | } |
| 182 | 185 | ||
| 183 | retry_count += info->status.rates[i].count; | 186 | retry_count += info->status.rates[i].count; |
| @@ -206,6 +209,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 206 | return; | 209 | return; |
| 207 | } | 210 | } |
| 208 | 211 | ||
| 212 | if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && | ||
| 213 | (rates_idx != -1)) | ||
| 214 | sta->last_tx_rate = info->status.rates[rates_idx]; | ||
| 215 | |||
| 209 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | 216 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && |
| 210 | (ieee80211_is_data_qos(fc))) { | 217 | (ieee80211_is_data_qos(fc))) { |
| 211 | u16 tid, ssn; | 218 | u16 tid, ssn; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 2cb77267f733..f3841f43249e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -429,6 +429,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
| 429 | struct sta_info *sta = tx->sta; | 429 | struct sta_info *sta = tx->sta; |
| 430 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 430 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
| 431 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 431 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
| 432 | struct ieee80211_local *local = tx->local; | ||
| 432 | u32 staflags; | 433 | u32 staflags; |
| 433 | 434 | ||
| 434 | if (unlikely(!sta || | 435 | if (unlikely(!sta || |
| @@ -476,6 +477,12 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
| 476 | info->control.vif = &tx->sdata->vif; | 477 | info->control.vif = &tx->sdata->vif; |
| 477 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 478 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
| 478 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); | 479 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); |
| 480 | |||
| 481 | if (!timer_pending(&local->sta_cleanup)) | ||
| 482 | mod_timer(&local->sta_cleanup, | ||
| 483 | round_jiffies(jiffies + | ||
| 484 | STA_INFO_CLEANUP_INTERVAL)); | ||
| 485 | |||
| 479 | return TX_QUEUED; | 486 | return TX_QUEUED; |
| 480 | } | 487 | } |
| 481 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 488 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
| @@ -586,7 +593,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
| 586 | struct ieee80211_hdr *hdr = (void *)tx->skb->data; | 593 | struct ieee80211_hdr *hdr = (void *)tx->skb->data; |
| 587 | struct ieee80211_supported_band *sband; | 594 | struct ieee80211_supported_band *sband; |
| 588 | struct ieee80211_rate *rate; | 595 | struct ieee80211_rate *rate; |
| 589 | int i, len; | 596 | int i; |
| 597 | u32 len; | ||
| 590 | bool inval = false, rts = false, short_preamble = false; | 598 | bool inval = false, rts = false, short_preamble = false; |
| 591 | struct ieee80211_tx_rate_control txrc; | 599 | struct ieee80211_tx_rate_control txrc; |
| 592 | u32 sta_flags; | 600 | u32 sta_flags; |
| @@ -595,7 +603,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
| 595 | 603 | ||
| 596 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 604 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
| 597 | 605 | ||
| 598 | len = min_t(int, tx->skb->len + FCS_LEN, | 606 | len = min_t(u32, tx->skb->len + FCS_LEN, |
| 599 | tx->local->hw.wiphy->frag_threshold); | 607 | tx->local->hw.wiphy->frag_threshold); |
| 600 | 608 | ||
| 601 | /* set up the tx rate control struct we give the RC algo */ | 609 | /* set up the tx rate control struct we give the RC algo */ |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index bdb1d05b16fc..3dd07600199d 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
| @@ -213,15 +213,25 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
| 213 | 213 | ||
| 214 | sband = local->hw.wiphy->bands[wk->chan->band]; | 214 | sband = local->hw.wiphy->bands[wk->chan->band]; |
| 215 | 215 | ||
| 216 | /* | 216 | if (wk->assoc.supp_rates_len) { |
| 217 | * Get all rates supported by the device and the AP as | 217 | /* |
| 218 | * some APs don't like getting a superset of their rates | 218 | * Get all rates supported by the device and the AP as |
| 219 | * in the association request (e.g. D-Link DAP 1353 in | 219 | * some APs don't like getting a superset of their rates |
| 220 | * b-only mode)... | 220 | * in the association request (e.g. D-Link DAP 1353 in |
| 221 | */ | 221 | * b-only mode)... |
| 222 | rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, | 222 | */ |
| 223 | wk->assoc.supp_rates_len, | 223 | rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, |
| 224 | sband, &rates); | 224 | wk->assoc.supp_rates_len, |
| 225 | sband, &rates); | ||
| 226 | } else { | ||
| 227 | /* | ||
| 228 | * In case AP not provide any supported rates information | ||
| 229 | * before association, we send information element(s) with | ||
| 230 | * all rates that we support. | ||
| 231 | */ | ||
| 232 | rates = ~0; | ||
| 233 | rates_len = sband->n_bitrates; | ||
| 234 | } | ||
| 225 | 235 | ||
| 226 | skb = alloc_skb(local->hw.extra_tx_headroom + | 236 | skb = alloc_skb(local->hw.extra_tx_headroom + |
| 227 | sizeof(*mgmt) + /* bit too much but doesn't matter */ | 237 | sizeof(*mgmt) + /* bit too much but doesn't matter */ |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 8fb0ae616761..7ba06939829f 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
| @@ -802,7 +802,7 @@ static int sync_thread_backup(void *data) | |||
| 802 | ip_vs_backup_mcast_ifn, ip_vs_backup_syncid); | 802 | ip_vs_backup_mcast_ifn, ip_vs_backup_syncid); |
| 803 | 803 | ||
| 804 | while (!kthread_should_stop()) { | 804 | while (!kthread_should_stop()) { |
| 805 | wait_event_interruptible(*tinfo->sock->sk->sk_sleep, | 805 | wait_event_interruptible(*sk_sleep(tinfo->sock->sk), |
| 806 | !skb_queue_empty(&tinfo->sock->sk->sk_receive_queue) | 806 | !skb_queue_empty(&tinfo->sock->sk->sk_receive_queue) |
| 807 | || kthread_should_stop()); | 807 | || kthread_should_stop()); |
| 808 | 808 | ||
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index fa07f044b599..06cb02796a0e 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
| @@ -739,7 +739,7 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, | |||
| 739 | DEFINE_WAIT(wait); | 739 | DEFINE_WAIT(wait); |
| 740 | 740 | ||
| 741 | for (;;) { | 741 | for (;;) { |
| 742 | prepare_to_wait(sk->sk_sleep, &wait, | 742 | prepare_to_wait(sk_sleep(sk), &wait, |
| 743 | TASK_INTERRUPTIBLE); | 743 | TASK_INTERRUPTIBLE); |
| 744 | if (sk->sk_state != TCP_SYN_SENT) | 744 | if (sk->sk_state != TCP_SYN_SENT) |
| 745 | break; | 745 | break; |
| @@ -752,7 +752,7 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, | |||
| 752 | err = -ERESTARTSYS; | 752 | err = -ERESTARTSYS; |
| 753 | break; | 753 | break; |
| 754 | } | 754 | } |
| 755 | finish_wait(sk->sk_sleep, &wait); | 755 | finish_wait(sk_sleep(sk), &wait); |
| 756 | if (err) | 756 | if (err) |
| 757 | goto out_release; | 757 | goto out_release; |
| 758 | } | 758 | } |
| @@ -798,7 +798,7 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 798 | * hooked into the SABM we saved | 798 | * hooked into the SABM we saved |
| 799 | */ | 799 | */ |
| 800 | for (;;) { | 800 | for (;;) { |
| 801 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 801 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 802 | skb = skb_dequeue(&sk->sk_receive_queue); | 802 | skb = skb_dequeue(&sk->sk_receive_queue); |
| 803 | if (skb) | 803 | if (skb) |
| 804 | break; | 804 | break; |
| @@ -816,7 +816,7 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 816 | err = -ERESTARTSYS; | 816 | err = -ERESTARTSYS; |
| 817 | break; | 817 | break; |
| 818 | } | 818 | } |
| 819 | finish_wait(sk->sk_sleep, &wait); | 819 | finish_wait(sk_sleep(sk), &wait); |
| 820 | if (err) | 820 | if (err) |
| 821 | goto out_release; | 821 | goto out_release; |
| 822 | 822 | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f162d59d8161..2078a277e06b 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -2228,8 +2228,6 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, | |||
| 2228 | case SIOCGIFDSTADDR: | 2228 | case SIOCGIFDSTADDR: |
| 2229 | case SIOCSIFDSTADDR: | 2229 | case SIOCSIFDSTADDR: |
| 2230 | case SIOCSIFFLAGS: | 2230 | case SIOCSIFFLAGS: |
| 2231 | if (!net_eq(sock_net(sk), &init_net)) | ||
| 2232 | return -ENOIOCTLCMD; | ||
| 2233 | return inet_dgram_ops.ioctl(sock, cmd, arg); | 2231 | return inet_dgram_ops.ioctl(sock, cmd, arg); |
| 2234 | #endif | 2232 | #endif |
| 2235 | 2233 | ||
diff --git a/net/phonet/pep.c b/net/phonet/pep.c index e2a95762abd3..af4d38bc3b22 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c | |||
| @@ -664,12 +664,12 @@ static int pep_wait_connreq(struct sock *sk, int noblock) | |||
| 664 | if (signal_pending(tsk)) | 664 | if (signal_pending(tsk)) |
| 665 | return sock_intr_errno(timeo); | 665 | return sock_intr_errno(timeo); |
| 666 | 666 | ||
| 667 | prepare_to_wait_exclusive(&sk->sk_socket->wait, &wait, | 667 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, |
| 668 | TASK_INTERRUPTIBLE); | 668 | TASK_INTERRUPTIBLE); |
| 669 | release_sock(sk); | 669 | release_sock(sk); |
| 670 | timeo = schedule_timeout(timeo); | 670 | timeo = schedule_timeout(timeo); |
| 671 | lock_sock(sk); | 671 | lock_sock(sk); |
| 672 | finish_wait(&sk->sk_socket->wait, &wait); | 672 | finish_wait(sk_sleep(sk), &wait); |
| 673 | } | 673 | } |
| 674 | 674 | ||
| 675 | return 0; | 675 | return 0; |
| @@ -910,10 +910,10 @@ disabled: | |||
| 910 | goto out; | 910 | goto out; |
| 911 | } | 911 | } |
| 912 | 912 | ||
| 913 | prepare_to_wait(&sk->sk_socket->wait, &wait, | 913 | prepare_to_wait(sk_sleep(sk), &wait, |
| 914 | TASK_INTERRUPTIBLE); | 914 | TASK_INTERRUPTIBLE); |
| 915 | done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits)); | 915 | done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits)); |
| 916 | finish_wait(&sk->sk_socket->wait, &wait); | 916 | finish_wait(sk_sleep(sk), &wait); |
| 917 | 917 | ||
| 918 | if (sk->sk_state != TCP_ESTABLISHED) | 918 | if (sk->sk_state != TCP_ESTABLISHED) |
| 919 | goto disabled; | 919 | goto disabled; |
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 9b4ced6e0968..c33da6576942 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c | |||
| @@ -46,9 +46,16 @@ struct phonet_net { | |||
| 46 | 46 | ||
| 47 | int phonet_net_id __read_mostly; | 47 | int phonet_net_id __read_mostly; |
| 48 | 48 | ||
| 49 | static struct phonet_net *phonet_pernet(struct net *net) | ||
| 50 | { | ||
| 51 | BUG_ON(!net); | ||
| 52 | |||
| 53 | return net_generic(net, phonet_net_id); | ||
| 54 | } | ||
| 55 | |||
| 49 | struct phonet_device_list *phonet_device_list(struct net *net) | 56 | struct phonet_device_list *phonet_device_list(struct net *net) |
| 50 | { | 57 | { |
| 51 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 58 | struct phonet_net *pnn = phonet_pernet(net); |
| 52 | return &pnn->pndevs; | 59 | return &pnn->pndevs; |
| 53 | } | 60 | } |
| 54 | 61 | ||
| @@ -261,7 +268,7 @@ static int phonet_device_autoconf(struct net_device *dev) | |||
| 261 | 268 | ||
| 262 | static void phonet_route_autodel(struct net_device *dev) | 269 | static void phonet_route_autodel(struct net_device *dev) |
| 263 | { | 270 | { |
| 264 | struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id); | 271 | struct phonet_net *pnn = phonet_pernet(dev_net(dev)); |
| 265 | unsigned i; | 272 | unsigned i; |
| 266 | DECLARE_BITMAP(deleted, 64); | 273 | DECLARE_BITMAP(deleted, 64); |
| 267 | 274 | ||
| @@ -313,7 +320,7 @@ static struct notifier_block phonet_device_notifier = { | |||
| 313 | /* Per-namespace Phonet devices handling */ | 320 | /* Per-namespace Phonet devices handling */ |
| 314 | static int __net_init phonet_init_net(struct net *net) | 321 | static int __net_init phonet_init_net(struct net *net) |
| 315 | { | 322 | { |
| 316 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 323 | struct phonet_net *pnn = phonet_pernet(net); |
| 317 | 324 | ||
| 318 | if (!proc_net_fops_create(net, "phonet", 0, &pn_sock_seq_fops)) | 325 | if (!proc_net_fops_create(net, "phonet", 0, &pn_sock_seq_fops)) |
| 319 | return -ENOMEM; | 326 | return -ENOMEM; |
| @@ -326,7 +333,7 @@ static int __net_init phonet_init_net(struct net *net) | |||
| 326 | 333 | ||
| 327 | static void __net_exit phonet_exit_net(struct net *net) | 334 | static void __net_exit phonet_exit_net(struct net *net) |
| 328 | { | 335 | { |
| 329 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 336 | struct phonet_net *pnn = phonet_pernet(net); |
| 330 | struct net_device *dev; | 337 | struct net_device *dev; |
| 331 | unsigned i; | 338 | unsigned i; |
| 332 | 339 | ||
| @@ -376,7 +383,7 @@ void phonet_device_exit(void) | |||
| 376 | 383 | ||
| 377 | int phonet_route_add(struct net_device *dev, u8 daddr) | 384 | int phonet_route_add(struct net_device *dev, u8 daddr) |
| 378 | { | 385 | { |
| 379 | struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id); | 386 | struct phonet_net *pnn = phonet_pernet(dev_net(dev)); |
| 380 | struct phonet_routes *routes = &pnn->routes; | 387 | struct phonet_routes *routes = &pnn->routes; |
| 381 | int err = -EEXIST; | 388 | int err = -EEXIST; |
| 382 | 389 | ||
| @@ -393,7 +400,7 @@ int phonet_route_add(struct net_device *dev, u8 daddr) | |||
| 393 | 400 | ||
| 394 | int phonet_route_del(struct net_device *dev, u8 daddr) | 401 | int phonet_route_del(struct net_device *dev, u8 daddr) |
| 395 | { | 402 | { |
| 396 | struct phonet_net *pnn = net_generic(dev_net(dev), phonet_net_id); | 403 | struct phonet_net *pnn = phonet_pernet(dev_net(dev)); |
| 397 | struct phonet_routes *routes = &pnn->routes; | 404 | struct phonet_routes *routes = &pnn->routes; |
| 398 | 405 | ||
| 399 | daddr = daddr >> 2; | 406 | daddr = daddr >> 2; |
| @@ -413,7 +420,7 @@ int phonet_route_del(struct net_device *dev, u8 daddr) | |||
| 413 | 420 | ||
| 414 | struct net_device *phonet_route_get(struct net *net, u8 daddr) | 421 | struct net_device *phonet_route_get(struct net *net, u8 daddr) |
| 415 | { | 422 | { |
| 416 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 423 | struct phonet_net *pnn = phonet_pernet(net); |
| 417 | struct phonet_routes *routes = &pnn->routes; | 424 | struct phonet_routes *routes = &pnn->routes; |
| 418 | struct net_device *dev; | 425 | struct net_device *dev; |
| 419 | 426 | ||
| @@ -428,7 +435,7 @@ struct net_device *phonet_route_get(struct net *net, u8 daddr) | |||
| 428 | 435 | ||
| 429 | struct net_device *phonet_route_output(struct net *net, u8 daddr) | 436 | struct net_device *phonet_route_output(struct net *net, u8 daddr) |
| 430 | { | 437 | { |
| 431 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 438 | struct phonet_net *pnn = phonet_pernet(net); |
| 432 | struct phonet_routes *routes = &pnn->routes; | 439 | struct phonet_routes *routes = &pnn->routes; |
| 433 | struct net_device *dev; | 440 | struct net_device *dev; |
| 434 | 441 | ||
diff --git a/net/phonet/socket.c b/net/phonet/socket.c index c785bfd0744f..6e9848bf0370 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c | |||
| @@ -265,7 +265,7 @@ static unsigned int pn_socket_poll(struct file *file, struct socket *sock, | |||
| 265 | struct pep_sock *pn = pep_sk(sk); | 265 | struct pep_sock *pn = pep_sk(sk); |
| 266 | unsigned int mask = 0; | 266 | unsigned int mask = 0; |
| 267 | 267 | ||
| 268 | poll_wait(file, &sock->wait, wait); | 268 | poll_wait(file, sk_sleep(sk), wait); |
| 269 | 269 | ||
| 270 | switch (sk->sk_state) { | 270 | switch (sk->sk_state) { |
| 271 | case TCP_LISTEN: | 271 | case TCP_LISTEN: |
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index 7919a9edb8e9..aebfecbdb841 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c | |||
| @@ -158,7 +158,7 @@ static unsigned int rds_poll(struct file *file, struct socket *sock, | |||
| 158 | unsigned int mask = 0; | 158 | unsigned int mask = 0; |
| 159 | unsigned long flags; | 159 | unsigned long flags; |
| 160 | 160 | ||
| 161 | poll_wait(file, sk->sk_sleep, wait); | 161 | poll_wait(file, sk_sleep(sk), wait); |
| 162 | 162 | ||
| 163 | if (rs->rs_seen_congestion) | 163 | if (rs->rs_seen_congestion) |
| 164 | poll_wait(file, &rds_poll_waitq, wait); | 164 | poll_wait(file, &rds_poll_waitq, wait); |
diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c index 5ea82fc47c3e..e599ba2f950d 100644 --- a/net/rds/rdma_transport.c +++ b/net/rds/rdma_transport.c | |||
| @@ -133,7 +133,7 @@ static int __init rds_rdma_listen_init(void) | |||
| 133 | ret = PTR_ERR(cm_id); | 133 | ret = PTR_ERR(cm_id); |
| 134 | printk(KERN_ERR "RDS/RDMA: failed to setup listener, " | 134 | printk(KERN_ERR "RDS/RDMA: failed to setup listener, " |
| 135 | "rdma_create_id() returned %d\n", ret); | 135 | "rdma_create_id() returned %d\n", ret); |
| 136 | goto out; | 136 | return ret; |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | sin.sin_family = AF_INET, | 139 | sin.sin_family = AF_INET, |
diff --git a/net/rds/rds.h b/net/rds/rds.h index 4bec6e2ed495..c224b5bb3ba9 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h | |||
| @@ -492,7 +492,7 @@ void rds_sock_put(struct rds_sock *rs); | |||
| 492 | void rds_wake_sk_sleep(struct rds_sock *rs); | 492 | void rds_wake_sk_sleep(struct rds_sock *rs); |
| 493 | static inline void __rds_wake_sk_sleep(struct sock *sk) | 493 | static inline void __rds_wake_sk_sleep(struct sock *sk) |
| 494 | { | 494 | { |
| 495 | wait_queue_head_t *waitq = sk->sk_sleep; | 495 | wait_queue_head_t *waitq = sk_sleep(sk); |
| 496 | 496 | ||
| 497 | if (!sock_flag(sk, SOCK_DEAD) && waitq) | 497 | if (!sock_flag(sk, SOCK_DEAD) && waitq) |
| 498 | wake_up(waitq); | 498 | wake_up(waitq); |
diff --git a/net/rds/recv.c b/net/rds/recv.c index e2a2b9344f7b..795a00b7f2cb 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c | |||
| @@ -432,7 +432,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
| 432 | break; | 432 | break; |
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | timeo = wait_event_interruptible_timeout(*sk->sk_sleep, | 435 | timeo = wait_event_interruptible_timeout(*sk_sleep(sk), |
| 436 | (!list_empty(&rs->rs_notify_queue) || | 436 | (!list_empty(&rs->rs_notify_queue) || |
| 437 | rs->rs_cong_notify || | 437 | rs->rs_cong_notify || |
| 438 | rds_next_incoming(rs, &inc)), timeo); | 438 | rds_next_incoming(rs, &inc)), timeo); |
diff --git a/net/rds/send.c b/net/rds/send.c index 53d6795ac9d0..9c1c6bcaa6c9 100644 --- a/net/rds/send.c +++ b/net/rds/send.c | |||
| @@ -915,7 +915,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
| 915 | goto out; | 915 | goto out; |
| 916 | } | 916 | } |
| 917 | 917 | ||
| 918 | timeo = wait_event_interruptible_timeout(*sk->sk_sleep, | 918 | timeo = wait_event_interruptible_timeout(*sk_sleep(sk), |
| 919 | rds_send_queue_rm(rs, conn, rm, | 919 | rds_send_queue_rm(rs, conn, rm, |
| 920 | rs->rs_bound_port, | 920 | rs->rs_bound_port, |
| 921 | dport, | 921 | dport, |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 4fb711a035f4..8e45e76a95f5 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
| @@ -845,7 +845,7 @@ rose_try_next_neigh: | |||
| 845 | DEFINE_WAIT(wait); | 845 | DEFINE_WAIT(wait); |
| 846 | 846 | ||
| 847 | for (;;) { | 847 | for (;;) { |
| 848 | prepare_to_wait(sk->sk_sleep, &wait, | 848 | prepare_to_wait(sk_sleep(sk), &wait, |
| 849 | TASK_INTERRUPTIBLE); | 849 | TASK_INTERRUPTIBLE); |
| 850 | if (sk->sk_state != TCP_SYN_SENT) | 850 | if (sk->sk_state != TCP_SYN_SENT) |
| 851 | break; | 851 | break; |
| @@ -858,7 +858,7 @@ rose_try_next_neigh: | |||
| 858 | err = -ERESTARTSYS; | 858 | err = -ERESTARTSYS; |
| 859 | break; | 859 | break; |
| 860 | } | 860 | } |
| 861 | finish_wait(sk->sk_sleep, &wait); | 861 | finish_wait(sk_sleep(sk), &wait); |
| 862 | 862 | ||
| 863 | if (err) | 863 | if (err) |
| 864 | goto out_release; | 864 | goto out_release; |
| @@ -911,7 +911,7 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 911 | * hooked into the SABM we saved | 911 | * hooked into the SABM we saved |
| 912 | */ | 912 | */ |
| 913 | for (;;) { | 913 | for (;;) { |
| 914 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 914 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 915 | 915 | ||
| 916 | skb = skb_dequeue(&sk->sk_receive_queue); | 916 | skb = skb_dequeue(&sk->sk_receive_queue); |
| 917 | if (skb) | 917 | if (skb) |
| @@ -930,7 +930,7 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags) | |||
| 930 | err = -ERESTARTSYS; | 930 | err = -ERESTARTSYS; |
| 931 | break; | 931 | break; |
| 932 | } | 932 | } |
| 933 | finish_wait(sk->sk_sleep, &wait); | 933 | finish_wait(sk_sleep(sk), &wait); |
| 934 | if (err) | 934 | if (err) |
| 935 | goto out_release; | 935 | goto out_release; |
| 936 | 936 | ||
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index c060095b27ce..0b9bb2085ce4 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
| @@ -62,13 +62,15 @@ static inline int rxrpc_writable(struct sock *sk) | |||
| 62 | static void rxrpc_write_space(struct sock *sk) | 62 | static void rxrpc_write_space(struct sock *sk) |
| 63 | { | 63 | { |
| 64 | _enter("%p", sk); | 64 | _enter("%p", sk); |
| 65 | read_lock(&sk->sk_callback_lock); | 65 | rcu_read_lock(); |
| 66 | if (rxrpc_writable(sk)) { | 66 | if (rxrpc_writable(sk)) { |
| 67 | if (sk_has_sleeper(sk)) | 67 | struct socket_wq *wq = rcu_dereference(sk->sk_wq); |
| 68 | wake_up_interruptible(sk->sk_sleep); | 68 | |
| 69 | if (wq_has_sleeper(wq)) | ||
| 70 | wake_up_interruptible(&wq->wait); | ||
| 69 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 71 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
| 70 | } | 72 | } |
| 71 | read_unlock(&sk->sk_callback_lock); | 73 | rcu_read_unlock(); |
| 72 | } | 74 | } |
| 73 | 75 | ||
| 74 | /* | 76 | /* |
| @@ -589,7 +591,7 @@ static unsigned int rxrpc_poll(struct file *file, struct socket *sock, | |||
| 589 | unsigned int mask; | 591 | unsigned int mask; |
| 590 | struct sock *sk = sock->sk; | 592 | struct sock *sk = sock->sk; |
| 591 | 593 | ||
| 592 | sock_poll_wait(file, sk->sk_sleep, wait); | 594 | sock_poll_wait(file, sk_sleep(sk), wait); |
| 593 | mask = 0; | 595 | mask = 0; |
| 594 | 596 | ||
| 595 | /* the socket is readable if there are any messages waiting on the Rx | 597 | /* the socket is readable if there are any messages waiting on the Rx |
diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c index 60c2b94e6b54..0c65013e3bfe 100644 --- a/net/rxrpc/ar-recvmsg.c +++ b/net/rxrpc/ar-recvmsg.c | |||
| @@ -91,7 +91,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 91 | 91 | ||
| 92 | /* wait for a message to turn up */ | 92 | /* wait for a message to turn up */ |
| 93 | release_sock(&rx->sk); | 93 | release_sock(&rx->sk); |
| 94 | prepare_to_wait_exclusive(rx->sk.sk_sleep, &wait, | 94 | prepare_to_wait_exclusive(sk_sleep(&rx->sk), &wait, |
| 95 | TASK_INTERRUPTIBLE); | 95 | TASK_INTERRUPTIBLE); |
| 96 | ret = sock_error(&rx->sk); | 96 | ret = sock_error(&rx->sk); |
| 97 | if (ret) | 97 | if (ret) |
| @@ -102,7 +102,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 102 | goto wait_interrupted; | 102 | goto wait_interrupted; |
| 103 | timeo = schedule_timeout(timeo); | 103 | timeo = schedule_timeout(timeo); |
| 104 | } | 104 | } |
| 105 | finish_wait(rx->sk.sk_sleep, &wait); | 105 | finish_wait(sk_sleep(&rx->sk), &wait); |
| 106 | lock_sock(&rx->sk); | 106 | lock_sock(&rx->sk); |
| 107 | continue; | 107 | continue; |
| 108 | } | 108 | } |
| @@ -356,7 +356,7 @@ csum_copy_error: | |||
| 356 | wait_interrupted: | 356 | wait_interrupted: |
| 357 | ret = sock_intr_errno(timeo); | 357 | ret = sock_intr_errno(timeo); |
| 358 | wait_error: | 358 | wait_error: |
| 359 | finish_wait(rx->sk.sk_sleep, &wait); | 359 | finish_wait(sk_sleep(&rx->sk), &wait); |
| 360 | if (continue_call) | 360 | if (continue_call) |
| 361 | rxrpc_put_call(continue_call); | 361 | rxrpc_put_call(continue_call); |
| 362 | if (copied) | 362 | if (copied) |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index aeddabfb8e4e..a969b111bd76 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
| @@ -94,7 +94,7 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, | |||
| 94 | * Another cpu is holding lock, requeue & delay xmits for | 94 | * Another cpu is holding lock, requeue & delay xmits for |
| 95 | * some time. | 95 | * some time. |
| 96 | */ | 96 | */ |
| 97 | __get_cpu_var(netdev_rx_stat).cpu_collision++; | 97 | __get_cpu_var(softnet_data).cpu_collision++; |
| 98 | ret = dev_requeue_skb(skb, q); | 98 | ret = dev_requeue_skb(skb, q); |
| 99 | } | 99 | } |
| 100 | 100 | ||
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index c5a9ac566007..c65762823f5e 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
| @@ -123,8 +123,8 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
| 123 | case htons(ETH_P_IP): | 123 | case htons(ETH_P_IP): |
| 124 | { | 124 | { |
| 125 | const struct iphdr *iph = ip_hdr(skb); | 125 | const struct iphdr *iph = ip_hdr(skb); |
| 126 | h = iph->daddr; | 126 | h = (__force u32)iph->daddr; |
| 127 | h2 = iph->saddr ^ iph->protocol; | 127 | h2 = (__force u32)iph->saddr ^ iph->protocol; |
| 128 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && | 128 | if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && |
| 129 | (iph->protocol == IPPROTO_TCP || | 129 | (iph->protocol == IPPROTO_TCP || |
| 130 | iph->protocol == IPPROTO_UDP || | 130 | iph->protocol == IPPROTO_UDP || |
| @@ -138,8 +138,8 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
| 138 | case htons(ETH_P_IPV6): | 138 | case htons(ETH_P_IPV6): |
| 139 | { | 139 | { |
| 140 | struct ipv6hdr *iph = ipv6_hdr(skb); | 140 | struct ipv6hdr *iph = ipv6_hdr(skb); |
| 141 | h = iph->daddr.s6_addr32[3]; | 141 | h = (__force u32)iph->daddr.s6_addr32[3]; |
| 142 | h2 = iph->saddr.s6_addr32[3] ^ iph->nexthdr; | 142 | h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr; |
| 143 | if (iph->nexthdr == IPPROTO_TCP || | 143 | if (iph->nexthdr == IPPROTO_TCP || |
| 144 | iph->nexthdr == IPPROTO_UDP || | 144 | iph->nexthdr == IPPROTO_UDP || |
| 145 | iph->nexthdr == IPPROTO_UDPLITE || | 145 | iph->nexthdr == IPPROTO_UDPLITE || |
| @@ -150,7 +150,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
| 150 | break; | 150 | break; |
| 151 | } | 151 | } |
| 152 | default: | 152 | default: |
| 153 | h = (unsigned long)skb_dst(skb) ^ skb->protocol; | 153 | h = (unsigned long)skb_dst(skb) ^ (__force u32)skb->protocol; |
| 154 | h2 = (unsigned long)skb->sk; | 154 | h2 = (unsigned long)skb->sk; |
| 155 | } | 155 | } |
| 156 | 156 | ||
diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index 58b3e882a187..126b014eb79b 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig | |||
| @@ -37,6 +37,18 @@ menuconfig IP_SCTP | |||
| 37 | 37 | ||
| 38 | if IP_SCTP | 38 | if IP_SCTP |
| 39 | 39 | ||
| 40 | config NET_SCTPPROBE | ||
| 41 | tristate "SCTP: Association probing" | ||
| 42 | depends on PROC_FS && KPROBES | ||
| 43 | ---help--- | ||
| 44 | This module allows for capturing the changes to SCTP association | ||
| 45 | state in response to incoming packets. It is used for debugging | ||
| 46 | SCTP congestion control algorithms. If you don't understand | ||
| 47 | what was just said, you don't need it: say N. | ||
| 48 | |||
| 49 | To compile this code as a module, choose M here: the | ||
| 50 | module will be called sctp_probe. | ||
| 51 | |||
| 40 | config SCTP_DBG_MSG | 52 | config SCTP_DBG_MSG |
| 41 | bool "SCTP: Debug messages" | 53 | bool "SCTP: Debug messages" |
| 42 | help | 54 | help |
diff --git a/net/sctp/Makefile b/net/sctp/Makefile index 6b794734380a..5c30b7a873df 100644 --- a/net/sctp/Makefile +++ b/net/sctp/Makefile | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-$(CONFIG_IP_SCTP) += sctp.o | 5 | obj-$(CONFIG_IP_SCTP) += sctp.o |
| 6 | obj-$(CONFIG_NET_SCTPPROBE) += sctp_probe.o | ||
| 6 | 7 | ||
| 7 | sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ | 8 | sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ |
| 8 | protocol.o endpointola.o associola.o \ | 9 | protocol.o endpointola.o associola.o \ |
| @@ -11,6 +12,8 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ | |||
| 11 | tsnmap.o bind_addr.o socket.o primitive.o \ | 12 | tsnmap.o bind_addr.o socket.o primitive.o \ |
| 12 | output.o input.o debug.o ssnmap.o auth.o | 13 | output.o input.o debug.o ssnmap.o auth.o |
| 13 | 14 | ||
| 15 | sctp_probe-y := probe.o | ||
| 16 | |||
| 14 | sctp-$(CONFIG_SCTP_DBG_OBJCNT) += objcnt.o | 17 | sctp-$(CONFIG_SCTP_DBG_OBJCNT) += objcnt.o |
| 15 | sctp-$(CONFIG_PROC_FS) += proc.o | 18 | sctp-$(CONFIG_PROC_FS) += proc.o |
| 16 | sctp-$(CONFIG_SYSCTL) += sysctl.o | 19 | sctp-$(CONFIG_SYSCTL) += sysctl.o |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index df5abbff63e2..3912420cedcc 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -87,9 +87,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
| 87 | /* Retrieve the SCTP per socket area. */ | 87 | /* Retrieve the SCTP per socket area. */ |
| 88 | sp = sctp_sk((struct sock *)sk); | 88 | sp = sctp_sk((struct sock *)sk); |
| 89 | 89 | ||
| 90 | /* Init all variables to a known value. */ | ||
| 91 | memset(asoc, 0, sizeof(struct sctp_association)); | ||
| 92 | |||
| 93 | /* Discarding const is appropriate here. */ | 90 | /* Discarding const is appropriate here. */ |
| 94 | asoc->ep = (struct sctp_endpoint *)ep; | 91 | asoc->ep = (struct sctp_endpoint *)ep; |
| 95 | sctp_endpoint_hold(asoc->ep); | 92 | sctp_endpoint_hold(asoc->ep); |
| @@ -762,7 +759,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
| 762 | asoc->peer.retran_path = peer; | 759 | asoc->peer.retran_path = peer; |
| 763 | } | 760 | } |
| 764 | 761 | ||
| 765 | if (asoc->peer.active_path == asoc->peer.retran_path) { | 762 | if (asoc->peer.active_path == asoc->peer.retran_path && |
| 763 | peer->state != SCTP_UNCONFIRMED) { | ||
| 766 | asoc->peer.retran_path = peer; | 764 | asoc->peer.retran_path = peer; |
| 767 | } | 765 | } |
| 768 | 766 | ||
| @@ -1194,8 +1192,10 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
| 1194 | /* Remove any peer addresses not present in the new association. */ | 1192 | /* Remove any peer addresses not present in the new association. */ |
| 1195 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 1193 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
| 1196 | trans = list_entry(pos, struct sctp_transport, transports); | 1194 | trans = list_entry(pos, struct sctp_transport, transports); |
| 1197 | if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr)) | 1195 | if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr)) { |
| 1198 | sctp_assoc_del_peer(asoc, &trans->ipaddr); | 1196 | sctp_assoc_rm_peer(asoc, trans); |
| 1197 | continue; | ||
| 1198 | } | ||
| 1199 | 1199 | ||
| 1200 | if (asoc->state >= SCTP_STATE_ESTABLISHED) | 1200 | if (asoc->state >= SCTP_STATE_ESTABLISHED) |
| 1201 | sctp_transport_reset(trans); | 1201 | sctp_transport_reset(trans); |
| @@ -1318,12 +1318,13 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
| 1318 | /* Keep track of the next transport in case | 1318 | /* Keep track of the next transport in case |
| 1319 | * we don't find any active transport. | 1319 | * we don't find any active transport. |
| 1320 | */ | 1320 | */ |
| 1321 | if (!next) | 1321 | if (t->state != SCTP_UNCONFIRMED && !next) |
| 1322 | next = t; | 1322 | next = t; |
| 1323 | } | 1323 | } |
| 1324 | } | 1324 | } |
| 1325 | 1325 | ||
| 1326 | asoc->peer.retran_path = t; | 1326 | if (t) |
| 1327 | asoc->peer.retran_path = t; | ||
| 1327 | 1328 | ||
| 1328 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | 1329 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" |
| 1329 | " %p addr: ", | 1330 | " %p addr: ", |
| @@ -1483,7 +1484,7 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len) | |||
| 1483 | if (asoc->rwnd >= len) { | 1484 | if (asoc->rwnd >= len) { |
| 1484 | asoc->rwnd -= len; | 1485 | asoc->rwnd -= len; |
| 1485 | if (over) { | 1486 | if (over) { |
| 1486 | asoc->rwnd_press = asoc->rwnd; | 1487 | asoc->rwnd_press += asoc->rwnd; |
| 1487 | asoc->rwnd = 0; | 1488 | asoc->rwnd = 0; |
| 1488 | } | 1489 | } |
| 1489 | } else { | 1490 | } else { |
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 3eab6db59a37..476caaf100ed 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c | |||
| @@ -58,9 +58,9 @@ static void sctp_datamsg_init(struct sctp_datamsg *msg) | |||
| 58 | msg->send_failed = 0; | 58 | msg->send_failed = 0; |
| 59 | msg->send_error = 0; | 59 | msg->send_error = 0; |
| 60 | msg->can_abandon = 0; | 60 | msg->can_abandon = 0; |
| 61 | msg->can_delay = 1; | ||
| 61 | msg->expires_at = 0; | 62 | msg->expires_at = 0; |
| 62 | INIT_LIST_HEAD(&msg->chunks); | 63 | INIT_LIST_HEAD(&msg->chunks); |
| 63 | msg->msg_size = 0; | ||
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | /* Allocate and initialize datamsg. */ | 66 | /* Allocate and initialize datamsg. */ |
| @@ -157,7 +157,6 @@ static void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chu | |||
| 157 | { | 157 | { |
| 158 | sctp_datamsg_hold(msg); | 158 | sctp_datamsg_hold(msg); |
| 159 | chunk->msg = msg; | 159 | chunk->msg = msg; |
| 160 | msg->msg_size += chunk->skb->len; | ||
| 161 | } | 160 | } |
| 162 | 161 | ||
| 163 | 162 | ||
| @@ -247,6 +246,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
| 247 | if (msg_len >= first_len) { | 246 | if (msg_len >= first_len) { |
| 248 | msg_len -= first_len; | 247 | msg_len -= first_len; |
| 249 | whole = 1; | 248 | whole = 1; |
| 249 | msg->can_delay = 0; | ||
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | /* How many full sized? How many bytes leftover? */ | 252 | /* How many full sized? How many bytes leftover? */ |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 905fda582b92..e10acc01c75f 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
| @@ -70,8 +70,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
| 70 | struct sctp_shared_key *null_key; | 70 | struct sctp_shared_key *null_key; |
| 71 | int err; | 71 | int err; |
| 72 | 72 | ||
| 73 | memset(ep, 0, sizeof(struct sctp_endpoint)); | ||
| 74 | |||
| 75 | ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp); | 73 | ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp); |
| 76 | if (!ep->digest) | 74 | if (!ep->digest) |
| 77 | return NULL; | 75 | return NULL; |
| @@ -144,6 +142,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
| 144 | /* Use SCTP specific send buffer space queues. */ | 142 | /* Use SCTP specific send buffer space queues. */ |
| 145 | ep->sndbuf_policy = sctp_sndbuf_policy; | 143 | ep->sndbuf_policy = sctp_sndbuf_policy; |
| 146 | 144 | ||
| 145 | sk->sk_data_ready = sctp_data_ready; | ||
| 147 | sk->sk_write_space = sctp_write_space; | 146 | sk->sk_write_space = sctp_write_space; |
| 148 | sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); | 147 | sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); |
| 149 | 148 | ||
diff --git a/net/sctp/output.c b/net/sctp/output.c index fad261d41ec2..a646681f5acd 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
| @@ -429,24 +429,17 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
| 429 | list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { | 429 | list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { |
| 430 | list_del_init(&chunk->list); | 430 | list_del_init(&chunk->list); |
| 431 | if (sctp_chunk_is_data(chunk)) { | 431 | if (sctp_chunk_is_data(chunk)) { |
| 432 | /* 6.3.1 C4) When data is in flight and when allowed | ||
| 433 | * by rule C5, a new RTT measurement MUST be made each | ||
| 434 | * round trip. Furthermore, new RTT measurements | ||
| 435 | * SHOULD be made no more than once per round-trip | ||
| 436 | * for a given destination transport address. | ||
| 437 | */ | ||
| 432 | 438 | ||
| 433 | if (!chunk->resent) { | 439 | if (!tp->rto_pending) { |
| 434 | 440 | chunk->rtt_in_progress = 1; | |
| 435 | /* 6.3.1 C4) When data is in flight and when allowed | 441 | tp->rto_pending = 1; |
| 436 | * by rule C5, a new RTT measurement MUST be made each | ||
| 437 | * round trip. Furthermore, new RTT measurements | ||
| 438 | * SHOULD be made no more than once per round-trip | ||
| 439 | * for a given destination transport address. | ||
| 440 | */ | ||
| 441 | |||
| 442 | if (!tp->rto_pending) { | ||
| 443 | chunk->rtt_in_progress = 1; | ||
| 444 | tp->rto_pending = 1; | ||
| 445 | } | ||
| 446 | } | 442 | } |
| 447 | |||
| 448 | chunk->resent = 1; | ||
| 449 | |||
| 450 | has_data = 1; | 443 | has_data = 1; |
| 451 | } | 444 | } |
| 452 | 445 | ||
| @@ -681,7 +674,7 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, | |||
| 681 | * Don't delay large message writes that may have been | 674 | * Don't delay large message writes that may have been |
| 682 | * fragmeneted into small peices. | 675 | * fragmeneted into small peices. |
| 683 | */ | 676 | */ |
| 684 | if ((len < max) && (chunk->msg->msg_size < max)) { | 677 | if ((len < max) && chunk->msg->can_delay) { |
| 685 | retval = SCTP_XMIT_NAGLE_DELAY; | 678 | retval = SCTP_XMIT_NAGLE_DELAY; |
| 686 | goto finish; | 679 | goto finish; |
| 687 | } | 680 | } |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index abfc0b8dee74..5d057178ce0c 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
| @@ -62,7 +62,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
| 62 | struct list_head *transmitted_queue, | 62 | struct list_head *transmitted_queue, |
| 63 | struct sctp_transport *transport, | 63 | struct sctp_transport *transport, |
| 64 | struct sctp_sackhdr *sack, | 64 | struct sctp_sackhdr *sack, |
| 65 | __u32 highest_new_tsn); | 65 | __u32 *highest_new_tsn); |
| 66 | 66 | ||
| 67 | static void sctp_mark_missing(struct sctp_outq *q, | 67 | static void sctp_mark_missing(struct sctp_outq *q, |
| 68 | struct list_head *transmitted_queue, | 68 | struct list_head *transmitted_queue, |
| @@ -308,7 +308,7 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
| 308 | /* If it is data, queue it up, otherwise, send it | 308 | /* If it is data, queue it up, otherwise, send it |
| 309 | * immediately. | 309 | * immediately. |
| 310 | */ | 310 | */ |
| 311 | if (SCTP_CID_DATA == chunk->chunk_hdr->type) { | 311 | if (sctp_chunk_is_data(chunk)) { |
| 312 | /* Is it OK to queue data chunks? */ | 312 | /* Is it OK to queue data chunks? */ |
| 313 | /* From 9. Termination of Association | 313 | /* From 9. Termination of Association |
| 314 | * | 314 | * |
| @@ -598,11 +598,23 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
| 598 | if (fast_rtx && !chunk->fast_retransmit) | 598 | if (fast_rtx && !chunk->fast_retransmit) |
| 599 | continue; | 599 | continue; |
| 600 | 600 | ||
| 601 | redo: | ||
| 601 | /* Attempt to append this chunk to the packet. */ | 602 | /* Attempt to append this chunk to the packet. */ |
| 602 | status = sctp_packet_append_chunk(pkt, chunk); | 603 | status = sctp_packet_append_chunk(pkt, chunk); |
| 603 | 604 | ||
| 604 | switch (status) { | 605 | switch (status) { |
| 605 | case SCTP_XMIT_PMTU_FULL: | 606 | case SCTP_XMIT_PMTU_FULL: |
| 607 | if (!pkt->has_data && !pkt->has_cookie_echo) { | ||
| 608 | /* If this packet did not contain DATA then | ||
| 609 | * retransmission did not happen, so do it | ||
| 610 | * again. We'll ignore the error here since | ||
| 611 | * control chunks are already freed so there | ||
| 612 | * is nothing we can do. | ||
| 613 | */ | ||
| 614 | sctp_packet_transmit(pkt); | ||
| 615 | goto redo; | ||
| 616 | } | ||
| 617 | |||
| 606 | /* Send this packet. */ | 618 | /* Send this packet. */ |
| 607 | error = sctp_packet_transmit(pkt); | 619 | error = sctp_packet_transmit(pkt); |
| 608 | 620 | ||
| @@ -647,14 +659,6 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
| 647 | if (chunk->fast_retransmit == SCTP_NEED_FRTX) | 659 | if (chunk->fast_retransmit == SCTP_NEED_FRTX) |
| 648 | chunk->fast_retransmit = SCTP_DONT_FRTX; | 660 | chunk->fast_retransmit = SCTP_DONT_FRTX; |
| 649 | 661 | ||
| 650 | /* Force start T3-rtx timer when fast retransmitting | ||
| 651 | * the earliest outstanding TSN | ||
| 652 | */ | ||
| 653 | if (!timer && fast_rtx && | ||
| 654 | ntohl(chunk->subh.data_hdr->tsn) == | ||
| 655 | asoc->ctsn_ack_point + 1) | ||
| 656 | timer = 2; | ||
| 657 | |||
| 658 | q->empty = 0; | 662 | q->empty = 0; |
| 659 | break; | 663 | break; |
| 660 | } | 664 | } |
| @@ -854,6 +858,12 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
| 854 | if (status != SCTP_XMIT_OK) { | 858 | if (status != SCTP_XMIT_OK) { |
| 855 | /* put the chunk back */ | 859 | /* put the chunk back */ |
| 856 | list_add(&chunk->list, &q->control_chunk_list); | 860 | list_add(&chunk->list, &q->control_chunk_list); |
| 861 | } else if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) { | ||
| 862 | /* PR-SCTP C5) If a FORWARD TSN is sent, the | ||
| 863 | * sender MUST assure that at least one T3-rtx | ||
| 864 | * timer is running. | ||
| 865 | */ | ||
| 866 | sctp_transport_reset_timers(transport); | ||
| 857 | } | 867 | } |
| 858 | break; | 868 | break; |
| 859 | 869 | ||
| @@ -906,8 +916,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
| 906 | rtx_timeout, &start_timer); | 916 | rtx_timeout, &start_timer); |
| 907 | 917 | ||
| 908 | if (start_timer) | 918 | if (start_timer) |
| 909 | sctp_transport_reset_timers(transport, | 919 | sctp_transport_reset_timers(transport); |
| 910 | start_timer-1); | ||
| 911 | 920 | ||
| 912 | /* This can happen on COOKIE-ECHO resend. Only | 921 | /* This can happen on COOKIE-ECHO resend. Only |
| 913 | * one chunk can get bundled with a COOKIE-ECHO. | 922 | * one chunk can get bundled with a COOKIE-ECHO. |
| @@ -1040,7 +1049,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
| 1040 | list_add_tail(&chunk->transmitted_list, | 1049 | list_add_tail(&chunk->transmitted_list, |
| 1041 | &transport->transmitted); | 1050 | &transport->transmitted); |
| 1042 | 1051 | ||
| 1043 | sctp_transport_reset_timers(transport, 0); | 1052 | sctp_transport_reset_timers(transport); |
| 1044 | 1053 | ||
| 1045 | q->empty = 0; | 1054 | q->empty = 0; |
| 1046 | 1055 | ||
| @@ -1100,32 +1109,6 @@ static void sctp_sack_update_unack_data(struct sctp_association *assoc, | |||
| 1100 | assoc->unack_data = unack_data; | 1109 | assoc->unack_data = unack_data; |
| 1101 | } | 1110 | } |
| 1102 | 1111 | ||
| 1103 | /* Return the highest new tsn that is acknowledged by the given SACK chunk. */ | ||
| 1104 | static __u32 sctp_highest_new_tsn(struct sctp_sackhdr *sack, | ||
| 1105 | struct sctp_association *asoc) | ||
| 1106 | { | ||
| 1107 | struct sctp_transport *transport; | ||
| 1108 | struct sctp_chunk *chunk; | ||
| 1109 | __u32 highest_new_tsn, tsn; | ||
| 1110 | struct list_head *transport_list = &asoc->peer.transport_addr_list; | ||
| 1111 | |||
| 1112 | highest_new_tsn = ntohl(sack->cum_tsn_ack); | ||
| 1113 | |||
| 1114 | list_for_each_entry(transport, transport_list, transports) { | ||
| 1115 | list_for_each_entry(chunk, &transport->transmitted, | ||
| 1116 | transmitted_list) { | ||
| 1117 | tsn = ntohl(chunk->subh.data_hdr->tsn); | ||
| 1118 | |||
| 1119 | if (!chunk->tsn_gap_acked && | ||
| 1120 | TSN_lt(highest_new_tsn, tsn) && | ||
| 1121 | sctp_acked(sack, tsn)) | ||
| 1122 | highest_new_tsn = tsn; | ||
| 1123 | } | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | return highest_new_tsn; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | /* This is where we REALLY process a SACK. | 1112 | /* This is where we REALLY process a SACK. |
| 1130 | * | 1113 | * |
| 1131 | * Process the SACK against the outqueue. Mostly, this just frees | 1114 | * Process the SACK against the outqueue. Mostly, this just frees |
| @@ -1145,6 +1128,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
| 1145 | struct sctp_transport *primary = asoc->peer.primary_path; | 1128 | struct sctp_transport *primary = asoc->peer.primary_path; |
| 1146 | int count_of_newacks = 0; | 1129 | int count_of_newacks = 0; |
| 1147 | int gap_ack_blocks; | 1130 | int gap_ack_blocks; |
| 1131 | u8 accum_moved = 0; | ||
| 1148 | 1132 | ||
| 1149 | /* Grab the association's destination address list. */ | 1133 | /* Grab the association's destination address list. */ |
| 1150 | transport_list = &asoc->peer.transport_addr_list; | 1134 | transport_list = &asoc->peer.transport_addr_list; |
| @@ -1193,18 +1177,15 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
| 1193 | if (gap_ack_blocks) | 1177 | if (gap_ack_blocks) |
| 1194 | highest_tsn += ntohs(frags[gap_ack_blocks - 1].gab.end); | 1178 | highest_tsn += ntohs(frags[gap_ack_blocks - 1].gab.end); |
| 1195 | 1179 | ||
| 1196 | if (TSN_lt(asoc->highest_sacked, highest_tsn)) { | 1180 | if (TSN_lt(asoc->highest_sacked, highest_tsn)) |
| 1197 | highest_new_tsn = highest_tsn; | ||
| 1198 | asoc->highest_sacked = highest_tsn; | 1181 | asoc->highest_sacked = highest_tsn; |
| 1199 | } else { | ||
| 1200 | highest_new_tsn = sctp_highest_new_tsn(sack, asoc); | ||
| 1201 | } | ||
| 1202 | 1182 | ||
| 1183 | highest_new_tsn = sack_ctsn; | ||
| 1203 | 1184 | ||
| 1204 | /* Run through the retransmit queue. Credit bytes received | 1185 | /* Run through the retransmit queue. Credit bytes received |
| 1205 | * and free those chunks that we can. | 1186 | * and free those chunks that we can. |
| 1206 | */ | 1187 | */ |
| 1207 | sctp_check_transmitted(q, &q->retransmit, NULL, sack, highest_new_tsn); | 1188 | sctp_check_transmitted(q, &q->retransmit, NULL, sack, &highest_new_tsn); |
| 1208 | 1189 | ||
| 1209 | /* Run through the transmitted queue. | 1190 | /* Run through the transmitted queue. |
| 1210 | * Credit bytes received and free those chunks which we can. | 1191 | * Credit bytes received and free those chunks which we can. |
| @@ -1213,7 +1194,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
| 1213 | */ | 1194 | */ |
| 1214 | list_for_each_entry(transport, transport_list, transports) { | 1195 | list_for_each_entry(transport, transport_list, transports) { |
| 1215 | sctp_check_transmitted(q, &transport->transmitted, | 1196 | sctp_check_transmitted(q, &transport->transmitted, |
| 1216 | transport, sack, highest_new_tsn); | 1197 | transport, sack, &highest_new_tsn); |
| 1217 | /* | 1198 | /* |
| 1218 | * SFR-CACC algorithm: | 1199 | * SFR-CACC algorithm: |
| 1219 | * C) Let count_of_newacks be the number of | 1200 | * C) Let count_of_newacks be the number of |
| @@ -1223,16 +1204,22 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
| 1223 | count_of_newacks ++; | 1204 | count_of_newacks ++; |
| 1224 | } | 1205 | } |
| 1225 | 1206 | ||
| 1207 | /* Move the Cumulative TSN Ack Point if appropriate. */ | ||
| 1208 | if (TSN_lt(asoc->ctsn_ack_point, sack_ctsn)) { | ||
| 1209 | asoc->ctsn_ack_point = sack_ctsn; | ||
| 1210 | accum_moved = 1; | ||
| 1211 | } | ||
| 1212 | |||
| 1226 | if (gap_ack_blocks) { | 1213 | if (gap_ack_blocks) { |
| 1214 | |||
| 1215 | if (asoc->fast_recovery && accum_moved) | ||
| 1216 | highest_new_tsn = highest_tsn; | ||
| 1217 | |||
| 1227 | list_for_each_entry(transport, transport_list, transports) | 1218 | list_for_each_entry(transport, transport_list, transports) |
| 1228 | sctp_mark_missing(q, &transport->transmitted, transport, | 1219 | sctp_mark_missing(q, &transport->transmitted, transport, |
| 1229 | highest_new_tsn, count_of_newacks); | 1220 | highest_new_tsn, count_of_newacks); |
| 1230 | } | 1221 | } |
| 1231 | 1222 | ||
| 1232 | /* Move the Cumulative TSN Ack Point if appropriate. */ | ||
| 1233 | if (TSN_lt(asoc->ctsn_ack_point, sack_ctsn)) | ||
| 1234 | asoc->ctsn_ack_point = sack_ctsn; | ||
| 1235 | |||
| 1236 | /* Update unack_data field in the assoc. */ | 1223 | /* Update unack_data field in the assoc. */ |
| 1237 | sctp_sack_update_unack_data(asoc, sack); | 1224 | sctp_sack_update_unack_data(asoc, sack); |
| 1238 | 1225 | ||
| @@ -1315,7 +1302,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
| 1315 | struct list_head *transmitted_queue, | 1302 | struct list_head *transmitted_queue, |
| 1316 | struct sctp_transport *transport, | 1303 | struct sctp_transport *transport, |
| 1317 | struct sctp_sackhdr *sack, | 1304 | struct sctp_sackhdr *sack, |
| 1318 | __u32 highest_new_tsn_in_sack) | 1305 | __u32 *highest_new_tsn_in_sack) |
| 1319 | { | 1306 | { |
| 1320 | struct list_head *lchunk; | 1307 | struct list_head *lchunk; |
| 1321 | struct sctp_chunk *tchunk; | 1308 | struct sctp_chunk *tchunk; |
| @@ -1387,7 +1374,6 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
| 1387 | * instance). | 1374 | * instance). |
| 1388 | */ | 1375 | */ |
| 1389 | if (!tchunk->tsn_gap_acked && | 1376 | if (!tchunk->tsn_gap_acked && |
| 1390 | !tchunk->resent && | ||
| 1391 | tchunk->rtt_in_progress) { | 1377 | tchunk->rtt_in_progress) { |
| 1392 | tchunk->rtt_in_progress = 0; | 1378 | tchunk->rtt_in_progress = 0; |
| 1393 | rtt = jiffies - tchunk->sent_at; | 1379 | rtt = jiffies - tchunk->sent_at; |
| @@ -1404,6 +1390,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
| 1404 | */ | 1390 | */ |
| 1405 | if (!tchunk->tsn_gap_acked) { | 1391 | if (!tchunk->tsn_gap_acked) { |
| 1406 | tchunk->tsn_gap_acked = 1; | 1392 | tchunk->tsn_gap_acked = 1; |
| 1393 | *highest_new_tsn_in_sack = tsn; | ||
| 1407 | bytes_acked += sctp_data_size(tchunk); | 1394 | bytes_acked += sctp_data_size(tchunk); |
| 1408 | if (!tchunk->transport) | 1395 | if (!tchunk->transport) |
| 1409 | migrate_bytes += sctp_data_size(tchunk); | 1396 | migrate_bytes += sctp_data_size(tchunk); |
| @@ -1677,7 +1664,8 @@ static void sctp_mark_missing(struct sctp_outq *q, | |||
| 1677 | struct sctp_chunk *chunk; | 1664 | struct sctp_chunk *chunk; |
| 1678 | __u32 tsn; | 1665 | __u32 tsn; |
| 1679 | char do_fast_retransmit = 0; | 1666 | char do_fast_retransmit = 0; |
| 1680 | struct sctp_transport *primary = q->asoc->peer.primary_path; | 1667 | struct sctp_association *asoc = q->asoc; |
| 1668 | struct sctp_transport *primary = asoc->peer.primary_path; | ||
| 1681 | 1669 | ||
| 1682 | list_for_each_entry(chunk, transmitted_queue, transmitted_list) { | 1670 | list_for_each_entry(chunk, transmitted_queue, transmitted_list) { |
| 1683 | 1671 | ||
diff --git a/net/sctp/probe.c b/net/sctp/probe.c new file mode 100644 index 000000000000..db3a42b8b349 --- /dev/null +++ b/net/sctp/probe.c | |||
| @@ -0,0 +1,214 @@ | |||
| 1 | /* | ||
| 2 | * sctp_probe - Observe the SCTP flow with kprobes. | ||
| 3 | * | ||
| 4 | * The idea for this came from Werner Almesberger's umlsim | ||
| 5 | * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org> | ||
| 6 | * | ||
| 7 | * Modified for SCTP from Stephen Hemminger's code | ||
| 8 | * Copyright (C) 2010, Wei Yongjun <yjwei@cn.fujitsu.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <linux/kernel.h> | ||
| 26 | #include <linux/kprobes.h> | ||
| 27 | #include <linux/socket.h> | ||
| 28 | #include <linux/sctp.h> | ||
| 29 | #include <linux/proc_fs.h> | ||
| 30 | #include <linux/vmalloc.h> | ||
| 31 | #include <linux/module.h> | ||
| 32 | #include <linux/kfifo.h> | ||
| 33 | #include <linux/time.h> | ||
| 34 | #include <net/net_namespace.h> | ||
| 35 | |||
| 36 | #include <net/sctp/sctp.h> | ||
| 37 | #include <net/sctp/sm.h> | ||
| 38 | |||
| 39 | MODULE_AUTHOR("Wei Yongjun <yjwei@cn.fujitsu.com>"); | ||
| 40 | MODULE_DESCRIPTION("SCTP snooper"); | ||
| 41 | MODULE_LICENSE("GPL"); | ||
| 42 | |||
| 43 | static int port __read_mostly = 0; | ||
| 44 | MODULE_PARM_DESC(port, "Port to match (0=all)"); | ||
| 45 | module_param(port, int, 0); | ||
| 46 | |||
| 47 | static int bufsize __read_mostly = 64 * 1024; | ||
| 48 | MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)"); | ||
| 49 | module_param(bufsize, int, 0); | ||
| 50 | |||
| 51 | static int full __read_mostly = 1; | ||
| 52 | MODULE_PARM_DESC(full, "Full log (1=every ack packet received, 0=only cwnd changes)"); | ||
| 53 | module_param(full, int, 0); | ||
| 54 | |||
| 55 | static const char procname[] = "sctpprobe"; | ||
| 56 | |||
| 57 | static struct { | ||
| 58 | struct kfifo fifo; | ||
| 59 | spinlock_t lock; | ||
| 60 | wait_queue_head_t wait; | ||
| 61 | struct timespec tstart; | ||
| 62 | } sctpw; | ||
| 63 | |||
| 64 | static void printl(const char *fmt, ...) | ||
| 65 | { | ||
| 66 | va_list args; | ||
| 67 | int len; | ||
| 68 | char tbuf[256]; | ||
| 69 | |||
| 70 | va_start(args, fmt); | ||
| 71 | len = vscnprintf(tbuf, sizeof(tbuf), fmt, args); | ||
| 72 | va_end(args); | ||
| 73 | |||
| 74 | kfifo_in_locked(&sctpw.fifo, tbuf, len, &sctpw.lock); | ||
| 75 | wake_up(&sctpw.wait); | ||
| 76 | } | ||
| 77 | |||
| 78 | static int sctpprobe_open(struct inode *inode, struct file *file) | ||
| 79 | { | ||
| 80 | kfifo_reset(&sctpw.fifo); | ||
| 81 | getnstimeofday(&sctpw.tstart); | ||
| 82 | |||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | static ssize_t sctpprobe_read(struct file *file, char __user *buf, | ||
| 87 | size_t len, loff_t *ppos) | ||
| 88 | { | ||
| 89 | int error = 0, cnt = 0; | ||
| 90 | unsigned char *tbuf; | ||
| 91 | |||
| 92 | if (!buf) | ||
| 93 | return -EINVAL; | ||
| 94 | |||
| 95 | if (len == 0) | ||
| 96 | return 0; | ||
| 97 | |||
| 98 | tbuf = vmalloc(len); | ||
| 99 | if (!tbuf) | ||
| 100 | return -ENOMEM; | ||
| 101 | |||
| 102 | error = wait_event_interruptible(sctpw.wait, | ||
| 103 | kfifo_len(&sctpw.fifo) != 0); | ||
| 104 | if (error) | ||
| 105 | goto out_free; | ||
| 106 | |||
| 107 | cnt = kfifo_out_locked(&sctpw.fifo, tbuf, len, &sctpw.lock); | ||
| 108 | error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0; | ||
| 109 | |||
| 110 | out_free: | ||
| 111 | vfree(tbuf); | ||
| 112 | |||
| 113 | return error ? error : cnt; | ||
| 114 | } | ||
| 115 | |||
| 116 | static const struct file_operations sctpprobe_fops = { | ||
| 117 | .owner = THIS_MODULE, | ||
| 118 | .open = sctpprobe_open, | ||
| 119 | .read = sctpprobe_read, | ||
| 120 | }; | ||
| 121 | |||
| 122 | sctp_disposition_t jsctp_sf_eat_sack(const struct sctp_endpoint *ep, | ||
| 123 | const struct sctp_association *asoc, | ||
| 124 | const sctp_subtype_t type, | ||
| 125 | void *arg, | ||
| 126 | sctp_cmd_seq_t *commands) | ||
| 127 | { | ||
| 128 | struct sctp_transport *sp; | ||
| 129 | static __u32 lcwnd = 0; | ||
| 130 | struct timespec now; | ||
| 131 | |||
| 132 | sp = asoc->peer.primary_path; | ||
| 133 | |||
| 134 | if ((full || sp->cwnd != lcwnd) && | ||
| 135 | (!port || asoc->peer.port == port || | ||
| 136 | ep->base.bind_addr.port == port)) { | ||
| 137 | lcwnd = sp->cwnd; | ||
| 138 | |||
| 139 | getnstimeofday(&now); | ||
| 140 | now = timespec_sub(now, sctpw.tstart); | ||
| 141 | |||
| 142 | printl("%lu.%06lu ", (unsigned long) now.tv_sec, | ||
| 143 | (unsigned long) now.tv_nsec / NSEC_PER_USEC); | ||
| 144 | |||
| 145 | printl("%p %5d %5d %5d %8d %5d ", asoc, | ||
| 146 | ep->base.bind_addr.port, asoc->peer.port, | ||
| 147 | asoc->pathmtu, asoc->peer.rwnd, asoc->unack_data); | ||
| 148 | |||
| 149 | list_for_each_entry(sp, &asoc->peer.transport_addr_list, | ||
| 150 | transports) { | ||
| 151 | if (sp == asoc->peer.primary_path) | ||
| 152 | printl("*"); | ||
| 153 | |||
| 154 | if (sp->ipaddr.sa.sa_family == AF_INET) | ||
| 155 | printl("%pI4 ", &sp->ipaddr.v4.sin_addr); | ||
| 156 | else | ||
| 157 | printl("%pI6 ", &sp->ipaddr.v6.sin6_addr); | ||
| 158 | |||
| 159 | printl("%2u %8u %8u %8u %8u %8u ", | ||
| 160 | sp->state, sp->cwnd, sp->ssthresh, | ||
| 161 | sp->flight_size, sp->partial_bytes_acked, | ||
| 162 | sp->pathmtu); | ||
| 163 | } | ||
| 164 | printl("\n"); | ||
| 165 | } | ||
| 166 | |||
| 167 | jprobe_return(); | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | static struct jprobe sctp_recv_probe = { | ||
| 172 | .kp = { | ||
| 173 | .symbol_name = "sctp_sf_eat_sack_6_2", | ||
| 174 | }, | ||
| 175 | .entry = jsctp_sf_eat_sack, | ||
| 176 | }; | ||
| 177 | |||
| 178 | static __init int sctpprobe_init(void) | ||
| 179 | { | ||
| 180 | int ret = -ENOMEM; | ||
| 181 | |||
| 182 | init_waitqueue_head(&sctpw.wait); | ||
| 183 | spin_lock_init(&sctpw.lock); | ||
| 184 | if (kfifo_alloc(&sctpw.fifo, bufsize, GFP_KERNEL)) | ||
| 185 | return ret; | ||
| 186 | |||
| 187 | if (!proc_net_fops_create(&init_net, procname, S_IRUSR, | ||
| 188 | &sctpprobe_fops)) | ||
| 189 | goto free_kfifo; | ||
| 190 | |||
| 191 | ret = register_jprobe(&sctp_recv_probe); | ||
| 192 | if (ret) | ||
| 193 | goto remove_proc; | ||
| 194 | |||
| 195 | pr_info("SCTP probe registered (port=%d)\n", port); | ||
| 196 | |||
| 197 | return 0; | ||
| 198 | |||
| 199 | remove_proc: | ||
| 200 | proc_net_remove(&init_net, procname); | ||
| 201 | free_kfifo: | ||
| 202 | kfifo_free(&sctpw.fifo); | ||
| 203 | return ret; | ||
| 204 | } | ||
| 205 | |||
| 206 | static __exit void sctpprobe_exit(void) | ||
| 207 | { | ||
| 208 | kfifo_free(&sctpw.fifo); | ||
| 209 | proc_net_remove(&init_net, procname); | ||
| 210 | unregister_jprobe(&sctp_recv_probe); | ||
| 211 | } | ||
| 212 | |||
| 213 | module_init(sctpprobe_init); | ||
| 214 | module_exit(sctpprobe_exit); | ||
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 704298f4b284..182749867c72 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
| @@ -474,13 +474,17 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
| 474 | 474 | ||
| 475 | memset(&fl, 0x0, sizeof(struct flowi)); | 475 | memset(&fl, 0x0, sizeof(struct flowi)); |
| 476 | fl.fl4_dst = daddr->v4.sin_addr.s_addr; | 476 | fl.fl4_dst = daddr->v4.sin_addr.s_addr; |
| 477 | fl.fl_ip_dport = daddr->v4.sin_port; | ||
| 477 | fl.proto = IPPROTO_SCTP; | 478 | fl.proto = IPPROTO_SCTP; |
| 478 | if (asoc) { | 479 | if (asoc) { |
| 479 | fl.fl4_tos = RT_CONN_FLAGS(asoc->base.sk); | 480 | fl.fl4_tos = RT_CONN_FLAGS(asoc->base.sk); |
| 480 | fl.oif = asoc->base.sk->sk_bound_dev_if; | 481 | fl.oif = asoc->base.sk->sk_bound_dev_if; |
| 482 | fl.fl_ip_sport = htons(asoc->base.bind_addr.port); | ||
| 481 | } | 483 | } |
| 482 | if (saddr) | 484 | if (saddr) { |
| 483 | fl.fl4_src = saddr->v4.sin_addr.s_addr; | 485 | fl.fl4_src = saddr->v4.sin_addr.s_addr; |
| 486 | fl.fl_ip_sport = saddr->v4.sin_port; | ||
| 487 | } | ||
| 484 | 488 | ||
| 485 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", | 489 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", |
| 486 | __func__, &fl.fl4_dst, &fl.fl4_src); | 490 | __func__, &fl.fl4_dst, &fl.fl4_src); |
| @@ -528,6 +532,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
| 528 | if ((laddr->state == SCTP_ADDR_SRC) && | 532 | if ((laddr->state == SCTP_ADDR_SRC) && |
| 529 | (AF_INET == laddr->a.sa.sa_family)) { | 533 | (AF_INET == laddr->a.sa.sa_family)) { |
| 530 | fl.fl4_src = laddr->a.v4.sin_addr.s_addr; | 534 | fl.fl4_src = laddr->a.v4.sin_addr.s_addr; |
| 535 | fl.fl_ip_sport = laddr->a.v4.sin_port; | ||
| 531 | if (!ip_route_output_key(&init_net, &rt, &fl)) { | 536 | if (!ip_route_output_key(&init_net, &rt, &fl)) { |
| 532 | dst = &rt->u.dst; | 537 | dst = &rt->u.dst; |
| 533 | goto out_unlock; | 538 | goto out_unlock; |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 17cb400ecd6a..d8261f3d7715 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -108,7 +108,7 @@ static const struct sctp_paramhdr prsctp_param = { | |||
| 108 | cpu_to_be16(sizeof(struct sctp_paramhdr)), | 108 | cpu_to_be16(sizeof(struct sctp_paramhdr)), |
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| 111 | /* A helper to initialize to initialize an op error inside a | 111 | /* A helper to initialize an op error inside a |
| 112 | * provided chunk, as most cause codes will be embedded inside an | 112 | * provided chunk, as most cause codes will be embedded inside an |
| 113 | * abort chunk. | 113 | * abort chunk. |
| 114 | */ | 114 | */ |
| @@ -125,6 +125,29 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, | |||
| 125 | chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err); | 125 | chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | /* A helper to initialize an op error inside a | ||
| 129 | * provided chunk, as most cause codes will be embedded inside an | ||
| 130 | * abort chunk. Differs from sctp_init_cause in that it won't oops | ||
| 131 | * if there isn't enough space in the op error chunk | ||
| 132 | */ | ||
| 133 | int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code, | ||
| 134 | size_t paylen) | ||
| 135 | { | ||
| 136 | sctp_errhdr_t err; | ||
| 137 | __u16 len; | ||
| 138 | |||
| 139 | /* Cause code constants are now defined in network order. */ | ||
| 140 | err.cause = cause_code; | ||
| 141 | len = sizeof(sctp_errhdr_t) + paylen; | ||
| 142 | err.length = htons(len); | ||
| 143 | |||
| 144 | if (skb_tailroom(chunk->skb) > len) | ||
| 145 | return -ENOSPC; | ||
| 146 | chunk->subh.err_hdr = sctp_addto_chunk_fixed(chunk, | ||
| 147 | sizeof(sctp_errhdr_t), | ||
| 148 | &err); | ||
| 149 | return 0; | ||
| 150 | } | ||
| 128 | /* 3.3.2 Initiation (INIT) (1) | 151 | /* 3.3.2 Initiation (INIT) (1) |
| 129 | * | 152 | * |
| 130 | * This chunk is used to initiate a SCTP association between two | 153 | * This chunk is used to initiate a SCTP association between two |
| @@ -208,7 +231,8 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
| 208 | sp = sctp_sk(asoc->base.sk); | 231 | sp = sctp_sk(asoc->base.sk); |
| 209 | num_types = sp->pf->supported_addrs(sp, types); | 232 | num_types = sp->pf->supported_addrs(sp, types); |
| 210 | 233 | ||
| 211 | chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN(num_types); | 234 | chunksize = sizeof(init) + addrs_len; |
| 235 | chunksize += WORD_ROUND(SCTP_SAT_LEN(num_types)); | ||
| 212 | chunksize += sizeof(ecap_param); | 236 | chunksize += sizeof(ecap_param); |
| 213 | 237 | ||
| 214 | if (sctp_prsctp_enable) | 238 | if (sctp_prsctp_enable) |
| @@ -238,14 +262,14 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
| 238 | /* Add HMACS parameter length if any were defined */ | 262 | /* Add HMACS parameter length if any were defined */ |
| 239 | auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs; | 263 | auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs; |
| 240 | if (auth_hmacs->length) | 264 | if (auth_hmacs->length) |
| 241 | chunksize += ntohs(auth_hmacs->length); | 265 | chunksize += WORD_ROUND(ntohs(auth_hmacs->length)); |
| 242 | else | 266 | else |
| 243 | auth_hmacs = NULL; | 267 | auth_hmacs = NULL; |
| 244 | 268 | ||
| 245 | /* Add CHUNKS parameter length */ | 269 | /* Add CHUNKS parameter length */ |
| 246 | auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks; | 270 | auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks; |
| 247 | if (auth_chunks->length) | 271 | if (auth_chunks->length) |
| 248 | chunksize += ntohs(auth_chunks->length); | 272 | chunksize += WORD_ROUND(ntohs(auth_chunks->length)); |
| 249 | else | 273 | else |
| 250 | auth_chunks = NULL; | 274 | auth_chunks = NULL; |
| 251 | 275 | ||
| @@ -255,7 +279,8 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
| 255 | 279 | ||
| 256 | /* If we have any extensions to report, account for that */ | 280 | /* If we have any extensions to report, account for that */ |
| 257 | if (num_ext) | 281 | if (num_ext) |
| 258 | chunksize += sizeof(sctp_supported_ext_param_t) + num_ext; | 282 | chunksize += WORD_ROUND(sizeof(sctp_supported_ext_param_t) + |
| 283 | num_ext); | ||
| 259 | 284 | ||
| 260 | /* RFC 2960 3.3.2 Initiation (INIT) (1) | 285 | /* RFC 2960 3.3.2 Initiation (INIT) (1) |
| 261 | * | 286 | * |
| @@ -397,13 +422,13 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
| 397 | 422 | ||
| 398 | auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs; | 423 | auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs; |
| 399 | if (auth_hmacs->length) | 424 | if (auth_hmacs->length) |
| 400 | chunksize += ntohs(auth_hmacs->length); | 425 | chunksize += WORD_ROUND(ntohs(auth_hmacs->length)); |
| 401 | else | 426 | else |
| 402 | auth_hmacs = NULL; | 427 | auth_hmacs = NULL; |
| 403 | 428 | ||
| 404 | auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks; | 429 | auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks; |
| 405 | if (auth_chunks->length) | 430 | if (auth_chunks->length) |
| 406 | chunksize += ntohs(auth_chunks->length); | 431 | chunksize += WORD_ROUND(ntohs(auth_chunks->length)); |
| 407 | else | 432 | else |
| 408 | auth_chunks = NULL; | 433 | auth_chunks = NULL; |
| 409 | 434 | ||
| @@ -412,17 +437,25 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
| 412 | } | 437 | } |
| 413 | 438 | ||
| 414 | if (num_ext) | 439 | if (num_ext) |
| 415 | chunksize += sizeof(sctp_supported_ext_param_t) + num_ext; | 440 | chunksize += WORD_ROUND(sizeof(sctp_supported_ext_param_t) + |
| 441 | num_ext); | ||
| 416 | 442 | ||
| 417 | /* Now allocate and fill out the chunk. */ | 443 | /* Now allocate and fill out the chunk. */ |
| 418 | retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize); | 444 | retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize); |
| 419 | if (!retval) | 445 | if (!retval) |
| 420 | goto nomem_chunk; | 446 | goto nomem_chunk; |
| 421 | 447 | ||
| 422 | /* Per the advice in RFC 2960 6.4, send this reply to | 448 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints |
| 423 | * the source of the INIT packet. | 449 | * |
| 450 | * An endpoint SHOULD transmit reply chunks (e.g., SACK, | ||
| 451 | * HEARTBEAT ACK, * etc.) to the same destination transport | ||
| 452 | * address from which it received the DATA or control chunk | ||
| 453 | * to which it is replying. | ||
| 454 | * | ||
| 455 | * [INIT ACK back to where the INIT came from.] | ||
| 424 | */ | 456 | */ |
| 425 | retval->transport = chunk->transport; | 457 | retval->transport = chunk->transport; |
| 458 | |||
| 426 | retval->subh.init_hdr = | 459 | retval->subh.init_hdr = |
| 427 | sctp_addto_chunk(retval, sizeof(initack), &initack); | 460 | sctp_addto_chunk(retval, sizeof(initack), &initack); |
| 428 | retval->param_hdr.v = sctp_addto_chunk(retval, addrs_len, addrs.v); | 461 | retval->param_hdr.v = sctp_addto_chunk(retval, addrs_len, addrs.v); |
| @@ -461,18 +494,6 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
| 461 | /* We need to remove the const qualifier at this point. */ | 494 | /* We need to remove the const qualifier at this point. */ |
| 462 | retval->asoc = (struct sctp_association *) asoc; | 495 | retval->asoc = (struct sctp_association *) asoc; |
| 463 | 496 | ||
| 464 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints | ||
| 465 | * | ||
| 466 | * An endpoint SHOULD transmit reply chunks (e.g., SACK, | ||
| 467 | * HEARTBEAT ACK, * etc.) to the same destination transport | ||
| 468 | * address from which it received the DATA or control chunk | ||
| 469 | * to which it is replying. | ||
| 470 | * | ||
| 471 | * [INIT ACK back to where the INIT came from.] | ||
| 472 | */ | ||
| 473 | if (chunk) | ||
| 474 | retval->transport = chunk->transport; | ||
| 475 | |||
| 476 | nomem_chunk: | 497 | nomem_chunk: |
| 477 | kfree(cookie); | 498 | kfree(cookie); |
| 478 | nomem_cookie: | 499 | nomem_cookie: |
| @@ -1129,6 +1150,24 @@ nodata: | |||
| 1129 | return retval; | 1150 | return retval; |
| 1130 | } | 1151 | } |
| 1131 | 1152 | ||
| 1153 | /* Create an Operation Error chunk of a fixed size, | ||
| 1154 | * specifically, max(asoc->pathmtu, SCTP_DEFAULT_MAXSEGMENT) | ||
| 1155 | * This is a helper function to allocate an error chunk for | ||
| 1156 | * for those invalid parameter codes in which we may not want | ||
| 1157 | * to report all the errors, if the incomming chunk is large | ||
| 1158 | */ | ||
| 1159 | static inline struct sctp_chunk *sctp_make_op_error_fixed( | ||
| 1160 | const struct sctp_association *asoc, | ||
| 1161 | const struct sctp_chunk *chunk) | ||
| 1162 | { | ||
| 1163 | size_t size = asoc ? asoc->pathmtu : 0; | ||
| 1164 | |||
| 1165 | if (!size) | ||
| 1166 | size = SCTP_DEFAULT_MAXSEGMENT; | ||
| 1167 | |||
| 1168 | return sctp_make_op_error_space(asoc, chunk, size); | ||
| 1169 | } | ||
| 1170 | |||
| 1132 | /* Create an Operation Error chunk. */ | 1171 | /* Create an Operation Error chunk. */ |
| 1133 | struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, | 1172 | struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, |
| 1134 | const struct sctp_chunk *chunk, | 1173 | const struct sctp_chunk *chunk, |
| @@ -1210,7 +1249,6 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb, | |||
| 1210 | INIT_LIST_HEAD(&retval->list); | 1249 | INIT_LIST_HEAD(&retval->list); |
| 1211 | retval->skb = skb; | 1250 | retval->skb = skb; |
| 1212 | retval->asoc = (struct sctp_association *)asoc; | 1251 | retval->asoc = (struct sctp_association *)asoc; |
| 1213 | retval->resent = 0; | ||
| 1214 | retval->has_tsn = 0; | 1252 | retval->has_tsn = 0; |
| 1215 | retval->has_ssn = 0; | 1253 | retval->has_ssn = 0; |
| 1216 | retval->rtt_in_progress = 0; | 1254 | retval->rtt_in_progress = 0; |
| @@ -1371,6 +1409,18 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data) | |||
| 1371 | return target; | 1409 | return target; |
| 1372 | } | 1410 | } |
| 1373 | 1411 | ||
| 1412 | /* Append bytes to the end of a chunk. Returns NULL if there isn't sufficient | ||
| 1413 | * space in the chunk | ||
| 1414 | */ | ||
| 1415 | void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk, | ||
| 1416 | int len, const void *data) | ||
| 1417 | { | ||
| 1418 | if (skb_tailroom(chunk->skb) > len) | ||
| 1419 | return sctp_addto_chunk(chunk, len, data); | ||
| 1420 | else | ||
| 1421 | return NULL; | ||
| 1422 | } | ||
| 1423 | |||
| 1374 | /* Append bytes from user space to the end of a chunk. Will panic if | 1424 | /* Append bytes from user space to the end of a chunk. Will panic if |
| 1375 | * chunk is not big enough. | 1425 | * chunk is not big enough. |
| 1376 | * Returns a kernel err value. | 1426 | * Returns a kernel err value. |
| @@ -1974,13 +2024,12 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc, | |||
| 1974 | * returning multiple unknown parameters. | 2024 | * returning multiple unknown parameters. |
| 1975 | */ | 2025 | */ |
| 1976 | if (NULL == *errp) | 2026 | if (NULL == *errp) |
| 1977 | *errp = sctp_make_op_error_space(asoc, chunk, | 2027 | *errp = sctp_make_op_error_fixed(asoc, chunk); |
| 1978 | ntohs(chunk->chunk_hdr->length)); | ||
| 1979 | 2028 | ||
| 1980 | if (*errp) { | 2029 | if (*errp) { |
| 1981 | sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, | 2030 | sctp_init_cause_fixed(*errp, SCTP_ERROR_UNKNOWN_PARAM, |
| 1982 | WORD_ROUND(ntohs(param.p->length))); | 2031 | WORD_ROUND(ntohs(param.p->length))); |
| 1983 | sctp_addto_chunk(*errp, | 2032 | sctp_addto_chunk_fixed(*errp, |
| 1984 | WORD_ROUND(ntohs(param.p->length)), | 2033 | WORD_ROUND(ntohs(param.p->length)), |
| 1985 | param.v); | 2034 | param.v); |
| 1986 | } else { | 2035 | } else { |
| @@ -3315,21 +3364,6 @@ int sctp_process_asconf_ack(struct sctp_association *asoc, | |||
| 3315 | sctp_chunk_free(asconf); | 3364 | sctp_chunk_free(asconf); |
| 3316 | asoc->addip_last_asconf = NULL; | 3365 | asoc->addip_last_asconf = NULL; |
| 3317 | 3366 | ||
| 3318 | /* Send the next asconf chunk from the addip chunk queue. */ | ||
| 3319 | if (!list_empty(&asoc->addip_chunk_list)) { | ||
| 3320 | struct list_head *entry = asoc->addip_chunk_list.next; | ||
| 3321 | asconf = list_entry(entry, struct sctp_chunk, list); | ||
| 3322 | |||
| 3323 | list_del_init(entry); | ||
| 3324 | |||
| 3325 | /* Hold the chunk until an ASCONF_ACK is received. */ | ||
| 3326 | sctp_chunk_hold(asconf); | ||
| 3327 | if (sctp_primitive_ASCONF(asoc, asconf)) | ||
| 3328 | sctp_chunk_free(asconf); | ||
| 3329 | else | ||
| 3330 | asoc->addip_last_asconf = asconf; | ||
| 3331 | } | ||
| 3332 | |||
| 3333 | return retval; | 3367 | return retval; |
| 3334 | } | 3368 | } |
| 3335 | 3369 | ||
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 4c5bed9af4e3..3b7230ef77c2 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
| @@ -697,11 +697,15 @@ static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds, | |||
| 697 | { | 697 | { |
| 698 | struct sctp_transport *t; | 698 | struct sctp_transport *t; |
| 699 | 699 | ||
| 700 | t = sctp_assoc_choose_alter_transport(asoc, | 700 | if (chunk->transport) |
| 701 | t = chunk->transport; | ||
| 702 | else { | ||
| 703 | t = sctp_assoc_choose_alter_transport(asoc, | ||
| 701 | asoc->shutdown_last_sent_to); | 704 | asoc->shutdown_last_sent_to); |
| 705 | chunk->transport = t; | ||
| 706 | } | ||
| 702 | asoc->shutdown_last_sent_to = t; | 707 | asoc->shutdown_last_sent_to = t; |
| 703 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; | 708 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; |
| 704 | chunk->transport = t; | ||
| 705 | } | 709 | } |
| 706 | 710 | ||
| 707 | /* Helper function to change the state of an association. */ | 711 | /* Helper function to change the state of an association. */ |
| @@ -962,6 +966,29 @@ static int sctp_cmd_send_msg(struct sctp_association *asoc, | |||
| 962 | } | 966 | } |
| 963 | 967 | ||
| 964 | 968 | ||
| 969 | /* Sent the next ASCONF packet currently stored in the association. | ||
| 970 | * This happens after the ASCONF_ACK was succeffully processed. | ||
| 971 | */ | ||
| 972 | static void sctp_cmd_send_asconf(struct sctp_association *asoc) | ||
| 973 | { | ||
| 974 | /* Send the next asconf chunk from the addip chunk | ||
| 975 | * queue. | ||
| 976 | */ | ||
| 977 | if (!list_empty(&asoc->addip_chunk_list)) { | ||
| 978 | struct list_head *entry = asoc->addip_chunk_list.next; | ||
| 979 | struct sctp_chunk *asconf = list_entry(entry, | ||
| 980 | struct sctp_chunk, list); | ||
| 981 | list_del_init(entry); | ||
| 982 | |||
| 983 | /* Hold the chunk until an ASCONF_ACK is received. */ | ||
| 984 | sctp_chunk_hold(asconf); | ||
| 985 | if (sctp_primitive_ASCONF(asoc, asconf)) | ||
| 986 | sctp_chunk_free(asconf); | ||
| 987 | else | ||
| 988 | asoc->addip_last_asconf = asconf; | ||
| 989 | } | ||
| 990 | } | ||
| 991 | |||
| 965 | 992 | ||
| 966 | /* These three macros allow us to pull the debugging code out of the | 993 | /* These three macros allow us to pull the debugging code out of the |
| 967 | * main flow of sctp_do_sm() to keep attention focused on the real | 994 | * main flow of sctp_do_sm() to keep attention focused on the real |
| @@ -1617,6 +1644,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1617 | } | 1644 | } |
| 1618 | error = sctp_cmd_send_msg(asoc, cmd->obj.msg); | 1645 | error = sctp_cmd_send_msg(asoc, cmd->obj.msg); |
| 1619 | break; | 1646 | break; |
| 1647 | case SCTP_CMD_SEND_NEXT_ASCONF: | ||
| 1648 | sctp_cmd_send_asconf(asoc); | ||
| 1649 | break; | ||
| 1620 | default: | 1650 | default: |
| 1621 | printk(KERN_WARNING "Impossible command: %u, %p\n", | 1651 | printk(KERN_WARNING "Impossible command: %u, %p\n", |
| 1622 | cmd->verb, cmd->obj.ptr); | 1652 | cmd->verb, cmd->obj.ptr); |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index abf601a1b847..24b2cd555637 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -3676,8 +3676,14 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
| 3676 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); | 3676 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); |
| 3677 | 3677 | ||
| 3678 | if (!sctp_process_asconf_ack((struct sctp_association *)asoc, | 3678 | if (!sctp_process_asconf_ack((struct sctp_association *)asoc, |
| 3679 | asconf_ack)) | 3679 | asconf_ack)) { |
| 3680 | /* Successfully processed ASCONF_ACK. We can | ||
| 3681 | * release the next asconf if we have one. | ||
| 3682 | */ | ||
| 3683 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_NEXT_ASCONF, | ||
| 3684 | SCTP_NULL()); | ||
| 3680 | return SCTP_DISPOSITION_CONSUME; | 3685 | return SCTP_DISPOSITION_CONSUME; |
| 3686 | } | ||
| 3681 | 3687 | ||
| 3682 | abort = sctp_make_abort(asoc, asconf_ack, | 3688 | abort = sctp_make_abort(asoc, asconf_ack, |
| 3683 | sizeof(sctp_errhdr_t)); | 3689 | sizeof(sctp_errhdr_t)); |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index c1941276f6e3..ba1add0b13c3 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -3719,12 +3719,9 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
| 3719 | sp->hmac = NULL; | 3719 | sp->hmac = NULL; |
| 3720 | 3720 | ||
| 3721 | SCTP_DBG_OBJCNT_INC(sock); | 3721 | SCTP_DBG_OBJCNT_INC(sock); |
| 3722 | percpu_counter_inc(&sctp_sockets_allocated); | ||
| 3723 | |||
| 3724 | /* Set socket backlog limit. */ | ||
| 3725 | sk->sk_backlog.limit = sysctl_sctp_rmem[1]; | ||
| 3726 | 3722 | ||
| 3727 | local_bh_disable(); | 3723 | local_bh_disable(); |
| 3724 | percpu_counter_inc(&sctp_sockets_allocated); | ||
| 3728 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | 3725 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
| 3729 | local_bh_enable(); | 3726 | local_bh_enable(); |
| 3730 | 3727 | ||
| @@ -3741,8 +3738,8 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk) | |||
| 3741 | /* Release our hold on the endpoint. */ | 3738 | /* Release our hold on the endpoint. */ |
| 3742 | ep = sctp_sk(sk)->ep; | 3739 | ep = sctp_sk(sk)->ep; |
| 3743 | sctp_endpoint_free(ep); | 3740 | sctp_endpoint_free(ep); |
| 3744 | percpu_counter_dec(&sctp_sockets_allocated); | ||
| 3745 | local_bh_disable(); | 3741 | local_bh_disable(); |
| 3742 | percpu_counter_dec(&sctp_sockets_allocated); | ||
| 3746 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); | 3743 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); |
| 3747 | local_bh_enable(); | 3744 | local_bh_enable(); |
| 3748 | } | 3745 | } |
| @@ -4387,7 +4384,7 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, | |||
| 4387 | transports) { | 4384 | transports) { |
| 4388 | memcpy(&temp, &from->ipaddr, sizeof(temp)); | 4385 | memcpy(&temp, &from->ipaddr, sizeof(temp)); |
| 4389 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); | 4386 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); |
| 4390 | addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; | 4387 | addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; |
| 4391 | if (space_left < addrlen) | 4388 | if (space_left < addrlen) |
| 4392 | return -ENOMEM; | 4389 | return -ENOMEM; |
| 4393 | if (copy_to_user(to, &temp, addrlen)) | 4390 | if (copy_to_user(to, &temp, addrlen)) |
| @@ -5702,7 +5699,7 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
| 5702 | struct sctp_sock *sp = sctp_sk(sk); | 5699 | struct sctp_sock *sp = sctp_sk(sk); |
| 5703 | unsigned int mask; | 5700 | unsigned int mask; |
| 5704 | 5701 | ||
| 5705 | poll_wait(file, sk->sk_sleep, wait); | 5702 | poll_wait(file, sk_sleep(sk), wait); |
| 5706 | 5703 | ||
| 5707 | /* A TCP-style listening socket becomes readable when the accept queue | 5704 | /* A TCP-style listening socket becomes readable when the accept queue |
| 5708 | * is not empty. | 5705 | * is not empty. |
| @@ -5943,7 +5940,7 @@ static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p) | |||
| 5943 | int error; | 5940 | int error; |
| 5944 | DEFINE_WAIT(wait); | 5941 | DEFINE_WAIT(wait); |
| 5945 | 5942 | ||
| 5946 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 5943 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 5947 | 5944 | ||
| 5948 | /* Socket errors? */ | 5945 | /* Socket errors? */ |
| 5949 | error = sock_error(sk); | 5946 | error = sock_error(sk); |
| @@ -5980,14 +5977,14 @@ static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p) | |||
| 5980 | sctp_lock_sock(sk); | 5977 | sctp_lock_sock(sk); |
| 5981 | 5978 | ||
| 5982 | ready: | 5979 | ready: |
| 5983 | finish_wait(sk->sk_sleep, &wait); | 5980 | finish_wait(sk_sleep(sk), &wait); |
| 5984 | return 0; | 5981 | return 0; |
| 5985 | 5982 | ||
| 5986 | interrupted: | 5983 | interrupted: |
| 5987 | error = sock_intr_errno(*timeo_p); | 5984 | error = sock_intr_errno(*timeo_p); |
| 5988 | 5985 | ||
| 5989 | out: | 5986 | out: |
| 5990 | finish_wait(sk->sk_sleep, &wait); | 5987 | finish_wait(sk_sleep(sk), &wait); |
| 5991 | *err = error; | 5988 | *err = error; |
| 5992 | return error; | 5989 | return error; |
| 5993 | } | 5990 | } |
| @@ -6061,14 +6058,14 @@ static void __sctp_write_space(struct sctp_association *asoc) | |||
| 6061 | wake_up_interruptible(&asoc->wait); | 6058 | wake_up_interruptible(&asoc->wait); |
| 6062 | 6059 | ||
| 6063 | if (sctp_writeable(sk)) { | 6060 | if (sctp_writeable(sk)) { |
| 6064 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 6061 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
| 6065 | wake_up_interruptible(sk->sk_sleep); | 6062 | wake_up_interruptible(sk_sleep(sk)); |
| 6066 | 6063 | ||
| 6067 | /* Note that we try to include the Async I/O support | 6064 | /* Note that we try to include the Async I/O support |
| 6068 | * here by modeling from the current TCP/UDP code. | 6065 | * here by modeling from the current TCP/UDP code. |
| 6069 | * We have not tested with it yet. | 6066 | * We have not tested with it yet. |
| 6070 | */ | 6067 | */ |
| 6071 | if (sock->fasync_list && | 6068 | if (sock->wq->fasync_list && |
| 6072 | !(sk->sk_shutdown & SEND_SHUTDOWN)) | 6069 | !(sk->sk_shutdown & SEND_SHUTDOWN)) |
| 6073 | sock_wake_async(sock, | 6070 | sock_wake_async(sock, |
| 6074 | SOCK_WAKE_SPACE, POLL_OUT); | 6071 | SOCK_WAKE_SPACE, POLL_OUT); |
| @@ -6188,6 +6185,19 @@ do_nonblock: | |||
| 6188 | goto out; | 6185 | goto out; |
| 6189 | } | 6186 | } |
| 6190 | 6187 | ||
| 6188 | void sctp_data_ready(struct sock *sk, int len) | ||
| 6189 | { | ||
| 6190 | struct socket_wq *wq; | ||
| 6191 | |||
| 6192 | rcu_read_lock(); | ||
| 6193 | wq = rcu_dereference(sk->sk_wq); | ||
| 6194 | if (wq_has_sleeper(wq)) | ||
| 6195 | wake_up_interruptible_sync_poll(&wq->wait, POLLIN | | ||
| 6196 | POLLRDNORM | POLLRDBAND); | ||
| 6197 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); | ||
| 6198 | rcu_read_unlock(); | ||
| 6199 | } | ||
| 6200 | |||
| 6191 | /* If socket sndbuf has changed, wake up all per association waiters. */ | 6201 | /* If socket sndbuf has changed, wake up all per association waiters. */ |
| 6192 | void sctp_write_space(struct sock *sk) | 6202 | void sctp_write_space(struct sock *sk) |
| 6193 | { | 6203 | { |
| @@ -6296,7 +6306,7 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo) | |||
| 6296 | 6306 | ||
| 6297 | 6307 | ||
| 6298 | for (;;) { | 6308 | for (;;) { |
| 6299 | prepare_to_wait_exclusive(sk->sk_sleep, &wait, | 6309 | prepare_to_wait_exclusive(sk_sleep(sk), &wait, |
| 6300 | TASK_INTERRUPTIBLE); | 6310 | TASK_INTERRUPTIBLE); |
| 6301 | 6311 | ||
| 6302 | if (list_empty(&ep->asocs)) { | 6312 | if (list_empty(&ep->asocs)) { |
| @@ -6322,7 +6332,7 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo) | |||
| 6322 | break; | 6332 | break; |
| 6323 | } | 6333 | } |
| 6324 | 6334 | ||
| 6325 | finish_wait(sk->sk_sleep, &wait); | 6335 | finish_wait(sk_sleep(sk), &wait); |
| 6326 | 6336 | ||
| 6327 | return err; | 6337 | return err; |
| 6328 | } | 6338 | } |
| @@ -6332,7 +6342,7 @@ static void sctp_wait_for_close(struct sock *sk, long timeout) | |||
| 6332 | DEFINE_WAIT(wait); | 6342 | DEFINE_WAIT(wait); |
| 6333 | 6343 | ||
| 6334 | do { | 6344 | do { |
| 6335 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 6345 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 6336 | if (list_empty(&sctp_sk(sk)->ep->asocs)) | 6346 | if (list_empty(&sctp_sk(sk)->ep->asocs)) |
| 6337 | break; | 6347 | break; |
| 6338 | sctp_release_sock(sk); | 6348 | sctp_release_sock(sk); |
| @@ -6340,7 +6350,7 @@ static void sctp_wait_for_close(struct sock *sk, long timeout) | |||
| 6340 | sctp_lock_sock(sk); | 6350 | sctp_lock_sock(sk); |
| 6341 | } while (!signal_pending(current) && timeout); | 6351 | } while (!signal_pending(current) && timeout); |
| 6342 | 6352 | ||
| 6343 | finish_wait(sk->sk_sleep, &wait); | 6353 | finish_wait(sk_sleep(sk), &wait); |
| 6344 | } | 6354 | } |
| 6345 | 6355 | ||
| 6346 | static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) | 6356 | static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index be4d63d5a5cc..fccf4947aff1 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
| @@ -64,9 +64,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
| 64 | /* Copy in the address. */ | 64 | /* Copy in the address. */ |
| 65 | peer->ipaddr = *addr; | 65 | peer->ipaddr = *addr; |
| 66 | peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); | 66 | peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); |
| 67 | peer->asoc = NULL; | ||
| 68 | |||
| 69 | peer->dst = NULL; | ||
| 70 | memset(&peer->saddr, 0, sizeof(union sctp_addr)); | 67 | memset(&peer->saddr, 0, sizeof(union sctp_addr)); |
| 71 | 68 | ||
| 72 | /* From 6.3.1 RTO Calculation: | 69 | /* From 6.3.1 RTO Calculation: |
| @@ -76,34 +73,21 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
| 76 | * parameter 'RTO.Initial'. | 73 | * parameter 'RTO.Initial'. |
| 77 | */ | 74 | */ |
| 78 | peer->rto = msecs_to_jiffies(sctp_rto_initial); | 75 | peer->rto = msecs_to_jiffies(sctp_rto_initial); |
| 79 | peer->rtt = 0; | ||
| 80 | peer->rttvar = 0; | ||
| 81 | peer->srtt = 0; | ||
| 82 | peer->rto_pending = 0; | ||
| 83 | peer->hb_sent = 0; | ||
| 84 | peer->fast_recovery = 0; | ||
| 85 | 76 | ||
| 86 | peer->last_time_heard = jiffies; | 77 | peer->last_time_heard = jiffies; |
| 87 | peer->last_time_ecne_reduced = jiffies; | 78 | peer->last_time_ecne_reduced = jiffies; |
| 88 | 79 | ||
| 89 | peer->init_sent_count = 0; | ||
| 90 | |||
| 91 | peer->param_flags = SPP_HB_DISABLE | | 80 | peer->param_flags = SPP_HB_DISABLE | |
| 92 | SPP_PMTUD_ENABLE | | 81 | SPP_PMTUD_ENABLE | |
| 93 | SPP_SACKDELAY_ENABLE; | 82 | SPP_SACKDELAY_ENABLE; |
| 94 | peer->hbinterval = 0; | ||
| 95 | 83 | ||
| 96 | /* Initialize the default path max_retrans. */ | 84 | /* Initialize the default path max_retrans. */ |
| 97 | peer->pathmaxrxt = sctp_max_retrans_path; | 85 | peer->pathmaxrxt = sctp_max_retrans_path; |
| 98 | peer->error_count = 0; | ||
| 99 | 86 | ||
| 100 | INIT_LIST_HEAD(&peer->transmitted); | 87 | INIT_LIST_HEAD(&peer->transmitted); |
| 101 | INIT_LIST_HEAD(&peer->send_ready); | 88 | INIT_LIST_HEAD(&peer->send_ready); |
| 102 | INIT_LIST_HEAD(&peer->transports); | 89 | INIT_LIST_HEAD(&peer->transports); |
| 103 | 90 | ||
| 104 | peer->T3_rtx_timer.expires = 0; | ||
| 105 | peer->hb_timer.expires = 0; | ||
| 106 | |||
| 107 | setup_timer(&peer->T3_rtx_timer, sctp_generate_t3_rtx_event, | 91 | setup_timer(&peer->T3_rtx_timer, sctp_generate_t3_rtx_event, |
| 108 | (unsigned long)peer); | 92 | (unsigned long)peer); |
| 109 | setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event, | 93 | setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event, |
| @@ -113,15 +97,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
| 113 | get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce)); | 97 | get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce)); |
| 114 | 98 | ||
| 115 | atomic_set(&peer->refcnt, 1); | 99 | atomic_set(&peer->refcnt, 1); |
| 116 | peer->dead = 0; | ||
| 117 | |||
| 118 | peer->malloced = 0; | ||
| 119 | |||
| 120 | /* Initialize the state information for SFR-CACC */ | ||
| 121 | peer->cacc.changeover_active = 0; | ||
| 122 | peer->cacc.cycling_changeover = 0; | ||
| 123 | peer->cacc.next_tsn_at_change = 0; | ||
| 124 | peer->cacc.cacc_saw_newack = 0; | ||
| 125 | 100 | ||
| 126 | return peer; | 101 | return peer; |
| 127 | } | 102 | } |
| @@ -195,7 +170,7 @@ static void sctp_transport_destroy(struct sctp_transport *transport) | |||
| 195 | /* Start T3_rtx timer if it is not already running and update the heartbeat | 170 | /* Start T3_rtx timer if it is not already running and update the heartbeat |
| 196 | * timer. This routine is called every time a DATA chunk is sent. | 171 | * timer. This routine is called every time a DATA chunk is sent. |
| 197 | */ | 172 | */ |
| 198 | void sctp_transport_reset_timers(struct sctp_transport *transport, int force) | 173 | void sctp_transport_reset_timers(struct sctp_transport *transport) |
| 199 | { | 174 | { |
| 200 | /* RFC 2960 6.3.2 Retransmission Timer Rules | 175 | /* RFC 2960 6.3.2 Retransmission Timer Rules |
| 201 | * | 176 | * |
| @@ -205,7 +180,7 @@ void sctp_transport_reset_timers(struct sctp_transport *transport, int force) | |||
| 205 | * address. | 180 | * address. |
| 206 | */ | 181 | */ |
| 207 | 182 | ||
| 208 | if (force || !timer_pending(&transport->T3_rtx_timer)) | 183 | if (!timer_pending(&transport->T3_rtx_timer)) |
| 209 | if (!mod_timer(&transport->T3_rtx_timer, | 184 | if (!mod_timer(&transport->T3_rtx_timer, |
| 210 | jiffies + transport->rto)) | 185 | jiffies + transport->rto)) |
| 211 | sctp_transport_hold(transport); | 186 | sctp_transport_hold(transport); |
| @@ -403,15 +378,16 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) | |||
| 403 | void sctp_transport_raise_cwnd(struct sctp_transport *transport, | 378 | void sctp_transport_raise_cwnd(struct sctp_transport *transport, |
| 404 | __u32 sack_ctsn, __u32 bytes_acked) | 379 | __u32 sack_ctsn, __u32 bytes_acked) |
| 405 | { | 380 | { |
| 381 | struct sctp_association *asoc = transport->asoc; | ||
| 406 | __u32 cwnd, ssthresh, flight_size, pba, pmtu; | 382 | __u32 cwnd, ssthresh, flight_size, pba, pmtu; |
| 407 | 383 | ||
| 408 | cwnd = transport->cwnd; | 384 | cwnd = transport->cwnd; |
| 409 | flight_size = transport->flight_size; | 385 | flight_size = transport->flight_size; |
| 410 | 386 | ||
| 411 | /* See if we need to exit Fast Recovery first */ | 387 | /* See if we need to exit Fast Recovery first */ |
| 412 | if (transport->fast_recovery && | 388 | if (asoc->fast_recovery && |
| 413 | TSN_lte(transport->fast_recovery_exit, sack_ctsn)) | 389 | TSN_lte(asoc->fast_recovery_exit, sack_ctsn)) |
| 414 | transport->fast_recovery = 0; | 390 | asoc->fast_recovery = 0; |
| 415 | 391 | ||
| 416 | /* The appropriate cwnd increase algorithm is performed if, and only | 392 | /* The appropriate cwnd increase algorithm is performed if, and only |
| 417 | * if the cumulative TSN whould advanced and the congestion window is | 393 | * if the cumulative TSN whould advanced and the congestion window is |
| @@ -440,7 +416,7 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport, | |||
| 440 | * 2) the destination's path MTU. This upper bound protects | 416 | * 2) the destination's path MTU. This upper bound protects |
| 441 | * against the ACK-Splitting attack outlined in [SAVAGE99]. | 417 | * against the ACK-Splitting attack outlined in [SAVAGE99]. |
| 442 | */ | 418 | */ |
| 443 | if (transport->fast_recovery) | 419 | if (asoc->fast_recovery) |
| 444 | return; | 420 | return; |
| 445 | 421 | ||
| 446 | if (bytes_acked > pmtu) | 422 | if (bytes_acked > pmtu) |
| @@ -491,6 +467,8 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport, | |||
| 491 | void sctp_transport_lower_cwnd(struct sctp_transport *transport, | 467 | void sctp_transport_lower_cwnd(struct sctp_transport *transport, |
| 492 | sctp_lower_cwnd_t reason) | 468 | sctp_lower_cwnd_t reason) |
| 493 | { | 469 | { |
| 470 | struct sctp_association *asoc = transport->asoc; | ||
| 471 | |||
| 494 | switch (reason) { | 472 | switch (reason) { |
| 495 | case SCTP_LOWER_CWND_T3_RTX: | 473 | case SCTP_LOWER_CWND_T3_RTX: |
| 496 | /* RFC 2960 Section 7.2.3, sctpimpguide | 474 | /* RFC 2960 Section 7.2.3, sctpimpguide |
| @@ -501,11 +479,11 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
| 501 | * partial_bytes_acked = 0 | 479 | * partial_bytes_acked = 0 |
| 502 | */ | 480 | */ |
| 503 | transport->ssthresh = max(transport->cwnd/2, | 481 | transport->ssthresh = max(transport->cwnd/2, |
| 504 | 4*transport->asoc->pathmtu); | 482 | 4*asoc->pathmtu); |
| 505 | transport->cwnd = transport->asoc->pathmtu; | 483 | transport->cwnd = asoc->pathmtu; |
| 506 | 484 | ||
| 507 | /* T3-rtx also clears fast recovery on the transport */ | 485 | /* T3-rtx also clears fast recovery */ |
| 508 | transport->fast_recovery = 0; | 486 | asoc->fast_recovery = 0; |
| 509 | break; | 487 | break; |
| 510 | 488 | ||
| 511 | case SCTP_LOWER_CWND_FAST_RTX: | 489 | case SCTP_LOWER_CWND_FAST_RTX: |
| @@ -521,15 +499,15 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
| 521 | * cwnd = ssthresh | 499 | * cwnd = ssthresh |
| 522 | * partial_bytes_acked = 0 | 500 | * partial_bytes_acked = 0 |
| 523 | */ | 501 | */ |
| 524 | if (transport->fast_recovery) | 502 | if (asoc->fast_recovery) |
| 525 | return; | 503 | return; |
| 526 | 504 | ||
| 527 | /* Mark Fast recovery */ | 505 | /* Mark Fast recovery */ |
| 528 | transport->fast_recovery = 1; | 506 | asoc->fast_recovery = 1; |
| 529 | transport->fast_recovery_exit = transport->asoc->next_tsn - 1; | 507 | asoc->fast_recovery_exit = asoc->next_tsn - 1; |
| 530 | 508 | ||
| 531 | transport->ssthresh = max(transport->cwnd/2, | 509 | transport->ssthresh = max(transport->cwnd/2, |
| 532 | 4*transport->asoc->pathmtu); | 510 | 4*asoc->pathmtu); |
| 533 | transport->cwnd = transport->ssthresh; | 511 | transport->cwnd = transport->ssthresh; |
| 534 | break; | 512 | break; |
| 535 | 513 | ||
| @@ -549,7 +527,7 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
| 549 | if (time_after(jiffies, transport->last_time_ecne_reduced + | 527 | if (time_after(jiffies, transport->last_time_ecne_reduced + |
| 550 | transport->rtt)) { | 528 | transport->rtt)) { |
| 551 | transport->ssthresh = max(transport->cwnd/2, | 529 | transport->ssthresh = max(transport->cwnd/2, |
| 552 | 4*transport->asoc->pathmtu); | 530 | 4*asoc->pathmtu); |
| 553 | transport->cwnd = transport->ssthresh; | 531 | transport->cwnd = transport->ssthresh; |
| 554 | transport->last_time_ecne_reduced = jiffies; | 532 | transport->last_time_ecne_reduced = jiffies; |
| 555 | } | 533 | } |
| @@ -565,7 +543,7 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
| 565 | * interval. | 543 | * interval. |
| 566 | */ | 544 | */ |
| 567 | transport->cwnd = max(transport->cwnd/2, | 545 | transport->cwnd = max(transport->cwnd/2, |
| 568 | 4*transport->asoc->pathmtu); | 546 | 4*asoc->pathmtu); |
| 569 | break; | 547 | break; |
| 570 | } | 548 | } |
| 571 | 549 | ||
| @@ -650,7 +628,6 @@ void sctp_transport_reset(struct sctp_transport *t) | |||
| 650 | t->error_count = 0; | 628 | t->error_count = 0; |
| 651 | t->rto_pending = 0; | 629 | t->rto_pending = 0; |
| 652 | t->hb_sent = 0; | 630 | t->hb_sent = 0; |
| 653 | t->fast_recovery = 0; | ||
| 654 | 631 | ||
| 655 | /* Initialize the state information for SFR-CACC */ | 632 | /* Initialize the state information for SFR-CACC */ |
| 656 | t->cacc.changeover_active = 0; | 633 | t->cacc.changeover_active = 0; |
diff --git a/net/socket.c b/net/socket.c index 35bc198bbf68..dae8c6b84a09 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -252,9 +252,14 @@ static struct inode *sock_alloc_inode(struct super_block *sb) | |||
| 252 | ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); | 252 | ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL); |
| 253 | if (!ei) | 253 | if (!ei) |
| 254 | return NULL; | 254 | return NULL; |
| 255 | init_waitqueue_head(&ei->socket.wait); | 255 | ei->socket.wq = kmalloc(sizeof(struct socket_wq), GFP_KERNEL); |
| 256 | if (!ei->socket.wq) { | ||
| 257 | kmem_cache_free(sock_inode_cachep, ei); | ||
| 258 | return NULL; | ||
| 259 | } | ||
| 260 | init_waitqueue_head(&ei->socket.wq->wait); | ||
| 261 | ei->socket.wq->fasync_list = NULL; | ||
| 256 | 262 | ||
| 257 | ei->socket.fasync_list = NULL; | ||
| 258 | ei->socket.state = SS_UNCONNECTED; | 263 | ei->socket.state = SS_UNCONNECTED; |
| 259 | ei->socket.flags = 0; | 264 | ei->socket.flags = 0; |
| 260 | ei->socket.ops = NULL; | 265 | ei->socket.ops = NULL; |
| @@ -264,10 +269,21 @@ static struct inode *sock_alloc_inode(struct super_block *sb) | |||
| 264 | return &ei->vfs_inode; | 269 | return &ei->vfs_inode; |
| 265 | } | 270 | } |
| 266 | 271 | ||
| 272 | |||
| 273 | static void wq_free_rcu(struct rcu_head *head) | ||
| 274 | { | ||
| 275 | struct socket_wq *wq = container_of(head, struct socket_wq, rcu); | ||
| 276 | |||
| 277 | kfree(wq); | ||
| 278 | } | ||
| 279 | |||
| 267 | static void sock_destroy_inode(struct inode *inode) | 280 | static void sock_destroy_inode(struct inode *inode) |
| 268 | { | 281 | { |
| 269 | kmem_cache_free(sock_inode_cachep, | 282 | struct socket_alloc *ei; |
| 270 | container_of(inode, struct socket_alloc, vfs_inode)); | 283 | |
| 284 | ei = container_of(inode, struct socket_alloc, vfs_inode); | ||
| 285 | call_rcu(&ei->socket.wq->rcu, wq_free_rcu); | ||
| 286 | kmem_cache_free(sock_inode_cachep, ei); | ||
| 271 | } | 287 | } |
| 272 | 288 | ||
| 273 | static void init_once(void *foo) | 289 | static void init_once(void *foo) |
| @@ -513,7 +529,7 @@ void sock_release(struct socket *sock) | |||
| 513 | module_put(owner); | 529 | module_put(owner); |
| 514 | } | 530 | } |
| 515 | 531 | ||
| 516 | if (sock->fasync_list) | 532 | if (sock->wq->fasync_list) |
| 517 | printk(KERN_ERR "sock_release: fasync list not empty!\n"); | 533 | printk(KERN_ERR "sock_release: fasync list not empty!\n"); |
| 518 | 534 | ||
| 519 | percpu_sub(sockets_in_use, 1); | 535 | percpu_sub(sockets_in_use, 1); |
| @@ -655,13 +671,13 @@ inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, struct sk_buff | |||
| 655 | sizeof(__u32), &skb->dropcount); | 671 | sizeof(__u32), &skb->dropcount); |
| 656 | } | 672 | } |
| 657 | 673 | ||
| 658 | void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, | 674 | void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, |
| 659 | struct sk_buff *skb) | 675 | struct sk_buff *skb) |
| 660 | { | 676 | { |
| 661 | sock_recv_timestamp(msg, sk, skb); | 677 | sock_recv_timestamp(msg, sk, skb); |
| 662 | sock_recv_drops(msg, sk, skb); | 678 | sock_recv_drops(msg, sk, skb); |
| 663 | } | 679 | } |
| 664 | EXPORT_SYMBOL_GPL(sock_recv_ts_and_drops); | 680 | EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); |
| 665 | 681 | ||
| 666 | static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock, | 682 | static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock, |
| 667 | struct msghdr *msg, size_t size, int flags) | 683 | struct msghdr *msg, size_t size, int flags) |
| @@ -1067,87 +1083,44 @@ static int sock_close(struct inode *inode, struct file *filp) | |||
| 1067 | * 1. fasync_list is modified only under process context socket lock | 1083 | * 1. fasync_list is modified only under process context socket lock |
| 1068 | * i.e. under semaphore. | 1084 | * i.e. under semaphore. |
| 1069 | * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) | 1085 | * 2. fasync_list is used under read_lock(&sk->sk_callback_lock) |
| 1070 | * or under socket lock. | 1086 | * or under socket lock |
| 1071 | * 3. fasync_list can be used from softirq context, so that | ||
| 1072 | * modification under socket lock have to be enhanced with | ||
| 1073 | * write_lock_bh(&sk->sk_callback_lock). | ||
| 1074 | * --ANK (990710) | ||
| 1075 | */ | 1087 | */ |
| 1076 | 1088 | ||
| 1077 | static int sock_fasync(int fd, struct file *filp, int on) | 1089 | static int sock_fasync(int fd, struct file *filp, int on) |
| 1078 | { | 1090 | { |
| 1079 | struct fasync_struct *fa, *fna = NULL, **prev; | 1091 | struct socket *sock = filp->private_data; |
| 1080 | struct socket *sock; | 1092 | struct sock *sk = sock->sk; |
| 1081 | struct sock *sk; | ||
| 1082 | |||
| 1083 | if (on) { | ||
| 1084 | fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL); | ||
| 1085 | if (fna == NULL) | ||
| 1086 | return -ENOMEM; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | sock = filp->private_data; | ||
| 1090 | 1093 | ||
| 1091 | sk = sock->sk; | 1094 | if (sk == NULL) |
| 1092 | if (sk == NULL) { | ||
| 1093 | kfree(fna); | ||
| 1094 | return -EINVAL; | 1095 | return -EINVAL; |
| 1095 | } | ||
| 1096 | 1096 | ||
| 1097 | lock_sock(sk); | 1097 | lock_sock(sk); |
| 1098 | 1098 | ||
| 1099 | spin_lock(&filp->f_lock); | 1099 | fasync_helper(fd, filp, on, &sock->wq->fasync_list); |
| 1100 | if (on) | ||
| 1101 | filp->f_flags |= FASYNC; | ||
| 1102 | else | ||
| 1103 | filp->f_flags &= ~FASYNC; | ||
| 1104 | spin_unlock(&filp->f_lock); | ||
| 1105 | |||
| 1106 | prev = &(sock->fasync_list); | ||
| 1107 | |||
| 1108 | for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev) | ||
| 1109 | if (fa->fa_file == filp) | ||
| 1110 | break; | ||
| 1111 | |||
| 1112 | if (on) { | ||
| 1113 | if (fa != NULL) { | ||
| 1114 | write_lock_bh(&sk->sk_callback_lock); | ||
| 1115 | fa->fa_fd = fd; | ||
| 1116 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 1117 | 1100 | ||
| 1118 | kfree(fna); | 1101 | if (!sock->wq->fasync_list) |
| 1119 | goto out; | 1102 | sock_reset_flag(sk, SOCK_FASYNC); |
| 1120 | } | 1103 | else |
| 1121 | fna->fa_file = filp; | ||
| 1122 | fna->fa_fd = fd; | ||
| 1123 | fna->magic = FASYNC_MAGIC; | ||
| 1124 | fna->fa_next = sock->fasync_list; | ||
| 1125 | write_lock_bh(&sk->sk_callback_lock); | ||
| 1126 | sock->fasync_list = fna; | ||
| 1127 | sock_set_flag(sk, SOCK_FASYNC); | 1104 | sock_set_flag(sk, SOCK_FASYNC); |
| 1128 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 1129 | } else { | ||
| 1130 | if (fa != NULL) { | ||
| 1131 | write_lock_bh(&sk->sk_callback_lock); | ||
| 1132 | *prev = fa->fa_next; | ||
| 1133 | if (!sock->fasync_list) | ||
| 1134 | sock_reset_flag(sk, SOCK_FASYNC); | ||
| 1135 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 1136 | kfree(fa); | ||
| 1137 | } | ||
| 1138 | } | ||
| 1139 | 1105 | ||
| 1140 | out: | 1106 | release_sock(sk); |
| 1141 | release_sock(sock->sk); | ||
| 1142 | return 0; | 1107 | return 0; |
| 1143 | } | 1108 | } |
| 1144 | 1109 | ||
| 1145 | /* This function may be called only under socket lock or callback_lock */ | 1110 | /* This function may be called only under socket lock or callback_lock or rcu_lock */ |
| 1146 | 1111 | ||
| 1147 | int sock_wake_async(struct socket *sock, int how, int band) | 1112 | int sock_wake_async(struct socket *sock, int how, int band) |
| 1148 | { | 1113 | { |
| 1149 | if (!sock || !sock->fasync_list) | 1114 | struct socket_wq *wq; |
| 1115 | |||
| 1116 | if (!sock) | ||
| 1150 | return -1; | 1117 | return -1; |
| 1118 | rcu_read_lock(); | ||
| 1119 | wq = rcu_dereference(sock->wq); | ||
| 1120 | if (!wq || !wq->fasync_list) { | ||
| 1121 | rcu_read_unlock(); | ||
| 1122 | return -1; | ||
| 1123 | } | ||
| 1151 | switch (how) { | 1124 | switch (how) { |
| 1152 | case SOCK_WAKE_WAITD: | 1125 | case SOCK_WAKE_WAITD: |
| 1153 | if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) | 1126 | if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) |
| @@ -1159,11 +1132,12 @@ int sock_wake_async(struct socket *sock, int how, int band) | |||
| 1159 | /* fall through */ | 1132 | /* fall through */ |
| 1160 | case SOCK_WAKE_IO: | 1133 | case SOCK_WAKE_IO: |
| 1161 | call_kill: | 1134 | call_kill: |
| 1162 | __kill_fasync(sock->fasync_list, SIGIO, band); | 1135 | kill_fasync(&wq->fasync_list, SIGIO, band); |
| 1163 | break; | 1136 | break; |
| 1164 | case SOCK_WAKE_URG: | 1137 | case SOCK_WAKE_URG: |
| 1165 | __kill_fasync(sock->fasync_list, SIGURG, band); | 1138 | kill_fasync(&wq->fasync_list, SIGURG, band); |
| 1166 | } | 1139 | } |
| 1140 | rcu_read_unlock(); | ||
| 1167 | return 0; | 1141 | return 0; |
| 1168 | } | 1142 | } |
| 1169 | 1143 | ||
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index a29f259204e6..ce0d5b35c2ac 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
| @@ -419,8 +419,8 @@ static void svc_udp_data_ready(struct sock *sk, int count) | |||
| 419 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 419 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
| 420 | svc_xprt_enqueue(&svsk->sk_xprt); | 420 | svc_xprt_enqueue(&svsk->sk_xprt); |
| 421 | } | 421 | } |
| 422 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 422 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
| 423 | wake_up_interruptible(sk->sk_sleep); | 423 | wake_up_interruptible(sk_sleep(sk)); |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | /* | 426 | /* |
| @@ -436,10 +436,10 @@ static void svc_write_space(struct sock *sk) | |||
| 436 | svc_xprt_enqueue(&svsk->sk_xprt); | 436 | svc_xprt_enqueue(&svsk->sk_xprt); |
| 437 | } | 437 | } |
| 438 | 438 | ||
| 439 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) { | 439 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) { |
| 440 | dprintk("RPC svc_write_space: someone sleeping on %p\n", | 440 | dprintk("RPC svc_write_space: someone sleeping on %p\n", |
| 441 | svsk); | 441 | svsk); |
| 442 | wake_up_interruptible(sk->sk_sleep); | 442 | wake_up_interruptible(sk_sleep(sk)); |
| 443 | } | 443 | } |
| 444 | } | 444 | } |
| 445 | 445 | ||
| @@ -757,8 +757,8 @@ static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused) | |||
| 757 | printk("svc: socket %p: no user data\n", sk); | 757 | printk("svc: socket %p: no user data\n", sk); |
| 758 | } | 758 | } |
| 759 | 759 | ||
| 760 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 760 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
| 761 | wake_up_interruptible_all(sk->sk_sleep); | 761 | wake_up_interruptible_all(sk_sleep(sk)); |
| 762 | } | 762 | } |
| 763 | 763 | ||
| 764 | /* | 764 | /* |
| @@ -777,8 +777,8 @@ static void svc_tcp_state_change(struct sock *sk) | |||
| 777 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 777 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
| 778 | svc_xprt_enqueue(&svsk->sk_xprt); | 778 | svc_xprt_enqueue(&svsk->sk_xprt); |
| 779 | } | 779 | } |
| 780 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 780 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
| 781 | wake_up_interruptible_all(sk->sk_sleep); | 781 | wake_up_interruptible_all(sk_sleep(sk)); |
| 782 | } | 782 | } |
| 783 | 783 | ||
| 784 | static void svc_tcp_data_ready(struct sock *sk, int count) | 784 | static void svc_tcp_data_ready(struct sock *sk, int count) |
| @@ -791,8 +791,8 @@ static void svc_tcp_data_ready(struct sock *sk, int count) | |||
| 791 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 791 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
| 792 | svc_xprt_enqueue(&svsk->sk_xprt); | 792 | svc_xprt_enqueue(&svsk->sk_xprt); |
| 793 | } | 793 | } |
| 794 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 794 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
| 795 | wake_up_interruptible(sk->sk_sleep); | 795 | wake_up_interruptible(sk_sleep(sk)); |
| 796 | } | 796 | } |
| 797 | 797 | ||
| 798 | /* | 798 | /* |
| @@ -1494,8 +1494,8 @@ static void svc_sock_detach(struct svc_xprt *xprt) | |||
| 1494 | sk->sk_data_ready = svsk->sk_odata; | 1494 | sk->sk_data_ready = svsk->sk_odata; |
| 1495 | sk->sk_write_space = svsk->sk_owspace; | 1495 | sk->sk_write_space = svsk->sk_owspace; |
| 1496 | 1496 | ||
| 1497 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1497 | if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) |
| 1498 | wake_up_interruptible(sk->sk_sleep); | 1498 | wake_up_interruptible(sk_sleep(sk)); |
| 1499 | } | 1499 | } |
| 1500 | 1500 | ||
| 1501 | /* | 1501 | /* |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 42f09ade0044..699ade68aac1 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
| @@ -974,7 +974,7 @@ void xprt_reserve(struct rpc_task *task) | |||
| 974 | 974 | ||
| 975 | static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) | 975 | static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) |
| 976 | { | 976 | { |
| 977 | return xprt->xid++; | 977 | return (__force __be32)xprt->xid++; |
| 978 | } | 978 | } |
| 979 | 979 | ||
| 980 | static inline void xprt_init_xid(struct rpc_xprt *xprt) | 980 | static inline void xprt_init_xid(struct rpc_xprt *xprt) |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index fd90eb89842b..edea15a54e51 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
| @@ -679,7 +679,10 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, | |||
| 679 | int ret; | 679 | int ret; |
| 680 | 680 | ||
| 681 | dprintk("svcrdma: Creating RDMA socket\n"); | 681 | dprintk("svcrdma: Creating RDMA socket\n"); |
| 682 | 682 | if (sa->sa_family != AF_INET) { | |
| 683 | dprintk("svcrdma: Address family %d is not supported.\n", sa->sa_family); | ||
| 684 | return ERR_PTR(-EAFNOSUPPORT); | ||
| 685 | } | ||
| 683 | cma_xprt = rdma_create_xprt(serv, 1); | 686 | cma_xprt = rdma_create_xprt(serv, 1); |
| 684 | if (!cma_xprt) | 687 | if (!cma_xprt) |
| 685 | return ERR_PTR(-ENOMEM); | 688 | return ERR_PTR(-ENOMEM); |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index cfb20b80b3a1..66e889ba48fd 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -446,7 +446,7 @@ static unsigned int poll(struct file *file, struct socket *sock, | |||
| 446 | struct sock *sk = sock->sk; | 446 | struct sock *sk = sock->sk; |
| 447 | u32 mask; | 447 | u32 mask; |
| 448 | 448 | ||
| 449 | poll_wait(file, sk->sk_sleep, wait); | 449 | poll_wait(file, sk_sleep(sk), wait); |
| 450 | 450 | ||
| 451 | if (!skb_queue_empty(&sk->sk_receive_queue) || | 451 | if (!skb_queue_empty(&sk->sk_receive_queue) || |
| 452 | (sock->state == SS_UNCONNECTED) || | 452 | (sock->state == SS_UNCONNECTED) || |
| @@ -591,7 +591,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 591 | break; | 591 | break; |
| 592 | } | 592 | } |
| 593 | release_sock(sk); | 593 | release_sock(sk); |
| 594 | res = wait_event_interruptible(*sk->sk_sleep, | 594 | res = wait_event_interruptible(*sk_sleep(sk), |
| 595 | !tport->congested); | 595 | !tport->congested); |
| 596 | lock_sock(sk); | 596 | lock_sock(sk); |
| 597 | if (res) | 597 | if (res) |
| @@ -650,7 +650,7 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
| 650 | break; | 650 | break; |
| 651 | } | 651 | } |
| 652 | release_sock(sk); | 652 | release_sock(sk); |
| 653 | res = wait_event_interruptible(*sk->sk_sleep, | 653 | res = wait_event_interruptible(*sk_sleep(sk), |
| 654 | (!tport->congested || !tport->connected)); | 654 | (!tport->congested || !tport->connected)); |
| 655 | lock_sock(sk); | 655 | lock_sock(sk); |
| 656 | if (res) | 656 | if (res) |
| @@ -931,7 +931,7 @@ restart: | |||
| 931 | goto exit; | 931 | goto exit; |
| 932 | } | 932 | } |
| 933 | release_sock(sk); | 933 | release_sock(sk); |
| 934 | res = wait_event_interruptible(*sk->sk_sleep, | 934 | res = wait_event_interruptible(*sk_sleep(sk), |
| 935 | (!skb_queue_empty(&sk->sk_receive_queue) || | 935 | (!skb_queue_empty(&sk->sk_receive_queue) || |
| 936 | (sock->state == SS_DISCONNECTING))); | 936 | (sock->state == SS_DISCONNECTING))); |
| 937 | lock_sock(sk); | 937 | lock_sock(sk); |
| @@ -1064,7 +1064,7 @@ restart: | |||
| 1064 | goto exit; | 1064 | goto exit; |
| 1065 | } | 1065 | } |
| 1066 | release_sock(sk); | 1066 | release_sock(sk); |
| 1067 | res = wait_event_interruptible(*sk->sk_sleep, | 1067 | res = wait_event_interruptible(*sk_sleep(sk), |
| 1068 | (!skb_queue_empty(&sk->sk_receive_queue) || | 1068 | (!skb_queue_empty(&sk->sk_receive_queue) || |
| 1069 | (sock->state == SS_DISCONNECTING))); | 1069 | (sock->state == SS_DISCONNECTING))); |
| 1070 | lock_sock(sk); | 1070 | lock_sock(sk); |
| @@ -1271,8 +1271,8 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
| 1271 | tipc_disconnect_port(tipc_sk_port(sk)); | 1271 | tipc_disconnect_port(tipc_sk_port(sk)); |
| 1272 | } | 1272 | } |
| 1273 | 1273 | ||
| 1274 | if (waitqueue_active(sk->sk_sleep)) | 1274 | if (waitqueue_active(sk_sleep(sk))) |
| 1275 | wake_up_interruptible(sk->sk_sleep); | 1275 | wake_up_interruptible(sk_sleep(sk)); |
| 1276 | return TIPC_OK; | 1276 | return TIPC_OK; |
| 1277 | } | 1277 | } |
| 1278 | 1278 | ||
| @@ -1343,8 +1343,8 @@ static void wakeupdispatch(struct tipc_port *tport) | |||
| 1343 | { | 1343 | { |
| 1344 | struct sock *sk = (struct sock *)tport->usr_handle; | 1344 | struct sock *sk = (struct sock *)tport->usr_handle; |
| 1345 | 1345 | ||
| 1346 | if (waitqueue_active(sk->sk_sleep)) | 1346 | if (waitqueue_active(sk_sleep(sk))) |
| 1347 | wake_up_interruptible(sk->sk_sleep); | 1347 | wake_up_interruptible(sk_sleep(sk)); |
| 1348 | } | 1348 | } |
| 1349 | 1349 | ||
| 1350 | /** | 1350 | /** |
| @@ -1426,7 +1426,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
| 1426 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ | 1426 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ |
| 1427 | 1427 | ||
| 1428 | release_sock(sk); | 1428 | release_sock(sk); |
| 1429 | res = wait_event_interruptible_timeout(*sk->sk_sleep, | 1429 | res = wait_event_interruptible_timeout(*sk_sleep(sk), |
| 1430 | (!skb_queue_empty(&sk->sk_receive_queue) || | 1430 | (!skb_queue_empty(&sk->sk_receive_queue) || |
| 1431 | (sock->state != SS_CONNECTING)), | 1431 | (sock->state != SS_CONNECTING)), |
| 1432 | sk->sk_rcvtimeo); | 1432 | sk->sk_rcvtimeo); |
| @@ -1521,7 +1521,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
| 1521 | goto exit; | 1521 | goto exit; |
| 1522 | } | 1522 | } |
| 1523 | release_sock(sk); | 1523 | release_sock(sk); |
| 1524 | res = wait_event_interruptible(*sk->sk_sleep, | 1524 | res = wait_event_interruptible(*sk_sleep(sk), |
| 1525 | (!skb_queue_empty(&sk->sk_receive_queue))); | 1525 | (!skb_queue_empty(&sk->sk_receive_queue))); |
| 1526 | lock_sock(sk); | 1526 | lock_sock(sk); |
| 1527 | if (res) | 1527 | if (res) |
| @@ -1632,8 +1632,8 @@ restart: | |||
| 1632 | /* Discard any unreceived messages; wake up sleeping tasks */ | 1632 | /* Discard any unreceived messages; wake up sleeping tasks */ |
| 1633 | 1633 | ||
| 1634 | discard_rx_queue(sk); | 1634 | discard_rx_queue(sk); |
| 1635 | if (waitqueue_active(sk->sk_sleep)) | 1635 | if (waitqueue_active(sk_sleep(sk))) |
| 1636 | wake_up_interruptible(sk->sk_sleep); | 1636 | wake_up_interruptible(sk_sleep(sk)); |
| 1637 | res = 0; | 1637 | res = 0; |
| 1638 | break; | 1638 | break; |
| 1639 | 1639 | ||
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 3d9122e78f41..fef2cc5e9d2b 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
| @@ -313,13 +313,16 @@ static inline int unix_writable(struct sock *sk) | |||
| 313 | 313 | ||
| 314 | static void unix_write_space(struct sock *sk) | 314 | static void unix_write_space(struct sock *sk) |
| 315 | { | 315 | { |
| 316 | read_lock(&sk->sk_callback_lock); | 316 | struct socket_wq *wq; |
| 317 | |||
| 318 | rcu_read_lock(); | ||
| 317 | if (unix_writable(sk)) { | 319 | if (unix_writable(sk)) { |
| 318 | if (sk_has_sleeper(sk)) | 320 | wq = rcu_dereference(sk->sk_wq); |
| 319 | wake_up_interruptible_sync(sk->sk_sleep); | 321 | if (wq_has_sleeper(wq)) |
| 322 | wake_up_interruptible_sync(&wq->wait); | ||
| 320 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 323 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
| 321 | } | 324 | } |
| 322 | read_unlock(&sk->sk_callback_lock); | 325 | rcu_read_unlock(); |
| 323 | } | 326 | } |
| 324 | 327 | ||
| 325 | /* When dgram socket disconnects (or changes its peer), we clear its receive | 328 | /* When dgram socket disconnects (or changes its peer), we clear its receive |
| @@ -406,9 +409,7 @@ static int unix_release_sock(struct sock *sk, int embrion) | |||
| 406 | skpair->sk_err = ECONNRESET; | 409 | skpair->sk_err = ECONNRESET; |
| 407 | unix_state_unlock(skpair); | 410 | unix_state_unlock(skpair); |
| 408 | skpair->sk_state_change(skpair); | 411 | skpair->sk_state_change(skpair); |
| 409 | read_lock(&skpair->sk_callback_lock); | ||
| 410 | sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP); | 412 | sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP); |
| 411 | read_unlock(&skpair->sk_callback_lock); | ||
| 412 | } | 413 | } |
| 413 | sock_put(skpair); /* It may now die */ | 414 | sock_put(skpair); /* It may now die */ |
| 414 | unix_peer(sk) = NULL; | 415 | unix_peer(sk) = NULL; |
| @@ -1142,7 +1143,7 @@ restart: | |||
| 1142 | newsk->sk_peercred.pid = task_tgid_vnr(current); | 1143 | newsk->sk_peercred.pid = task_tgid_vnr(current); |
| 1143 | current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid); | 1144 | current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid); |
| 1144 | newu = unix_sk(newsk); | 1145 | newu = unix_sk(newsk); |
| 1145 | newsk->sk_sleep = &newu->peer_wait; | 1146 | newsk->sk_wq = &newu->peer_wq; |
| 1146 | otheru = unix_sk(other); | 1147 | otheru = unix_sk(other); |
| 1147 | 1148 | ||
| 1148 | /* copy address information from listening to new sock*/ | 1149 | /* copy address information from listening to new sock*/ |
| @@ -1736,7 +1737,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) | |||
| 1736 | unix_state_lock(sk); | 1737 | unix_state_lock(sk); |
| 1737 | 1738 | ||
| 1738 | for (;;) { | 1739 | for (;;) { |
| 1739 | prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); | 1740 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 1740 | 1741 | ||
| 1741 | if (!skb_queue_empty(&sk->sk_receive_queue) || | 1742 | if (!skb_queue_empty(&sk->sk_receive_queue) || |
| 1742 | sk->sk_err || | 1743 | sk->sk_err || |
| @@ -1752,7 +1753,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) | |||
| 1752 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); | 1753 | clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); |
| 1753 | } | 1754 | } |
| 1754 | 1755 | ||
| 1755 | finish_wait(sk->sk_sleep, &wait); | 1756 | finish_wait(sk_sleep(sk), &wait); |
| 1756 | unix_state_unlock(sk); | 1757 | unix_state_unlock(sk); |
| 1757 | return timeo; | 1758 | return timeo; |
| 1758 | } | 1759 | } |
| @@ -1931,12 +1932,10 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
| 1931 | other->sk_shutdown |= peer_mode; | 1932 | other->sk_shutdown |= peer_mode; |
| 1932 | unix_state_unlock(other); | 1933 | unix_state_unlock(other); |
| 1933 | other->sk_state_change(other); | 1934 | other->sk_state_change(other); |
| 1934 | read_lock(&other->sk_callback_lock); | ||
| 1935 | if (peer_mode == SHUTDOWN_MASK) | 1935 | if (peer_mode == SHUTDOWN_MASK) |
| 1936 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); | 1936 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); |
| 1937 | else if (peer_mode & RCV_SHUTDOWN) | 1937 | else if (peer_mode & RCV_SHUTDOWN) |
| 1938 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); | 1938 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); |
| 1939 | read_unlock(&other->sk_callback_lock); | ||
| 1940 | } | 1939 | } |
| 1941 | if (other) | 1940 | if (other) |
| 1942 | sock_put(other); | 1941 | sock_put(other); |
| @@ -1991,7 +1990,7 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table | |||
| 1991 | struct sock *sk = sock->sk; | 1990 | struct sock *sk = sock->sk; |
| 1992 | unsigned int mask; | 1991 | unsigned int mask; |
| 1993 | 1992 | ||
| 1994 | sock_poll_wait(file, sk->sk_sleep, wait); | 1993 | sock_poll_wait(file, sk_sleep(sk), wait); |
| 1995 | mask = 0; | 1994 | mask = 0; |
| 1996 | 1995 | ||
| 1997 | /* exceptional events? */ | 1996 | /* exceptional events? */ |
| @@ -2028,7 +2027,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
| 2028 | struct sock *sk = sock->sk, *other; | 2027 | struct sock *sk = sock->sk, *other; |
| 2029 | unsigned int mask, writable; | 2028 | unsigned int mask, writable; |
| 2030 | 2029 | ||
| 2031 | sock_poll_wait(file, sk->sk_sleep, wait); | 2030 | sock_poll_wait(file, sk_sleep(sk), wait); |
| 2032 | mask = 0; | 2031 | mask = 0; |
| 2033 | 2032 | ||
| 2034 | /* exceptional events? */ | 2033 | /* exceptional events? */ |
diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 14c22c3768da..c8df6fda0b1f 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c | |||
| @@ -153,15 +153,6 @@ void unix_notinflight(struct file *fp) | |||
| 153 | } | 153 | } |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | static inline struct sk_buff *sock_queue_head(struct sock *sk) | ||
| 157 | { | ||
| 158 | return (struct sk_buff *)&sk->sk_receive_queue; | ||
| 159 | } | ||
| 160 | |||
| 161 | #define receive_queue_for_each_skb(sk, next, skb) \ | ||
| 162 | for (skb = sock_queue_head(sk)->next, next = skb->next; \ | ||
| 163 | skb != sock_queue_head(sk); skb = next, next = skb->next) | ||
| 164 | |||
| 165 | static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), | 156 | static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), |
| 166 | struct sk_buff_head *hitlist) | 157 | struct sk_buff_head *hitlist) |
| 167 | { | 158 | { |
| @@ -169,7 +160,7 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), | |||
| 169 | struct sk_buff *next; | 160 | struct sk_buff *next; |
| 170 | 161 | ||
| 171 | spin_lock(&x->sk_receive_queue.lock); | 162 | spin_lock(&x->sk_receive_queue.lock); |
| 172 | receive_queue_for_each_skb(x, next, skb) { | 163 | skb_queue_walk_safe(&x->sk_receive_queue, skb, next) { |
| 173 | /* | 164 | /* |
| 174 | * Do we have file descriptors ? | 165 | * Do we have file descriptors ? |
| 175 | */ | 166 | */ |
| @@ -225,7 +216,7 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *), | |||
| 225 | * and perform a scan on them as well. | 216 | * and perform a scan on them as well. |
| 226 | */ | 217 | */ |
| 227 | spin_lock(&x->sk_receive_queue.lock); | 218 | spin_lock(&x->sk_receive_queue.lock); |
| 228 | receive_queue_for_each_skb(x, next, skb) { | 219 | skb_queue_walk_safe(&x->sk_receive_queue, skb, next) { |
| 229 | u = unix_sk(skb->sk); | 220 | u = unix_sk(skb->sk); |
| 230 | 221 | ||
| 231 | /* | 222 | /* |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 6ac70c101523..37d0e0ab4432 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -705,7 +705,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
| 705 | wdev->ps = true; | 705 | wdev->ps = true; |
| 706 | else | 706 | else |
| 707 | wdev->ps = false; | 707 | wdev->ps = false; |
| 708 | wdev->ps_timeout = 100; | 708 | /* allow mac80211 to determine the timeout */ |
| 709 | wdev->ps_timeout = -1; | ||
| 709 | if (rdev->ops->set_power_mgmt) | 710 | if (rdev->ops->set_power_mgmt) |
| 710 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, | 711 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, |
| 711 | wdev->ps, | 712 | wdev->ps, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 356a84a5daee..01da83ddcff7 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -152,6 +152,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
| 152 | [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, | 152 | [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, |
| 153 | [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, | 153 | [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, |
| 154 | [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, | 154 | [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, |
| 155 | [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 }, | ||
| 155 | }; | 156 | }; |
| 156 | 157 | ||
| 157 | /* policy for the attributes */ | 158 | /* policy for the attributes */ |
| @@ -2442,6 +2443,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
| 2442 | params.use_cts_prot = -1; | 2443 | params.use_cts_prot = -1; |
| 2443 | params.use_short_preamble = -1; | 2444 | params.use_short_preamble = -1; |
| 2444 | params.use_short_slot_time = -1; | 2445 | params.use_short_slot_time = -1; |
| 2446 | params.ap_isolate = -1; | ||
| 2445 | 2447 | ||
| 2446 | if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) | 2448 | if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) |
| 2447 | params.use_cts_prot = | 2449 | params.use_cts_prot = |
| @@ -2458,6 +2460,8 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
| 2458 | params.basic_rates_len = | 2460 | params.basic_rates_len = |
| 2459 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | 2461 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); |
| 2460 | } | 2462 | } |
| 2463 | if (info->attrs[NL80211_ATTR_AP_ISOLATE]) | ||
| 2464 | params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]); | ||
| 2461 | 2465 | ||
| 2462 | rtnl_lock(); | 2466 | rtnl_lock(); |
| 2463 | 2467 | ||
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index c2735775ec19..8ddf5ae0dd03 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
| @@ -518,12 +518,16 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
| 518 | ev->type = EVENT_CONNECT_RESULT; | 518 | ev->type = EVENT_CONNECT_RESULT; |
| 519 | if (bssid) | 519 | if (bssid) |
| 520 | memcpy(ev->cr.bssid, bssid, ETH_ALEN); | 520 | memcpy(ev->cr.bssid, bssid, ETH_ALEN); |
| 521 | ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev); | 521 | if (req_ie_len) { |
| 522 | ev->cr.req_ie_len = req_ie_len; | 522 | ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev); |
| 523 | memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len); | 523 | ev->cr.req_ie_len = req_ie_len; |
| 524 | ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; | 524 | memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len); |
| 525 | ev->cr.resp_ie_len = resp_ie_len; | 525 | } |
| 526 | memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); | 526 | if (resp_ie_len) { |
| 527 | ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; | ||
| 528 | ev->cr.resp_ie_len = resp_ie_len; | ||
| 529 | memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); | ||
| 530 | } | ||
| 527 | ev->cr.status = status; | 531 | ev->cr.status = status; |
| 528 | 532 | ||
| 529 | spin_lock_irqsave(&wdev->event_lock, flags); | 533 | spin_lock_irqsave(&wdev->event_lock, flags); |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index cbddd0cb83f1..296e65e01064 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
| @@ -402,6 +402,7 @@ static void __x25_destroy_socket(struct sock *sk) | |||
| 402 | /* | 402 | /* |
| 403 | * Queue the unaccepted socket for death | 403 | * Queue the unaccepted socket for death |
| 404 | */ | 404 | */ |
| 405 | skb->sk->sk_state = TCP_LISTEN; | ||
| 405 | sock_set_flag(skb->sk, SOCK_DEAD); | 406 | sock_set_flag(skb->sk, SOCK_DEAD); |
| 406 | x25_start_heartbeat(skb->sk); | 407 | x25_start_heartbeat(skb->sk); |
| 407 | x25_sk(skb->sk)->state = X25_STATE_0; | 408 | x25_sk(skb->sk)->state = X25_STATE_0; |
| @@ -718,7 +719,7 @@ static int x25_wait_for_connection_establishment(struct sock *sk) | |||
| 718 | DECLARE_WAITQUEUE(wait, current); | 719 | DECLARE_WAITQUEUE(wait, current); |
| 719 | int rc; | 720 | int rc; |
| 720 | 721 | ||
| 721 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 722 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
| 722 | for (;;) { | 723 | for (;;) { |
| 723 | __set_current_state(TASK_INTERRUPTIBLE); | 724 | __set_current_state(TASK_INTERRUPTIBLE); |
| 724 | rc = -ERESTARTSYS; | 725 | rc = -ERESTARTSYS; |
| @@ -738,7 +739,7 @@ static int x25_wait_for_connection_establishment(struct sock *sk) | |||
| 738 | break; | 739 | break; |
| 739 | } | 740 | } |
| 740 | __set_current_state(TASK_RUNNING); | 741 | __set_current_state(TASK_RUNNING); |
| 741 | remove_wait_queue(sk->sk_sleep, &wait); | 742 | remove_wait_queue(sk_sleep(sk), &wait); |
| 742 | return rc; | 743 | return rc; |
| 743 | } | 744 | } |
| 744 | 745 | ||
| @@ -838,7 +839,7 @@ static int x25_wait_for_data(struct sock *sk, long timeout) | |||
| 838 | DECLARE_WAITQUEUE(wait, current); | 839 | DECLARE_WAITQUEUE(wait, current); |
| 839 | int rc = 0; | 840 | int rc = 0; |
| 840 | 841 | ||
| 841 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 842 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
| 842 | for (;;) { | 843 | for (;;) { |
| 843 | __set_current_state(TASK_INTERRUPTIBLE); | 844 | __set_current_state(TASK_INTERRUPTIBLE); |
| 844 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 845 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
| @@ -858,7 +859,7 @@ static int x25_wait_for_data(struct sock *sk, long timeout) | |||
| 858 | break; | 859 | break; |
| 859 | } | 860 | } |
| 860 | __set_current_state(TASK_RUNNING); | 861 | __set_current_state(TASK_RUNNING); |
| 861 | remove_wait_queue(sk->sk_sleep, &wait); | 862 | remove_wait_queue(sk_sleep(sk), &wait); |
| 862 | return rc; | 863 | return rc; |
| 863 | } | 864 | } |
| 864 | 865 | ||
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index b9ef682230a0..9005f6daeab5 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <net/sock.h> | 24 | #include <net/sock.h> |
| 25 | #include <linux/if_arp.h> | 25 | #include <linux/if_arp.h> |
| 26 | #include <net/x25.h> | 26 | #include <net/x25.h> |
| 27 | #include <net/x25device.h> | ||
| 27 | 28 | ||
| 28 | static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb) | 29 | static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb) |
| 29 | { | 30 | { |
| @@ -115,19 +116,22 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev, | |||
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | switch (skb->data[0]) { | 118 | switch (skb->data[0]) { |
| 118 | case 0x00: | 119 | |
| 119 | skb_pull(skb, 1); | 120 | case X25_IFACE_DATA: |
| 120 | if (x25_receive_data(skb, nb)) { | 121 | skb_pull(skb, 1); |
| 121 | x25_neigh_put(nb); | 122 | if (x25_receive_data(skb, nb)) { |
| 122 | goto out; | 123 | x25_neigh_put(nb); |
| 123 | } | 124 | goto out; |
| 124 | break; | 125 | } |
| 125 | case 0x01: | 126 | break; |
| 126 | x25_link_established(nb); | 127 | |
| 127 | break; | 128 | case X25_IFACE_CONNECT: |
| 128 | case 0x02: | 129 | x25_link_established(nb); |
| 129 | x25_link_terminated(nb); | 130 | break; |
| 130 | break; | 131 | |
| 132 | case X25_IFACE_DISCONNECT: | ||
| 133 | x25_link_terminated(nb); | ||
| 134 | break; | ||
| 131 | } | 135 | } |
| 132 | x25_neigh_put(nb); | 136 | x25_neigh_put(nb); |
| 133 | drop: | 137 | drop: |
| @@ -148,7 +152,7 @@ void x25_establish_link(struct x25_neigh *nb) | |||
| 148 | return; | 152 | return; |
| 149 | } | 153 | } |
| 150 | ptr = skb_put(skb, 1); | 154 | ptr = skb_put(skb, 1); |
| 151 | *ptr = 0x01; | 155 | *ptr = X25_IFACE_CONNECT; |
| 152 | break; | 156 | break; |
| 153 | 157 | ||
| 154 | #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) | 158 | #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) |
| @@ -184,7 +188,7 @@ void x25_terminate_link(struct x25_neigh *nb) | |||
| 184 | } | 188 | } |
| 185 | 189 | ||
| 186 | ptr = skb_put(skb, 1); | 190 | ptr = skb_put(skb, 1); |
| 187 | *ptr = 0x02; | 191 | *ptr = X25_IFACE_DISCONNECT; |
| 188 | 192 | ||
| 189 | skb->protocol = htons(ETH_P_X25); | 193 | skb->protocol = htons(ETH_P_X25); |
| 190 | skb->dev = nb->dev; | 194 | skb->dev = nb->dev; |
| @@ -200,7 +204,7 @@ void x25_send_frame(struct sk_buff *skb, struct x25_neigh *nb) | |||
| 200 | switch (nb->dev->type) { | 204 | switch (nb->dev->type) { |
| 201 | case ARPHRD_X25: | 205 | case ARPHRD_X25: |
| 202 | dptr = skb_push(skb, 1); | 206 | dptr = skb_push(skb, 1); |
| 203 | *dptr = 0x00; | 207 | *dptr = X25_IFACE_DATA; |
| 204 | break; | 208 | break; |
| 205 | 209 | ||
| 206 | #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) | 210 | #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) |
diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h index e5195c99f71e..1396572d2ade 100644 --- a/net/xfrm/xfrm_hash.h +++ b/net/xfrm/xfrm_hash.h | |||
| @@ -16,7 +16,8 @@ static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) | |||
| 16 | 16 | ||
| 17 | static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | 17 | static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) |
| 18 | { | 18 | { |
| 19 | return ntohl(daddr->a4 + saddr->a4); | 19 | u32 sum = (__force u32)daddr->a4 + (__force u32)saddr->a4; |
| 20 | return ntohl((__force __be32)sum); | ||
| 20 | } | 21 | } |
| 21 | 22 | ||
| 22 | static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | 23 | static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 7430ac26ec49..31f4ba43b48f 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -1732,7 +1732,7 @@ int __xfrm_lookup(struct net *net, struct dst_entry **dst_p, struct flowi *fl, | |||
| 1732 | struct dst_entry *dst, *dst_orig = *dst_p, *route; | 1732 | struct dst_entry *dst, *dst_orig = *dst_p, *route; |
| 1733 | u16 family = dst_orig->ops->family; | 1733 | u16 family = dst_orig->ops->family; |
| 1734 | u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); | 1734 | u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); |
| 1735 | int i, err, num_pols, num_xfrms, drop_pols = 0; | 1735 | int i, err, num_pols, num_xfrms = 0, drop_pols = 0; |
| 1736 | 1736 | ||
| 1737 | restart: | 1737 | restart: |
| 1738 | dst = NULL; | 1738 | dst = NULL; |
