Phonet: use atomic for packet TX window
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> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									57c81fffc8
								
							
						
					
					
						commit
						be677730a0
					
				| @ -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 */ | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user