diff mbox

[3/5] Phonet: use atomic for packet TX window

Message ID 1229522874-20636-3-git-send-email-remi.denis-courmont@nokia.com
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Rémi Denis-Courmont Dec. 17, 2008, 2:07 p.m. UTC
GPRS TX flow control won't need to lock the underlying socket anymore.

Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
 include/net/phonet/pep.h |    2 +-
 net/phonet/pep.c         |   38 +++++++++++++++++++++-----------------
 net/phonet/socket.c      |    2 +-
 3 files changed, 23 insertions(+), 19 deletions(-)

Comments

David Miller Dec. 17, 2008, 11:53 p.m. UTC | #1
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Date: Wed, 17 Dec 2008 16:07:52 +0200

> GPRS TX flow control won't need to lock the underlying socket anymore.
> 
> Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>

Applied.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h
index fcd7930..4c61cdc 100644
--- a/include/net/phonet/pep.h
+++ b/include/net/phonet/pep.h
@@ -35,12 +35,12 @@  struct pep_sock {
 	struct sock		*listener;
 	struct sk_buff_head	ctrlreq_queue;
 #define PNPIPE_CTRLREQ_MAX	10
+	atomic_t		tx_credits;
 	int			ifindex;
 	u16			peer_type;	/* peer type/subtype */
 	u8			pipe_handle;
 
 	u8			rx_credits;
-	u8			tx_credits;
 	u8			rx_fc;	/* RX flow control */
 	u8			tx_fc;	/* TX flow control */
 	u8			init_enable;	/* auto-enable at creation */
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index bc6d50f..bb3e678 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)
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index c75aa5c..ada2a35 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,
 	if (!mask && sk->sk_state == TCP_CLOSE_WAIT)
 		return POLLHUP;
 
-	if (sk->sk_state == TCP_ESTABLISHED && pn->tx_credits)
+	if (sk->sk_state == TCP_ESTABLISHED && atomic_read(&pn->tx_credits))
 		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
 
 	return mask;