aboutsummaryrefslogtreecommitdiffstats
path: root/net/phonet
diff options
context:
space:
mode:
Diffstat (limited to 'net/phonet')
-rw-r--r--net/phonet/pep.c38
-rw-r--r--net/phonet/socket.c2
2 files changed, 22 insertions, 18 deletions
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index bc6d50f83249..bb3e67849b38 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -225,6 +225,7 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
225{ 225{
226 struct pep_sock *pn = pep_sk(sk); 226 struct pep_sock *pn = pep_sk(sk);
227 struct pnpipehdr *hdr = pnp_hdr(skb); 227 struct pnpipehdr *hdr = pnp_hdr(skb);
228 int wake = 0;
228 229
229 if (!pskb_may_pull(skb, sizeof(*hdr) + 4)) 230 if (!pskb_may_pull(skb, sizeof(*hdr) + 4))
230 return -EINVAL; 231 return -EINVAL;
@@ -241,16 +242,16 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
241 case PN_LEGACY_FLOW_CONTROL: 242 case PN_LEGACY_FLOW_CONTROL:
242 switch (hdr->data[4]) { 243 switch (hdr->data[4]) {
243 case PEP_IND_BUSY: 244 case PEP_IND_BUSY:
244 pn->tx_credits = 0; 245 atomic_set(&pn->tx_credits, 0);
245 break; 246 break;
246 case PEP_IND_READY: 247 case PEP_IND_READY:
247 pn->tx_credits = 1; 248 atomic_set(&pn->tx_credits, wake = 1);
248 break; 249 break;
249 } 250 }
250 break; 251 break;
251 case PN_ONE_CREDIT_FLOW_CONTROL: 252 case PN_ONE_CREDIT_FLOW_CONTROL:
252 if (hdr->data[4] == PEP_IND_READY) 253 if (hdr->data[4] == PEP_IND_READY)
253 pn->tx_credits = 1; 254 atomic_set(&pn->tx_credits, wake = 1);
254 break; 255 break;
255 } 256 }
256 break; 257 break;
@@ -258,10 +259,7 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
258 case PN_PEP_IND_ID_MCFC_GRANT_CREDITS: 259 case PN_PEP_IND_ID_MCFC_GRANT_CREDITS:
259 if (pn->tx_fc != PN_MULTI_CREDIT_FLOW_CONTROL) 260 if (pn->tx_fc != PN_MULTI_CREDIT_FLOW_CONTROL)
260 break; 261 break;
261 if (pn->tx_credits + hdr->data[4] > 0xff) 262 atomic_add(wake = hdr->data[4], &pn->tx_credits);
262 pn->tx_credits = 0xff;
263 else
264 pn->tx_credits += hdr->data[4];
265 break; 263 break;
266 264
267 default: 265 default:
@@ -269,7 +267,7 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
269 (unsigned)hdr->data[1]); 267 (unsigned)hdr->data[1]);
270 return -EOPNOTSUPP; 268 return -EOPNOTSUPP;
271 } 269 }
272 if (pn->tx_credits) 270 if (wake)
273 sk->sk_write_space(sk); 271 sk->sk_write_space(sk);
274 return 0; 272 return 0;
275} 273}
@@ -343,7 +341,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
343 } 341 }
344 /* fall through */ 342 /* fall through */
345 case PNS_PEP_DISABLE_REQ: 343 case PNS_PEP_DISABLE_REQ:
346 pn->tx_credits = 0; 344 atomic_set(&pn->tx_credits, 0);
347 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); 345 pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
348 break; 346 break;
349 347
@@ -390,7 +388,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
390 /* fall through */ 388 /* fall through */
391 case PNS_PIPE_ENABLED_IND: 389 case PNS_PIPE_ENABLED_IND:
392 if (!pn_flow_safe(pn->tx_fc)) { 390 if (!pn_flow_safe(pn->tx_fc)) {
393 pn->tx_credits = 1; 391 atomic_set(&pn->tx_credits, 1);
394 sk->sk_write_space(sk); 392 sk->sk_write_space(sk);
395 } 393 }
396 if (sk->sk_state == TCP_ESTABLISHED) 394 if (sk->sk_state == TCP_ESTABLISHED)
@@ -504,8 +502,9 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb)
504 newpn->pn_sk.resource = pn->pn_sk.resource; 502 newpn->pn_sk.resource = pn->pn_sk.resource;
505 skb_queue_head_init(&newpn->ctrlreq_queue); 503 skb_queue_head_init(&newpn->ctrlreq_queue);
506 newpn->pipe_handle = pipe_handle; 504 newpn->pipe_handle = pipe_handle;
505 atomic_set(&newpn->tx_credits, 0);
507 newpn->peer_type = peer_type; 506 newpn->peer_type = peer_type;
508 newpn->rx_credits = newpn->tx_credits = 0; 507 newpn->rx_credits = 0;
509 newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL; 508 newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL;
510 newpn->init_enable = enabled; 509 newpn->init_enable = enabled;
511 510
@@ -821,14 +820,18 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb)
821 struct pep_sock *pn = pep_sk(sk); 820 struct pep_sock *pn = pep_sk(sk);
822 struct pnpipehdr *ph; 821 struct pnpipehdr *ph;
823 822
823 if (pn_flow_safe(pn->tx_fc) &&
824 !atomic_add_unless(&pn->tx_credits, -1, 0)) {
825 kfree_skb(skb);
826 return -ENOBUFS;
827 }
828
824 skb_push(skb, 3); 829 skb_push(skb, 3);
825 skb_reset_transport_header(skb); 830 skb_reset_transport_header(skb);
826 ph = pnp_hdr(skb); 831 ph = pnp_hdr(skb);
827 ph->utid = 0; 832 ph->utid = 0;
828 ph->message_id = PNS_PIPE_DATA; 833 ph->message_id = PNS_PIPE_DATA;
829 ph->pipe_handle = pn->pipe_handle; 834 ph->pipe_handle = pn->pipe_handle;
830 if (pn_flow_safe(pn->tx_fc) && pn->tx_credits)
831 pn->tx_credits--;
832 835
833 return pn_skb_send(sk, skb, &pipe_srv); 836 return pn_skb_send(sk, skb, &pipe_srv);
834} 837}
@@ -866,7 +869,7 @@ disabled:
866 BUG_ON(sk->sk_state != TCP_ESTABLISHED); 869 BUG_ON(sk->sk_state != TCP_ESTABLISHED);
867 870
868 /* Wait until flow control allows TX */ 871 /* Wait until flow control allows TX */
869 done = pn->tx_credits > 0; 872 done = atomic_read(&pn->tx_credits);
870 while (!done) { 873 while (!done) {
871 DEFINE_WAIT(wait); 874 DEFINE_WAIT(wait);
872 875
@@ -881,7 +884,7 @@ disabled:
881 884
882 prepare_to_wait(&sk->sk_socket->wait, &wait, 885 prepare_to_wait(&sk->sk_socket->wait, &wait,
883 TASK_INTERRUPTIBLE); 886 TASK_INTERRUPTIBLE);
884 done = sk_wait_event(sk, &timeo, pn->tx_credits > 0); 887 done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits));
885 finish_wait(&sk->sk_socket->wait, &wait); 888 finish_wait(&sk->sk_socket->wait, &wait);
886 889
887 if (sk->sk_state != TCP_ESTABLISHED) 890 if (sk->sk_state != TCP_ESTABLISHED)
@@ -895,7 +898,8 @@ disabled:
895 goto out; 898 goto out;
896 skb_reserve(skb, MAX_PHONET_HEADER + 3); 899 skb_reserve(skb, MAX_PHONET_HEADER + 3);
897 900
898 if (sk->sk_state != TCP_ESTABLISHED || !pn->tx_credits) 901 if (sk->sk_state != TCP_ESTABLISHED ||
902 !atomic_read(&pn->tx_credits))
899 goto disabled; /* sock_alloc_send_skb might sleep */ 903 goto disabled; /* sock_alloc_send_skb might sleep */
900 } 904 }
901 905
@@ -917,7 +921,7 @@ int pep_writeable(struct sock *sk)
917{ 921{
918 struct pep_sock *pn = pep_sk(sk); 922 struct pep_sock *pn = pep_sk(sk);
919 923
920 return (sk->sk_state == TCP_ESTABLISHED) ? pn->tx_credits : 0; 924 return atomic_read(&pn->tx_credits);
921} 925}
922 926
923int pep_write(struct sock *sk, struct sk_buff *skb) 927int pep_write(struct sock *sk, struct sk_buff *skb)
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index c75aa5cdead5..ada2a35bf7a2 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -227,7 +227,7 @@ static unsigned int pn_socket_poll(struct file *file, struct socket *sock,
227 if (!mask && sk->sk_state == TCP_CLOSE_WAIT) 227 if (!mask && sk->sk_state == TCP_CLOSE_WAIT)
228 return POLLHUP; 228 return POLLHUP;
229 229
230 if (sk->sk_state == TCP_ESTABLISHED && pn->tx_credits) 230 if (sk->sk_state == TCP_ESTABLISHED && atomic_read(&pn->tx_credits))
231 mask |= POLLOUT | POLLWRNORM | POLLWRBAND; 231 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
232 232
233 return mask; 233 return mask;