summaryrefslogtreecommitdiffstats
path: root/net/phonet/pep.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-12-28 12:49:40 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2008-12-28 12:49:40 -0800
commit0191b625ca5a46206d2fb862bb08f36f2fcb3b31 (patch)
tree454d1842b1833d976da62abcbd5c47521ebe9bd7 /net/phonet/pep.c
parent54a696bd07c14d3b1192d03ce7269bc59b45209a (diff)
parenteb56092fc168bf5af199d47af50c0d84a96db898 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1429 commits) net: Allow dependancies of FDDI & Tokenring to be modular. igb: Fix build warning when DCA is disabled. net: Fix warning fallout from recent NAPI interface changes. gro: Fix potential use after free sfc: If AN is enabled, always read speed/duplex from the AN advertising bits sfc: When disabling the NIC, close the device rather than unregistering it sfc: SFT9001: Add cable diagnostics sfc: Add support for multiple PHY self-tests sfc: Merge top-level functions for self-tests sfc: Clean up PHY mode management in loopback self-test sfc: Fix unreliable link detection in some loopback modes sfc: Generate unique names for per-NIC workqueues 802.3ad: use standard ethhdr instead of ad_header 802.3ad: generalize out mac address initializer 802.3ad: initialize ports LACPDU from const initializer 802.3ad: remove typedef around ad_system 802.3ad: turn ports is_individual into a bool 802.3ad: turn ports is_enabled into a bool 802.3ad: make ntt bool ixgbe: Fix set_ringparam in ixgbe to use the same memory pools. ... Fixed trivial IPv4/6 address printing conflicts in fs/cifs/connect.c due to the conversion to %pI (in this networking merge) and the addition of doing IPv6 addresses (from the earlier merge of CIFS).
Diffstat (limited to 'net/phonet/pep.c')
-rw-r--r--net/phonet/pep.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index bc6d50f8324..bb3e67849b3 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)
{
struct pep_sock *pn = pep_sk(sk);
struct pnpipehdr *hdr = pnp_hdr(skb);
+ int wake = 0;
if (!pskb_may_pull(skb, sizeof(*hdr) + 4))
return -EINVAL;
@@ -241,16 +242,16 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
case PN_LEGACY_FLOW_CONTROL:
switch (hdr->data[4]) {
case PEP_IND_BUSY:
- pn->tx_credits = 0;
+ atomic_set(&pn->tx_credits, 0);
break;
case PEP_IND_READY:
- pn->tx_credits = 1;
+ atomic_set(&pn->tx_credits, wake = 1);
break;
}
break;
case PN_ONE_CREDIT_FLOW_CONTROL:
if (hdr->data[4] == PEP_IND_READY)
- pn->tx_credits = 1;
+ atomic_set(&pn->tx_credits, wake = 1);
break;
}
break;
@@ -258,10 +259,7 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
case PN_PEP_IND_ID_MCFC_GRANT_CREDITS:
if (pn->tx_fc != PN_MULTI_CREDIT_FLOW_CONTROL)
break;
- if (pn->tx_credits + hdr->data[4] > 0xff)
- pn->tx_credits = 0xff;
- else
- pn->tx_credits += hdr->data[4];
+ atomic_add(wake = hdr->data[4], &pn->tx_credits);
break;
default:
@@ -269,7 +267,7 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
(unsigned)hdr->data[1]);
return -EOPNOTSUPP;
}
- if (pn->tx_credits)
+ if (wake)
sk->sk_write_space(sk);
return 0;
}
@@ -343,7 +341,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
}
/* fall through */
case PNS_PEP_DISABLE_REQ:
- pn->tx_credits = 0;
+ atomic_set(&pn->tx_credits, 0);
pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
break;
@@ -390,7 +388,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
/* fall through */
case PNS_PIPE_ENABLED_IND:
if (!pn_flow_safe(pn->tx_fc)) {
- pn->tx_credits = 1;
+ atomic_set(&pn->tx_credits, 1);
sk->sk_write_space(sk);
}
if (sk->sk_state == TCP_ESTABLISHED)
@@ -504,8 +502,9 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb)
newpn->pn_sk.resource = pn->pn_sk.resource;
skb_queue_head_init(&newpn->ctrlreq_queue);
newpn->pipe_handle = pipe_handle;
+ atomic_set(&newpn->tx_credits, 0);
newpn->peer_type = peer_type;
- newpn->rx_credits = newpn->tx_credits = 0;
+ newpn->rx_credits = 0;
newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL;
newpn->init_enable = enabled;
@@ -821,14 +820,18 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb)
struct pep_sock *pn = pep_sk(sk);
struct pnpipehdr *ph;
+ if (pn_flow_safe(pn->tx_fc) &&
+ !atomic_add_unless(&pn->tx_credits, -1, 0)) {
+ kfree_skb(skb);
+ return -ENOBUFS;
+ }
+
skb_push(skb, 3);
skb_reset_transport_header(skb);
ph = pnp_hdr(skb);
ph->utid = 0;
ph->message_id = PNS_PIPE_DATA;
ph->pipe_handle = pn->pipe_handle;
- if (pn_flow_safe(pn->tx_fc) && pn->tx_credits)
- pn->tx_credits--;
return pn_skb_send(sk, skb, &pipe_srv);
}
@@ -866,7 +869,7 @@ disabled:
BUG_ON(sk->sk_state != TCP_ESTABLISHED);
/* Wait until flow control allows TX */
- done = pn->tx_credits > 0;
+ done = atomic_read(&pn->tx_credits);
while (!done) {
DEFINE_WAIT(wait);
@@ -881,7 +884,7 @@ disabled:
prepare_to_wait(&sk->sk_socket->wait, &wait,
TASK_INTERRUPTIBLE);
- done = sk_wait_event(sk, &timeo, pn->tx_credits > 0);
+ done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits));
finish_wait(&sk->sk_socket->wait, &wait);
if (sk->sk_state != TCP_ESTABLISHED)
@@ -895,7 +898,8 @@ disabled:
goto out;
skb_reserve(skb, MAX_PHONET_HEADER + 3);
- if (sk->sk_state != TCP_ESTABLISHED || !pn->tx_credits)
+ if (sk->sk_state != TCP_ESTABLISHED ||
+ !atomic_read(&pn->tx_credits))
goto disabled; /* sock_alloc_send_skb might sleep */
}
@@ -917,7 +921,7 @@ int pep_writeable(struct sock *sk)
{
struct pep_sock *pn = pep_sk(sk);
- return (sk->sk_state == TCP_ESTABLISHED) ? pn->tx_credits : 0;
+ return atomic_read(&pn->tx_credits);
}
int pep_write(struct sock *sk, struct sk_buff *skb)