xref: /openbmc/linux/net/caif/caif_socket.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1af873fceSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e6f95ec8SSjur Braendeland /*
3e6f95ec8SSjur Braendeland  * Copyright (C) ST-Ericsson AB 2010
426ee65e6Ssjur.brandeland@stericsson.com  * Author:	Sjur Brendeland
5e6f95ec8SSjur Braendeland  */
6e6f95ec8SSjur Braendeland 
7b31fa5baSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
8b31fa5baSJoe Perches 
9b6459415SJakub Kicinski #include <linux/filter.h>
10e6f95ec8SSjur Braendeland #include <linux/fs.h>
11e6f95ec8SSjur Braendeland #include <linux/init.h>
12e6f95ec8SSjur Braendeland #include <linux/module.h>
133f07c014SIngo Molnar #include <linux/sched/signal.h>
14e6f95ec8SSjur Braendeland #include <linux/spinlock.h>
15e6f95ec8SSjur Braendeland #include <linux/mutex.h>
16e6f95ec8SSjur Braendeland #include <linux/list.h>
17e6f95ec8SSjur Braendeland #include <linux/wait.h>
18e6f95ec8SSjur Braendeland #include <linux/poll.h>
19e6f95ec8SSjur Braendeland #include <linux/tcp.h>
20e6f95ec8SSjur Braendeland #include <linux/uaccess.h>
21bece7b23SSjur Braendeland #include <linux/debugfs.h>
22e6f95ec8SSjur Braendeland #include <linux/caif/caif_socket.h>
2344764812SDmitry Tarnyagin #include <linux/pkt_sched.h>
24bece7b23SSjur Braendeland #include <net/sock.h>
25bece7b23SSjur Braendeland #include <net/tcp_states.h>
26e6f95ec8SSjur Braendeland #include <net/caif/caif_layer.h>
27e6f95ec8SSjur Braendeland #include <net/caif/caif_dev.h>
28e6f95ec8SSjur Braendeland #include <net/caif/cfpkt.h>
29e6f95ec8SSjur Braendeland 
30e6f95ec8SSjur Braendeland MODULE_LICENSE("GPL");
31bece7b23SSjur Braendeland MODULE_ALIAS_NETPROTO(AF_CAIF);
32e6f95ec8SSjur Braendeland 
33bece7b23SSjur Braendeland /*
34bece7b23SSjur Braendeland  * CAIF state is re-using the TCP socket states.
35bece7b23SSjur Braendeland  * caif_states stored in sk_state reflect the state as reported by
36bece7b23SSjur Braendeland  * the CAIF stack, while sk_socket->state is the state of the socket.
37bece7b23SSjur Braendeland  */
38bece7b23SSjur Braendeland enum caif_states {
39bece7b23SSjur Braendeland 	CAIF_CONNECTED		= TCP_ESTABLISHED,
40bece7b23SSjur Braendeland 	CAIF_CONNECTING	= TCP_SYN_SENT,
41bece7b23SSjur Braendeland 	CAIF_DISCONNECTED	= TCP_CLOSE
42bece7b23SSjur Braendeland };
43e6f95ec8SSjur Braendeland 
44e6f95ec8SSjur Braendeland #define TX_FLOW_ON_BIT	1
45e6f95ec8SSjur Braendeland #define RX_FLOW_ON_BIT	2
46e6f95ec8SSjur Braendeland 
47e6f95ec8SSjur Braendeland struct caifsock {
48bece7b23SSjur Braendeland 	struct sock sk; /* must be first member */
49e6f95ec8SSjur Braendeland 	struct cflayer layer;
508ee18e2aSChristophe JAILLET 	unsigned long flow_state;
51e6f95ec8SSjur Braendeland 	struct caif_connect_request conn_req;
52bece7b23SSjur Braendeland 	struct mutex readlock;
53e6f95ec8SSjur Braendeland 	struct dentry *debugfs_socket_dir;
542aa40aefSSjur Braendeland 	int headroom, tailroom, maxframe;
55e6f95ec8SSjur Braendeland };
56e6f95ec8SSjur Braendeland 
rx_flow_is_on(struct caifsock * cf_sk)57bece7b23SSjur Braendeland static int rx_flow_is_on(struct caifsock *cf_sk)
58bece7b23SSjur Braendeland {
598ee18e2aSChristophe JAILLET 	return test_bit(RX_FLOW_ON_BIT, &cf_sk->flow_state);
60bece7b23SSjur Braendeland }
61bece7b23SSjur Braendeland 
tx_flow_is_on(struct caifsock * cf_sk)62bece7b23SSjur Braendeland static int tx_flow_is_on(struct caifsock *cf_sk)
63bece7b23SSjur Braendeland {
648ee18e2aSChristophe JAILLET 	return test_bit(TX_FLOW_ON_BIT, &cf_sk->flow_state);
65bece7b23SSjur Braendeland }
66bece7b23SSjur Braendeland 
set_rx_flow_off(struct caifsock * cf_sk)67bece7b23SSjur Braendeland static void set_rx_flow_off(struct caifsock *cf_sk)
68bece7b23SSjur Braendeland {
698ee18e2aSChristophe JAILLET 	clear_bit(RX_FLOW_ON_BIT, &cf_sk->flow_state);
70bece7b23SSjur Braendeland }
71bece7b23SSjur Braendeland 
set_rx_flow_on(struct caifsock * cf_sk)72bece7b23SSjur Braendeland static void set_rx_flow_on(struct caifsock *cf_sk)
73bece7b23SSjur Braendeland {
748ee18e2aSChristophe JAILLET 	set_bit(RX_FLOW_ON_BIT, &cf_sk->flow_state);
75bece7b23SSjur Braendeland }
76bece7b23SSjur Braendeland 
set_tx_flow_off(struct caifsock * cf_sk)77bece7b23SSjur Braendeland static void set_tx_flow_off(struct caifsock *cf_sk)
78bece7b23SSjur Braendeland {
798ee18e2aSChristophe JAILLET 	clear_bit(TX_FLOW_ON_BIT, &cf_sk->flow_state);
80bece7b23SSjur Braendeland }
81bece7b23SSjur Braendeland 
set_tx_flow_on(struct caifsock * cf_sk)82bece7b23SSjur Braendeland static void set_tx_flow_on(struct caifsock *cf_sk)
83bece7b23SSjur Braendeland {
848ee18e2aSChristophe JAILLET 	set_bit(TX_FLOW_ON_BIT, &cf_sk->flow_state);
85bece7b23SSjur Braendeland }
86bece7b23SSjur Braendeland 
caif_read_lock(struct sock * sk)87bece7b23SSjur Braendeland static void caif_read_lock(struct sock *sk)
88bece7b23SSjur Braendeland {
89bece7b23SSjur Braendeland 	struct caifsock *cf_sk;
90bece7b23SSjur Braendeland 	cf_sk = container_of(sk, struct caifsock, sk);
91bece7b23SSjur Braendeland 	mutex_lock(&cf_sk->readlock);
92bece7b23SSjur Braendeland }
93bece7b23SSjur Braendeland 
caif_read_unlock(struct sock * sk)94bece7b23SSjur Braendeland static void caif_read_unlock(struct sock *sk)
95bece7b23SSjur Braendeland {
96bece7b23SSjur Braendeland 	struct caifsock *cf_sk;
97bece7b23SSjur Braendeland 	cf_sk = container_of(sk, struct caifsock, sk);
98bece7b23SSjur Braendeland 	mutex_unlock(&cf_sk->readlock);
99bece7b23SSjur Braendeland }
100bece7b23SSjur Braendeland 
sk_rcvbuf_lowwater(struct caifsock * cf_sk)101a9a8f107SSjur Braendeland static int sk_rcvbuf_lowwater(struct caifsock *cf_sk)
102bece7b23SSjur Braendeland {
103bece7b23SSjur Braendeland 	/* A quarter of full buffer is used a low water mark */
104bece7b23SSjur Braendeland 	return cf_sk->sk.sk_rcvbuf / 4;
105bece7b23SSjur Braendeland }
106bece7b23SSjur Braendeland 
caif_flow_ctrl(struct sock * sk,int mode)107a9a8f107SSjur Braendeland static void caif_flow_ctrl(struct sock *sk, int mode)
108bece7b23SSjur Braendeland {
109bece7b23SSjur Braendeland 	struct caifsock *cf_sk;
110bece7b23SSjur Braendeland 	cf_sk = container_of(sk, struct caifsock, sk);
111ca6a09f2SSjur Braendeland 	if (cf_sk->layer.dn && cf_sk->layer.dn->modemcmd)
112bece7b23SSjur Braendeland 		cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, mode);
113bece7b23SSjur Braendeland }
114bece7b23SSjur Braendeland 
115bece7b23SSjur Braendeland /*
116bece7b23SSjur Braendeland  * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are
117bece7b23SSjur Braendeland  * not dropped, but CAIF is sending flow off instead.
118bece7b23SSjur Braendeland  */
caif_queue_rcv_skb(struct sock * sk,struct sk_buff * skb)119b8a23e8dSEric Dumazet static void caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
120bece7b23SSjur Braendeland {
121bece7b23SSjur Braendeland 	int err;
122bece7b23SSjur Braendeland 	unsigned long flags;
123bece7b23SSjur Braendeland 	struct sk_buff_head *list = &sk->sk_receive_queue;
124bece7b23SSjur Braendeland 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
125b8a23e8dSEric Dumazet 	bool queued = false;
126bece7b23SSjur Braendeland 
127bece7b23SSjur Braendeland 	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
12895c96174SEric Dumazet 		(unsigned int)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) {
129e87cc472SJoe Perches 		net_dbg_ratelimited("sending flow OFF (queue len = %d %d)\n",
130bece7b23SSjur Braendeland 				    atomic_read(&cf_sk->sk.sk_rmem_alloc),
131bece7b23SSjur Braendeland 				    sk_rcvbuf_lowwater(cf_sk));
132bece7b23SSjur Braendeland 		set_rx_flow_off(cf_sk);
133ca6a09f2SSjur Braendeland 		caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ);
134bece7b23SSjur Braendeland 	}
135bece7b23SSjur Braendeland 
136bece7b23SSjur Braendeland 	err = sk_filter(sk, skb);
137bece7b23SSjur Braendeland 	if (err)
138b8a23e8dSEric Dumazet 		goto out;
139b8a23e8dSEric Dumazet 
140c76562b6SMel Gorman 	if (!sk_rmem_schedule(sk, skb, skb->truesize) && rx_flow_is_on(cf_sk)) {
141bece7b23SSjur Braendeland 		set_rx_flow_off(cf_sk);
142e87cc472SJoe Perches 		net_dbg_ratelimited("sending flow OFF due to rmem_schedule\n");
143ca6a09f2SSjur Braendeland 		caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ);
144bece7b23SSjur Braendeland 	}
145bece7b23SSjur Braendeland 	skb->dev = NULL;
146bece7b23SSjur Braendeland 	skb_set_owner_r(skb, sk);
147bece7b23SSjur Braendeland 	spin_lock_irqsave(&list->lock, flags);
148b8a23e8dSEric Dumazet 	queued = !sock_flag(sk, SOCK_DEAD);
149b8a23e8dSEric Dumazet 	if (queued)
150bece7b23SSjur Braendeland 		__skb_queue_tail(list, skb);
151bece7b23SSjur Braendeland 	spin_unlock_irqrestore(&list->lock, flags);
152b8a23e8dSEric Dumazet out:
153b8a23e8dSEric Dumazet 	if (queued)
154676d2369SDavid S. Miller 		sk->sk_data_ready(sk);
155bece7b23SSjur Braendeland 	else
156bece7b23SSjur Braendeland 		kfree_skb(skb);
157bece7b23SSjur Braendeland }
158e6f95ec8SSjur Braendeland 
159e6f95ec8SSjur Braendeland /* Packet Receive Callback function called from CAIF Stack */
caif_sktrecv_cb(struct cflayer * layr,struct cfpkt * pkt)160e6f95ec8SSjur Braendeland static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt)
161e6f95ec8SSjur Braendeland {
162e6f95ec8SSjur Braendeland 	struct caifsock *cf_sk;
163bece7b23SSjur Braendeland 	struct sk_buff *skb;
164e6f95ec8SSjur Braendeland 
165bece7b23SSjur Braendeland 	cf_sk = container_of(layr, struct caifsock, layer);
166bece7b23SSjur Braendeland 	skb = cfpkt_tonative(pkt);
167bece7b23SSjur Braendeland 
168bece7b23SSjur Braendeland 	if (unlikely(cf_sk->sk.sk_state != CAIF_CONNECTED)) {
1693f874adcSsjur.brandeland@stericsson.com 		kfree_skb(skb);
170e6f95ec8SSjur Braendeland 		return 0;
171e6f95ec8SSjur Braendeland 	}
172bece7b23SSjur Braendeland 	caif_queue_rcv_skb(&cf_sk->sk, skb);
173e6f95ec8SSjur Braendeland 	return 0;
174e6f95ec8SSjur Braendeland }
175e6f95ec8SSjur Braendeland 
cfsk_hold(struct cflayer * layr)176b3ccfbe4Ssjur.brandeland@stericsson.com static void cfsk_hold(struct cflayer *layr)
177b3ccfbe4Ssjur.brandeland@stericsson.com {
178b3ccfbe4Ssjur.brandeland@stericsson.com 	struct caifsock *cf_sk = container_of(layr, struct caifsock, layer);
179b3ccfbe4Ssjur.brandeland@stericsson.com 	sock_hold(&cf_sk->sk);
180b3ccfbe4Ssjur.brandeland@stericsson.com }
181b3ccfbe4Ssjur.brandeland@stericsson.com 
cfsk_put(struct cflayer * layr)182b3ccfbe4Ssjur.brandeland@stericsson.com static void cfsk_put(struct cflayer *layr)
183b3ccfbe4Ssjur.brandeland@stericsson.com {
184b3ccfbe4Ssjur.brandeland@stericsson.com 	struct caifsock *cf_sk = container_of(layr, struct caifsock, layer);
185b3ccfbe4Ssjur.brandeland@stericsson.com 	sock_put(&cf_sk->sk);
186b3ccfbe4Ssjur.brandeland@stericsson.com }
187b3ccfbe4Ssjur.brandeland@stericsson.com 
188bece7b23SSjur Braendeland /* Packet Control Callback function called from CAIF */
caif_ctrl_cb(struct cflayer * layr,enum caif_ctrlcmd flow,int phyid)189bece7b23SSjur Braendeland static void caif_ctrl_cb(struct cflayer *layr,
190e6f95ec8SSjur Braendeland 			 enum caif_ctrlcmd flow,
191e6f95ec8SSjur Braendeland 			 int phyid)
192e6f95ec8SSjur Braendeland {
193bece7b23SSjur Braendeland 	struct caifsock *cf_sk = container_of(layr, struct caifsock, layer);
194e6f95ec8SSjur Braendeland 	switch (flow) {
195e6f95ec8SSjur Braendeland 	case CAIF_CTRLCMD_FLOW_ON_IND:
196bece7b23SSjur Braendeland 		/* OK from modem to start sending again */
197bece7b23SSjur Braendeland 		set_tx_flow_on(cf_sk);
198bece7b23SSjur Braendeland 		cf_sk->sk.sk_state_change(&cf_sk->sk);
199e6f95ec8SSjur Braendeland 		break;
200e6f95ec8SSjur Braendeland 
201e6f95ec8SSjur Braendeland 	case CAIF_CTRLCMD_FLOW_OFF_IND:
202bece7b23SSjur Braendeland 		/* Modem asks us to shut up */
203bece7b23SSjur Braendeland 		set_tx_flow_off(cf_sk);
204bece7b23SSjur Braendeland 		cf_sk->sk.sk_state_change(&cf_sk->sk);
205e6f95ec8SSjur Braendeland 		break;
206e6f95ec8SSjur Braendeland 
207e6f95ec8SSjur Braendeland 	case CAIF_CTRLCMD_INIT_RSP:
208bece7b23SSjur Braendeland 		/* We're now connected */
209b3ccfbe4Ssjur.brandeland@stericsson.com 		caif_client_register_refcnt(&cf_sk->layer,
210b3ccfbe4Ssjur.brandeland@stericsson.com 						cfsk_hold, cfsk_put);
211bece7b23SSjur Braendeland 		cf_sk->sk.sk_state = CAIF_CONNECTED;
212bece7b23SSjur Braendeland 		set_tx_flow_on(cf_sk);
213eaa8c5f3SSjur Brændeland 		cf_sk->sk.sk_shutdown = 0;
214bece7b23SSjur Braendeland 		cf_sk->sk.sk_state_change(&cf_sk->sk);
215e6f95ec8SSjur Braendeland 		break;
216e6f95ec8SSjur Braendeland 
217e6f95ec8SSjur Braendeland 	case CAIF_CTRLCMD_DEINIT_RSP:
218bece7b23SSjur Braendeland 		/* We're now disconnected */
219bece7b23SSjur Braendeland 		cf_sk->sk.sk_state = CAIF_DISCONNECTED;
220bece7b23SSjur Braendeland 		cf_sk->sk.sk_state_change(&cf_sk->sk);
221e6f95ec8SSjur Braendeland 		break;
222e6f95ec8SSjur Braendeland 
223e6f95ec8SSjur Braendeland 	case CAIF_CTRLCMD_INIT_FAIL_RSP:
224bece7b23SSjur Braendeland 		/* Connect request failed */
225bece7b23SSjur Braendeland 		cf_sk->sk.sk_err = ECONNREFUSED;
226bece7b23SSjur Braendeland 		cf_sk->sk.sk_state = CAIF_DISCONNECTED;
227bece7b23SSjur Braendeland 		cf_sk->sk.sk_shutdown = SHUTDOWN_MASK;
228bece7b23SSjur Braendeland 		/*
229bece7b23SSjur Braendeland 		 * Socket "standards" seems to require POLLOUT to
230bece7b23SSjur Braendeland 		 * be set at connect failure.
231bece7b23SSjur Braendeland 		 */
232bece7b23SSjur Braendeland 		set_tx_flow_on(cf_sk);
233bece7b23SSjur Braendeland 		cf_sk->sk.sk_state_change(&cf_sk->sk);
234e6f95ec8SSjur Braendeland 		break;
235e6f95ec8SSjur Braendeland 
236e6f95ec8SSjur Braendeland 	case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND:
237bece7b23SSjur Braendeland 		/* Modem has closed this connection, or device is down. */
238bece7b23SSjur Braendeland 		cf_sk->sk.sk_shutdown = SHUTDOWN_MASK;
239bece7b23SSjur Braendeland 		cf_sk->sk.sk_err = ECONNRESET;
240bece7b23SSjur Braendeland 		set_rx_flow_on(cf_sk);
241e3ae2365SAlexander Aring 		sk_error_report(&cf_sk->sk);
242e6f95ec8SSjur Braendeland 		break;
243e6f95ec8SSjur Braendeland 
244e6f95ec8SSjur Braendeland 	default:
245b31fa5baSJoe Perches 		pr_debug("Unexpected flow command %d\n", flow);
246e6f95ec8SSjur Braendeland 	}
247e6f95ec8SSjur Braendeland }
248e6f95ec8SSjur Braendeland 
caif_check_flow_release(struct sock * sk)249bece7b23SSjur Braendeland static void caif_check_flow_release(struct sock *sk)
250e6f95ec8SSjur Braendeland {
251bece7b23SSjur Braendeland 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
252bece7b23SSjur Braendeland 
253bece7b23SSjur Braendeland 	if (rx_flow_is_on(cf_sk))
254bece7b23SSjur Braendeland 		return;
255bece7b23SSjur Braendeland 
256bece7b23SSjur Braendeland 	if (atomic_read(&sk->sk_rmem_alloc) <= sk_rcvbuf_lowwater(cf_sk)) {
257bece7b23SSjur Braendeland 			set_rx_flow_on(cf_sk);
258ca6a09f2SSjur Braendeland 			caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_ON_REQ);
259e6f95ec8SSjur Braendeland 	}
260bece7b23SSjur Braendeland }
261e6f95ec8SSjur Braendeland 
262dcda138dSSjur Braendeland /*
263dcda138dSSjur Braendeland  * Copied from unix_dgram_recvmsg, but removed credit checks,
264dcda138dSSjur Braendeland  * changed locking, address handling and added MSG_TRUNC.
265dcda138dSSjur Braendeland  */
caif_seqpkt_recvmsg(struct socket * sock,struct msghdr * m,size_t len,int flags)2661b784140SYing Xue static int caif_seqpkt_recvmsg(struct socket *sock, struct msghdr *m,
2671b784140SYing Xue 			       size_t len, int flags)
268e6f95ec8SSjur Braendeland 
269e6f95ec8SSjur Braendeland {
270e6f95ec8SSjur Braendeland 	struct sock *sk = sock->sk;
271e6f95ec8SSjur Braendeland 	struct sk_buff *skb;
272dcda138dSSjur Braendeland 	int ret;
273dcda138dSSjur Braendeland 	int copylen;
274e6f95ec8SSjur Braendeland 
275dcda138dSSjur Braendeland 	ret = -EOPNOTSUPP;
2763eeff778SAl Viro 	if (flags & MSG_OOB)
277dcda138dSSjur Braendeland 		goto read_error;
278e6f95ec8SSjur Braendeland 
279f4b41f06SOliver Hartkopp 	skb = skb_recv_datagram(sk, flags, &ret);
280bece7b23SSjur Braendeland 	if (!skb)
281e6f95ec8SSjur Braendeland 		goto read_error;
282dcda138dSSjur Braendeland 	copylen = skb->len;
283dcda138dSSjur Braendeland 	if (len < copylen) {
284dcda138dSSjur Braendeland 		m->msg_flags |= MSG_TRUNC;
285dcda138dSSjur Braendeland 		copylen = len;
286e6f95ec8SSjur Braendeland 	}
287e6f95ec8SSjur Braendeland 
28851f3d02bSDavid S. Miller 	ret = skb_copy_datagram_msg(skb, 0, m, copylen);
289bece7b23SSjur Braendeland 	if (ret)
290dcda138dSSjur Braendeland 		goto out_free;
291e6f95ec8SSjur Braendeland 
292dcda138dSSjur Braendeland 	ret = (flags & MSG_TRUNC) ? skb->len : copylen;
293dcda138dSSjur Braendeland out_free:
294e6f95ec8SSjur Braendeland 	skb_free_datagram(sk, skb);
295bece7b23SSjur Braendeland 	caif_check_flow_release(sk);
296dcda138dSSjur Braendeland 	return ret;
297e6f95ec8SSjur Braendeland 
298e6f95ec8SSjur Braendeland read_error:
299e6f95ec8SSjur Braendeland 	return ret;
300e6f95ec8SSjur Braendeland }
301e6f95ec8SSjur Braendeland 
302bece7b23SSjur Braendeland 
303bece7b23SSjur Braendeland /* Copied from unix_stream_wait_data, identical except for lock call. */
caif_stream_data_wait(struct sock * sk,long timeo)304bece7b23SSjur Braendeland static long caif_stream_data_wait(struct sock *sk, long timeo)
305e6f95ec8SSjur Braendeland {
306bece7b23SSjur Braendeland 	DEFINE_WAIT(wait);
307bece7b23SSjur Braendeland 	lock_sock(sk);
308e6f95ec8SSjur Braendeland 
309bece7b23SSjur Braendeland 	for (;;) {
310bece7b23SSjur Braendeland 		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
311e6f95ec8SSjur Braendeland 
312bece7b23SSjur Braendeland 		if (!skb_queue_empty(&sk->sk_receive_queue) ||
313bece7b23SSjur Braendeland 			sk->sk_err ||
314bece7b23SSjur Braendeland 			sk->sk_state != CAIF_CONNECTED ||
315bece7b23SSjur Braendeland 			sock_flag(sk, SOCK_DEAD) ||
316bece7b23SSjur Braendeland 			(sk->sk_shutdown & RCV_SHUTDOWN) ||
317bece7b23SSjur Braendeland 			signal_pending(current) ||
318bece7b23SSjur Braendeland 			!timeo)
319bece7b23SSjur Braendeland 			break;
320bece7b23SSjur Braendeland 
3219cd3e072SEric Dumazet 		sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
322bece7b23SSjur Braendeland 		release_sock(sk);
323bece7b23SSjur Braendeland 		timeo = schedule_timeout(timeo);
324bece7b23SSjur Braendeland 		lock_sock(sk);
325b48732e4SMark Salyzyn 
326b48732e4SMark Salyzyn 		if (sock_flag(sk, SOCK_DEAD))
327b48732e4SMark Salyzyn 			break;
328b48732e4SMark Salyzyn 
3299cd3e072SEric Dumazet 		sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
330e6f95ec8SSjur Braendeland 	}
331e6f95ec8SSjur Braendeland 
332bece7b23SSjur Braendeland 	finish_wait(sk_sleep(sk), &wait);
333bece7b23SSjur Braendeland 	release_sock(sk);
334bece7b23SSjur Braendeland 	return timeo;
335e6f95ec8SSjur Braendeland }
336e6f95ec8SSjur Braendeland 
337e6f95ec8SSjur Braendeland 
338e6f95ec8SSjur Braendeland /*
339bece7b23SSjur Braendeland  * Copied from unix_stream_recvmsg, but removed credit checks,
340bece7b23SSjur Braendeland  * changed locking calls, changed address handling.
341e6f95ec8SSjur Braendeland  */
caif_stream_recvmsg(struct socket * sock,struct msghdr * msg,size_t size,int flags)3421b784140SYing Xue static int caif_stream_recvmsg(struct socket *sock, struct msghdr *msg,
3431b784140SYing Xue 			       size_t size, int flags)
344bece7b23SSjur Braendeland {
345bece7b23SSjur Braendeland 	struct sock *sk = sock->sk;
346bece7b23SSjur Braendeland 	int copied = 0;
347bece7b23SSjur Braendeland 	int target;
348bece7b23SSjur Braendeland 	int err = 0;
349bece7b23SSjur Braendeland 	long timeo;
350e6f95ec8SSjur Braendeland 
351bece7b23SSjur Braendeland 	err = -EOPNOTSUPP;
352bece7b23SSjur Braendeland 	if (flags&MSG_OOB)
353bece7b23SSjur Braendeland 		goto out;
354e6f95ec8SSjur Braendeland 
355bece7b23SSjur Braendeland 	/*
356bece7b23SSjur Braendeland 	 * Lock the socket to prevent queue disordering
357bece7b23SSjur Braendeland 	 * while sleeps in memcpy_tomsg
358bece7b23SSjur Braendeland 	 */
359bece7b23SSjur Braendeland 	err = -EAGAIN;
360bece7b23SSjur Braendeland 	if (sk->sk_state == CAIF_CONNECTING)
361bece7b23SSjur Braendeland 		goto out;
362e6f95ec8SSjur Braendeland 
363bece7b23SSjur Braendeland 	caif_read_lock(sk);
364bece7b23SSjur Braendeland 	target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
365bece7b23SSjur Braendeland 	timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
366e6f95ec8SSjur Braendeland 
367e6f95ec8SSjur Braendeland 	do {
368bece7b23SSjur Braendeland 		int chunk;
369bece7b23SSjur Braendeland 		struct sk_buff *skb;
370e6f95ec8SSjur Braendeland 
371bece7b23SSjur Braendeland 		lock_sock(sk);
372b48732e4SMark Salyzyn 		if (sock_flag(sk, SOCK_DEAD)) {
373b48732e4SMark Salyzyn 			err = -ECONNRESET;
374b48732e4SMark Salyzyn 			goto unlock;
375b48732e4SMark Salyzyn 		}
376bece7b23SSjur Braendeland 		skb = skb_dequeue(&sk->sk_receive_queue);
377bece7b23SSjur Braendeland 		caif_check_flow_release(sk);
378bece7b23SSjur Braendeland 
379bece7b23SSjur Braendeland 		if (skb == NULL) {
380bece7b23SSjur Braendeland 			if (copied >= target)
381bece7b23SSjur Braendeland 				goto unlock;
382bece7b23SSjur Braendeland 			/*
383bece7b23SSjur Braendeland 			 *	POSIX 1003.1g mandates this order.
384bece7b23SSjur Braendeland 			 */
385bece7b23SSjur Braendeland 			err = sock_error(sk);
386bece7b23SSjur Braendeland 			if (err)
387bece7b23SSjur Braendeland 				goto unlock;
388bece7b23SSjur Braendeland 			err = -ECONNRESET;
389bece7b23SSjur Braendeland 			if (sk->sk_shutdown & RCV_SHUTDOWN)
390bece7b23SSjur Braendeland 				goto unlock;
391bece7b23SSjur Braendeland 
392bece7b23SSjur Braendeland 			err = -EPIPE;
393bece7b23SSjur Braendeland 			if (sk->sk_state != CAIF_CONNECTED)
394bece7b23SSjur Braendeland 				goto unlock;
395bece7b23SSjur Braendeland 			if (sock_flag(sk, SOCK_DEAD))
396bece7b23SSjur Braendeland 				goto unlock;
397bece7b23SSjur Braendeland 
398bece7b23SSjur Braendeland 			release_sock(sk);
399bece7b23SSjur Braendeland 
400bece7b23SSjur Braendeland 			err = -EAGAIN;
401bece7b23SSjur Braendeland 			if (!timeo)
402e6f95ec8SSjur Braendeland 				break;
403e6f95ec8SSjur Braendeland 
404bece7b23SSjur Braendeland 			caif_read_unlock(sk);
405bece7b23SSjur Braendeland 
406bece7b23SSjur Braendeland 			timeo = caif_stream_data_wait(sk, timeo);
407bece7b23SSjur Braendeland 
408bece7b23SSjur Braendeland 			if (signal_pending(current)) {
409bece7b23SSjur Braendeland 				err = sock_intr_errno(timeo);
410bece7b23SSjur Braendeland 				goto out;
411bece7b23SSjur Braendeland 			}
412bece7b23SSjur Braendeland 			caif_read_lock(sk);
413bece7b23SSjur Braendeland 			continue;
414bece7b23SSjur Braendeland unlock:
415bece7b23SSjur Braendeland 			release_sock(sk);
416bece7b23SSjur Braendeland 			break;
417bece7b23SSjur Braendeland 		}
418bece7b23SSjur Braendeland 		release_sock(sk);
419bece7b23SSjur Braendeland 		chunk = min_t(unsigned int, skb->len, size);
4207eab8d9eSAl Viro 		if (memcpy_to_msg(msg, skb->data, chunk)) {
421bece7b23SSjur Braendeland 			skb_queue_head(&sk->sk_receive_queue, skb);
422bece7b23SSjur Braendeland 			if (copied == 0)
423bece7b23SSjur Braendeland 				copied = -EFAULT;
424bece7b23SSjur Braendeland 			break;
425bece7b23SSjur Braendeland 		}
426bece7b23SSjur Braendeland 		copied += chunk;
427bece7b23SSjur Braendeland 		size -= chunk;
428bece7b23SSjur Braendeland 
429bece7b23SSjur Braendeland 		/* Mark read part of skb as used */
430bece7b23SSjur Braendeland 		if (!(flags & MSG_PEEK)) {
431bece7b23SSjur Braendeland 			skb_pull(skb, chunk);
432bece7b23SSjur Braendeland 
433bece7b23SSjur Braendeland 			/* put the skb back if we didn't use it up. */
434bece7b23SSjur Braendeland 			if (skb->len) {
435bece7b23SSjur Braendeland 				skb_queue_head(&sk->sk_receive_queue, skb);
436bece7b23SSjur Braendeland 				break;
437bece7b23SSjur Braendeland 			}
438bece7b23SSjur Braendeland 			kfree_skb(skb);
439bece7b23SSjur Braendeland 
440bece7b23SSjur Braendeland 		} else {
441bece7b23SSjur Braendeland 			/*
442bece7b23SSjur Braendeland 			 * It is questionable, see note in unix_dgram_recvmsg.
443bece7b23SSjur Braendeland 			 */
444bece7b23SSjur Braendeland 			/* put message back and return */
445bece7b23SSjur Braendeland 			skb_queue_head(&sk->sk_receive_queue, skb);
446bece7b23SSjur Braendeland 			break;
447bece7b23SSjur Braendeland 		}
448bece7b23SSjur Braendeland 	} while (size);
449bece7b23SSjur Braendeland 	caif_read_unlock(sk);
450bece7b23SSjur Braendeland 
451bece7b23SSjur Braendeland out:
452bece7b23SSjur Braendeland 	return copied ? : err;
453e6f95ec8SSjur Braendeland }
454e6f95ec8SSjur Braendeland 
455bece7b23SSjur Braendeland /*
456bece7b23SSjur Braendeland  * Copied from sock.c:sock_wait_for_wmem, but change to wait for
457bece7b23SSjur Braendeland  * CAIF flow-on and sock_writable.
458bece7b23SSjur Braendeland  */
caif_wait_for_flow_on(struct caifsock * cf_sk,int wait_writeable,long timeo,int * err)459bece7b23SSjur Braendeland static long caif_wait_for_flow_on(struct caifsock *cf_sk,
460bece7b23SSjur Braendeland 				  int wait_writeable, long timeo, int *err)
461bece7b23SSjur Braendeland {
462bece7b23SSjur Braendeland 	struct sock *sk = &cf_sk->sk;
463bece7b23SSjur Braendeland 	DEFINE_WAIT(wait);
464bece7b23SSjur Braendeland 	for (;;) {
465bece7b23SSjur Braendeland 		*err = 0;
466bece7b23SSjur Braendeland 		if (tx_flow_is_on(cf_sk) &&
467bece7b23SSjur Braendeland 			(!wait_writeable || sock_writeable(&cf_sk->sk)))
468bece7b23SSjur Braendeland 			break;
469bece7b23SSjur Braendeland 		*err = -ETIMEDOUT;
470bece7b23SSjur Braendeland 		if (!timeo)
471bece7b23SSjur Braendeland 			break;
472bece7b23SSjur Braendeland 		*err = -ERESTARTSYS;
473bece7b23SSjur Braendeland 		if (signal_pending(current))
474bece7b23SSjur Braendeland 			break;
475bece7b23SSjur Braendeland 		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
476bece7b23SSjur Braendeland 		*err = -ECONNRESET;
477bece7b23SSjur Braendeland 		if (sk->sk_shutdown & SHUTDOWN_MASK)
478bece7b23SSjur Braendeland 			break;
479bece7b23SSjur Braendeland 		*err = -sk->sk_err;
480bece7b23SSjur Braendeland 		if (sk->sk_err)
481bece7b23SSjur Braendeland 			break;
482bece7b23SSjur Braendeland 		*err = -EPIPE;
483bece7b23SSjur Braendeland 		if (cf_sk->sk.sk_state != CAIF_CONNECTED)
484bece7b23SSjur Braendeland 			break;
485bece7b23SSjur Braendeland 		timeo = schedule_timeout(timeo);
486bece7b23SSjur Braendeland 	}
487bece7b23SSjur Braendeland 	finish_wait(sk_sleep(sk), &wait);
488bece7b23SSjur Braendeland 	return timeo;
489e6f95ec8SSjur Braendeland }
490e6f95ec8SSjur Braendeland 
491bece7b23SSjur Braendeland /*
492bece7b23SSjur Braendeland  * Transmit a SKB. The device may temporarily request re-transmission
493bece7b23SSjur Braendeland  * by returning EAGAIN.
494bece7b23SSjur Braendeland  */
transmit_skb(struct sk_buff * skb,struct caifsock * cf_sk,int noblock,long timeo)495bece7b23SSjur Braendeland static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk,
496bece7b23SSjur Braendeland 			int noblock, long timeo)
497bece7b23SSjur Braendeland {
498bece7b23SSjur Braendeland 	struct cfpkt *pkt;
499e6f95ec8SSjur Braendeland 
500bece7b23SSjur Braendeland 	pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb);
5013f874adcSsjur.brandeland@stericsson.com 	memset(skb->cb, 0, sizeof(struct caif_payload_info));
50244764812SDmitry Tarnyagin 	cfpkt_set_prio(pkt, cf_sk->sk.sk_priority);
503bece7b23SSjur Braendeland 
504ba760574SDmitry Tarnyagin 	if (cf_sk->layer.dn == NULL) {
505ba760574SDmitry Tarnyagin 		kfree_skb(skb);
5064dd820c0SSjur Brændeland 		return -EINVAL;
507ba760574SDmitry Tarnyagin 	}
508bece7b23SSjur Braendeland 
5094dd820c0SSjur Brændeland 	return cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt);
510e6f95ec8SSjur Braendeland }
511e6f95ec8SSjur Braendeland 
512bece7b23SSjur Braendeland /* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */
caif_seqpkt_sendmsg(struct socket * sock,struct msghdr * msg,size_t len)5131b784140SYing Xue static int caif_seqpkt_sendmsg(struct socket *sock, struct msghdr *msg,
5141b784140SYing Xue 			       size_t len)
515e6f95ec8SSjur Braendeland {
516e6f95ec8SSjur Braendeland 	struct sock *sk = sock->sk;
517e6f95ec8SSjur Braendeland 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
518bece7b23SSjur Braendeland 	int buffer_size;
519bece7b23SSjur Braendeland 	int ret = 0;
520bece7b23SSjur Braendeland 	struct sk_buff *skb = NULL;
521bece7b23SSjur Braendeland 	int noblock;
522bece7b23SSjur Braendeland 	long timeo;
523bece7b23SSjur Braendeland 	caif_assert(cf_sk);
524bece7b23SSjur Braendeland 	ret = sock_error(sk);
525bece7b23SSjur Braendeland 	if (ret)
526bece7b23SSjur Braendeland 		goto err;
527bece7b23SSjur Braendeland 
528bece7b23SSjur Braendeland 	ret = -EOPNOTSUPP;
529bece7b23SSjur Braendeland 	if (msg->msg_flags&MSG_OOB)
530bece7b23SSjur Braendeland 		goto err;
531bece7b23SSjur Braendeland 
532bece7b23SSjur Braendeland 	ret = -EOPNOTSUPP;
533bece7b23SSjur Braendeland 	if (msg->msg_namelen)
534bece7b23SSjur Braendeland 		goto err;
535bece7b23SSjur Braendeland 
536bece7b23SSjur Braendeland 	noblock = msg->msg_flags & MSG_DONTWAIT;
537bece7b23SSjur Braendeland 
538bece7b23SSjur Braendeland 	timeo = sock_sndtimeo(sk, noblock);
539bece7b23SSjur Braendeland 	timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk),
540bece7b23SSjur Braendeland 				1, timeo, &ret);
541bece7b23SSjur Braendeland 
5422aa40aefSSjur Braendeland 	if (ret)
5432aa40aefSSjur Braendeland 		goto err;
544bece7b23SSjur Braendeland 	ret = -EPIPE;
545bece7b23SSjur Braendeland 	if (cf_sk->sk.sk_state != CAIF_CONNECTED ||
546bece7b23SSjur Braendeland 		sock_flag(sk, SOCK_DEAD) ||
547bece7b23SSjur Braendeland 		(sk->sk_shutdown & RCV_SHUTDOWN))
548bece7b23SSjur Braendeland 		goto err;
549bece7b23SSjur Braendeland 
5502aa40aefSSjur Braendeland 	/* Error if trying to write more than maximum frame size. */
5512aa40aefSSjur Braendeland 	ret = -EMSGSIZE;
5522aa40aefSSjur Braendeland 	if (len > cf_sk->maxframe && cf_sk->sk.sk_protocol != CAIFPROTO_RFM)
5532aa40aefSSjur Braendeland 		goto err;
5542aa40aefSSjur Braendeland 
5552aa40aefSSjur Braendeland 	buffer_size = len + cf_sk->headroom + cf_sk->tailroom;
5562aa40aefSSjur Braendeland 
557bece7b23SSjur Braendeland 	ret = -ENOMEM;
558bece7b23SSjur Braendeland 	skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret);
5592aa40aefSSjur Braendeland 
5602aa40aefSSjur Braendeland 	if (!skb || skb_tailroom(skb) < buffer_size)
561bece7b23SSjur Braendeland 		goto err;
5622aa40aefSSjur Braendeland 
5632aa40aefSSjur Braendeland 	skb_reserve(skb, cf_sk->headroom);
564bece7b23SSjur Braendeland 
5656ce8e9ceSAl Viro 	ret = memcpy_from_msg(skb_put(skb, len), msg, len);
566bece7b23SSjur Braendeland 
567bece7b23SSjur Braendeland 	if (ret)
568bece7b23SSjur Braendeland 		goto err;
569bece7b23SSjur Braendeland 	ret = transmit_skb(skb, cf_sk, noblock, timeo);
570bece7b23SSjur Braendeland 	if (ret < 0)
571c85c2951Ssjur.brandeland@stericsson.com 		/* skb is already freed */
572c85c2951Ssjur.brandeland@stericsson.com 		return ret;
573c85c2951Ssjur.brandeland@stericsson.com 
574bece7b23SSjur Braendeland 	return len;
575bece7b23SSjur Braendeland err:
576bece7b23SSjur Braendeland 	kfree_skb(skb);
577bece7b23SSjur Braendeland 	return ret;
578e6f95ec8SSjur Braendeland }
579e6f95ec8SSjur Braendeland 
580bece7b23SSjur Braendeland /*
581bece7b23SSjur Braendeland  * Copied from unix_stream_sendmsg and adapted to CAIF:
582bece7b23SSjur Braendeland  * Changed removed permission handling and added waiting for flow on
583bece7b23SSjur Braendeland  * and other minor adaptations.
584bece7b23SSjur Braendeland  */
caif_stream_sendmsg(struct socket * sock,struct msghdr * msg,size_t len)5851b784140SYing Xue static int caif_stream_sendmsg(struct socket *sock, struct msghdr *msg,
5861b784140SYing Xue 			       size_t len)
587e6f95ec8SSjur Braendeland {
588bece7b23SSjur Braendeland 	struct sock *sk = sock->sk;
589bece7b23SSjur Braendeland 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
590bece7b23SSjur Braendeland 	int err, size;
591bece7b23SSjur Braendeland 	struct sk_buff *skb;
592bece7b23SSjur Braendeland 	int sent = 0;
593bece7b23SSjur Braendeland 	long timeo;
594e6f95ec8SSjur Braendeland 
595bece7b23SSjur Braendeland 	err = -EOPNOTSUPP;
596bece7b23SSjur Braendeland 	if (unlikely(msg->msg_flags&MSG_OOB))
597bece7b23SSjur Braendeland 		goto out_err;
598e6f95ec8SSjur Braendeland 
599bece7b23SSjur Braendeland 	if (unlikely(msg->msg_namelen))
600bece7b23SSjur Braendeland 		goto out_err;
601e6f95ec8SSjur Braendeland 
602bece7b23SSjur Braendeland 	timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
603bece7b23SSjur Braendeland 	timeo = caif_wait_for_flow_on(cf_sk, 1, timeo, &err);
604bece7b23SSjur Braendeland 
605bece7b23SSjur Braendeland 	if (unlikely(sk->sk_shutdown & SEND_SHUTDOWN))
606bece7b23SSjur Braendeland 		goto pipe_err;
607bece7b23SSjur Braendeland 
608bece7b23SSjur Braendeland 	while (sent < len) {
609bece7b23SSjur Braendeland 
610bece7b23SSjur Braendeland 		size = len-sent;
611bece7b23SSjur Braendeland 
6122aa40aefSSjur Braendeland 		if (size > cf_sk->maxframe)
6132aa40aefSSjur Braendeland 			size = cf_sk->maxframe;
614bece7b23SSjur Braendeland 
615bece7b23SSjur Braendeland 		/* If size is more than half of sndbuf, chop up message */
616bece7b23SSjur Braendeland 		if (size > ((sk->sk_sndbuf >> 1) - 64))
617bece7b23SSjur Braendeland 			size = (sk->sk_sndbuf >> 1) - 64;
618bece7b23SSjur Braendeland 
619bece7b23SSjur Braendeland 		if (size > SKB_MAX_ALLOC)
620bece7b23SSjur Braendeland 			size = SKB_MAX_ALLOC;
621bece7b23SSjur Braendeland 
622bece7b23SSjur Braendeland 		skb = sock_alloc_send_skb(sk,
6232aa40aefSSjur Braendeland 					size + cf_sk->headroom +
6242aa40aefSSjur Braendeland 					cf_sk->tailroom,
625bece7b23SSjur Braendeland 					msg->msg_flags&MSG_DONTWAIT,
626bece7b23SSjur Braendeland 					&err);
627bece7b23SSjur Braendeland 		if (skb == NULL)
628bece7b23SSjur Braendeland 			goto out_err;
629bece7b23SSjur Braendeland 
6302aa40aefSSjur Braendeland 		skb_reserve(skb, cf_sk->headroom);
631bece7b23SSjur Braendeland 		/*
632bece7b23SSjur Braendeland 		 *	If you pass two values to the sock_alloc_send_skb
633bece7b23SSjur Braendeland 		 *	it tries to grab the large buffer with GFP_NOFS
634bece7b23SSjur Braendeland 		 *	(which can fail easily), and if it fails grab the
635bece7b23SSjur Braendeland 		 *	fallback size buffer which is under a page and will
636bece7b23SSjur Braendeland 		 *	succeed. [Alan]
637bece7b23SSjur Braendeland 		 */
638bece7b23SSjur Braendeland 		size = min_t(int, size, skb_tailroom(skb));
639bece7b23SSjur Braendeland 
6406ce8e9ceSAl Viro 		err = memcpy_from_msg(skb_put(skb, size), msg, size);
641bece7b23SSjur Braendeland 		if (err) {
642bece7b23SSjur Braendeland 			kfree_skb(skb);
643bece7b23SSjur Braendeland 			goto out_err;
644bece7b23SSjur Braendeland 		}
645bece7b23SSjur Braendeland 		err = transmit_skb(skb, cf_sk,
646bece7b23SSjur Braendeland 				msg->msg_flags&MSG_DONTWAIT, timeo);
647ba760574SDmitry Tarnyagin 		if (err < 0)
648ba760574SDmitry Tarnyagin 			/* skb is already freed */
649bece7b23SSjur Braendeland 			goto pipe_err;
650ba760574SDmitry Tarnyagin 
651bece7b23SSjur Braendeland 		sent += size;
652bece7b23SSjur Braendeland 	}
653bece7b23SSjur Braendeland 
654bece7b23SSjur Braendeland 	return sent;
655bece7b23SSjur Braendeland 
656bece7b23SSjur Braendeland pipe_err:
657bece7b23SSjur Braendeland 	if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
658bece7b23SSjur Braendeland 		send_sig(SIGPIPE, current, 0);
659bece7b23SSjur Braendeland 	err = -EPIPE;
660bece7b23SSjur Braendeland out_err:
661bece7b23SSjur Braendeland 	return sent ? : err;
662e6f95ec8SSjur Braendeland }
663e6f95ec8SSjur Braendeland 
setsockopt(struct socket * sock,int lvl,int opt,sockptr_t ov,unsigned int ol)664a7b75c5aSChristoph Hellwig static int setsockopt(struct socket *sock, int lvl, int opt, sockptr_t ov,
665a7b75c5aSChristoph Hellwig 		unsigned int ol)
666e6f95ec8SSjur Braendeland {
667e6f95ec8SSjur Braendeland 	struct sock *sk = sock->sk;
668e6f95ec8SSjur Braendeland 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
669f2527ec4SAndré Carvalho de Matos 	int linksel;
670e6f95ec8SSjur Braendeland 
671bece7b23SSjur Braendeland 	if (cf_sk->sk.sk_socket->state != SS_UNCONNECTED)
672e6f95ec8SSjur Braendeland 		return -ENOPROTOOPT;
673bece7b23SSjur Braendeland 
674e6f95ec8SSjur Braendeland 	switch (opt) {
675e6f95ec8SSjur Braendeland 	case CAIFSO_LINK_SELECT:
676bece7b23SSjur Braendeland 		if (ol < sizeof(int))
677e6f95ec8SSjur Braendeland 			return -EINVAL;
678e6f95ec8SSjur Braendeland 		if (lvl != SOL_CAIF)
679e6f95ec8SSjur Braendeland 			goto bad_sol;
680a7b75c5aSChristoph Hellwig 		if (copy_from_sockptr(&linksel, ov, sizeof(int)))
681e6f95ec8SSjur Braendeland 			return -EINVAL;
682e6f95ec8SSjur Braendeland 		lock_sock(&(cf_sk->sk));
683e6f95ec8SSjur Braendeland 		cf_sk->conn_req.link_selector = linksel;
684e6f95ec8SSjur Braendeland 		release_sock(&cf_sk->sk);
685e6f95ec8SSjur Braendeland 		return 0;
686e6f95ec8SSjur Braendeland 
687e6f95ec8SSjur Braendeland 	case CAIFSO_REQ_PARAM:
688e6f95ec8SSjur Braendeland 		if (lvl != SOL_CAIF)
689e6f95ec8SSjur Braendeland 			goto bad_sol;
690e6f95ec8SSjur Braendeland 		if (cf_sk->sk.sk_protocol != CAIFPROTO_UTIL)
691e6f95ec8SSjur Braendeland 			return -ENOPROTOOPT;
692e6f95ec8SSjur Braendeland 		lock_sock(&(cf_sk->sk));
693bece7b23SSjur Braendeland 		if (ol > sizeof(cf_sk->conn_req.param.data) ||
694a7b75c5aSChristoph Hellwig 		    copy_from_sockptr(&cf_sk->conn_req.param.data, ov, ol)) {
695e6f95ec8SSjur Braendeland 			release_sock(&cf_sk->sk);
696e6f95ec8SSjur Braendeland 			return -EINVAL;
697e6f95ec8SSjur Braendeland 		}
69891b5c98cSDan Rosenberg 		cf_sk->conn_req.param.size = ol;
699e6f95ec8SSjur Braendeland 		release_sock(&cf_sk->sk);
700e6f95ec8SSjur Braendeland 		return 0;
701e6f95ec8SSjur Braendeland 
702e6f95ec8SSjur Braendeland 	default:
703bece7b23SSjur Braendeland 		return -ENOPROTOOPT;
704e6f95ec8SSjur Braendeland 	}
705e6f95ec8SSjur Braendeland 
706e6f95ec8SSjur Braendeland 	return 0;
707e6f95ec8SSjur Braendeland bad_sol:
708e6f95ec8SSjur Braendeland 	return -ENOPROTOOPT;
709e6f95ec8SSjur Braendeland 
710e6f95ec8SSjur Braendeland }
711e6f95ec8SSjur Braendeland 
712bece7b23SSjur Braendeland /*
713bece7b23SSjur Braendeland  * caif_connect() - Connect a CAIF Socket
714bece7b23SSjur Braendeland  * Copied and modified af_irda.c:irda_connect().
715bece7b23SSjur Braendeland  *
716bece7b23SSjur Braendeland  * Note : by consulting "errno", the user space caller may learn the cause
717bece7b23SSjur Braendeland  * of the failure. Most of them are visible in the function, others may come
718bece7b23SSjur Braendeland  * from subroutines called and are listed here :
719bece7b23SSjur Braendeland  *  o -EAFNOSUPPORT: bad socket family or type.
720bece7b23SSjur Braendeland  *  o -ESOCKTNOSUPPORT: bad socket type or protocol
721bece7b23SSjur Braendeland  *  o -EINVAL: bad socket address, or CAIF link type
722bece7b23SSjur Braendeland  *  o -ECONNREFUSED: remote end refused the connection.
723bece7b23SSjur Braendeland  *  o -EINPROGRESS: connect request sent but timed out (or non-blocking)
724bece7b23SSjur Braendeland  *  o -EISCONN: already connected.
725bece7b23SSjur Braendeland  *  o -ETIMEDOUT: Connection timed out (send timeout)
726bece7b23SSjur Braendeland  *  o -ENODEV: No link layer to send request
727bece7b23SSjur Braendeland  *  o -ECONNRESET: Received Shutdown indication or lost link layer
728bece7b23SSjur Braendeland  *  o -ENOMEM: Out of memory
729bece7b23SSjur Braendeland  *
730bece7b23SSjur Braendeland  *  State Strategy:
731bece7b23SSjur Braendeland  *  o sk_state: holds the CAIF_* protocol state, it's updated by
732bece7b23SSjur Braendeland  *	caif_ctrl_cb.
733bece7b23SSjur Braendeland  *  o sock->state: holds the SS_* socket state and is updated by connect and
734bece7b23SSjur Braendeland  *	disconnect.
735bece7b23SSjur Braendeland  */
caif_connect(struct socket * sock,struct sockaddr * uaddr,int addr_len,int flags)736bece7b23SSjur Braendeland static int caif_connect(struct socket *sock, struct sockaddr *uaddr,
737bece7b23SSjur Braendeland 			int addr_len, int flags)
738e6f95ec8SSjur Braendeland {
739e6f95ec8SSjur Braendeland 	struct sock *sk = sock->sk;
740bece7b23SSjur Braendeland 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
741bece7b23SSjur Braendeland 	long timeo;
742bece7b23SSjur Braendeland 	int err;
7432aa40aefSSjur Braendeland 	int ifindex, headroom, tailroom;
74479315068SEric Dumazet 	unsigned int mtu;
7452aa40aefSSjur Braendeland 	struct net_device *dev;
7462aa40aefSSjur Braendeland 
747bece7b23SSjur Braendeland 	lock_sock(sk);
748e6f95ec8SSjur Braendeland 
74920a3d5bfSMateusz Jurczyk 	err = -EINVAL;
75020a3d5bfSMateusz Jurczyk 	if (addr_len < offsetofend(struct sockaddr, sa_family))
75120a3d5bfSMateusz Jurczyk 		goto out;
75220a3d5bfSMateusz Jurczyk 
753bece7b23SSjur Braendeland 	err = -EAFNOSUPPORT;
754bece7b23SSjur Braendeland 	if (uaddr->sa_family != AF_CAIF)
755e6f95ec8SSjur Braendeland 		goto out;
756e6f95ec8SSjur Braendeland 
757bece7b23SSjur Braendeland 	switch (sock->state) {
758bece7b23SSjur Braendeland 	case SS_UNCONNECTED:
759bece7b23SSjur Braendeland 		/* Normal case, a fresh connect */
760bece7b23SSjur Braendeland 		caif_assert(sk->sk_state == CAIF_DISCONNECTED);
761bece7b23SSjur Braendeland 		break;
762bece7b23SSjur Braendeland 	case SS_CONNECTING:
763bece7b23SSjur Braendeland 		switch (sk->sk_state) {
764bece7b23SSjur Braendeland 		case CAIF_CONNECTED:
765bece7b23SSjur Braendeland 			sock->state = SS_CONNECTED;
766bece7b23SSjur Braendeland 			err = -EISCONN;
767bece7b23SSjur Braendeland 			goto out;
768bece7b23SSjur Braendeland 		case CAIF_DISCONNECTED:
769bece7b23SSjur Braendeland 			/* Reconnect allowed */
770bece7b23SSjur Braendeland 			break;
771bece7b23SSjur Braendeland 		case CAIF_CONNECTING:
772bece7b23SSjur Braendeland 			err = -EALREADY;
773bece7b23SSjur Braendeland 			if (flags & O_NONBLOCK)
774bece7b23SSjur Braendeland 				goto out;
775bece7b23SSjur Braendeland 			goto wait_connect;
776e6f95ec8SSjur Braendeland 		}
777bece7b23SSjur Braendeland 		break;
778bece7b23SSjur Braendeland 	case SS_CONNECTED:
779bece7b23SSjur Braendeland 		caif_assert(sk->sk_state == CAIF_CONNECTED ||
780bece7b23SSjur Braendeland 				sk->sk_state == CAIF_DISCONNECTED);
781bece7b23SSjur Braendeland 		if (sk->sk_shutdown & SHUTDOWN_MASK) {
782bece7b23SSjur Braendeland 			/* Allow re-connect after SHUTDOWN_IND */
783bee925dbSsjur.brandeland@stericsson.com 			caif_disconnect_client(sock_net(sk), &cf_sk->layer);
78454e90fb5Ssjur.brandeland@stericsson.com 			caif_free_client(&cf_sk->layer);
785bece7b23SSjur Braendeland 			break;
786e6f95ec8SSjur Braendeland 		}
787bece7b23SSjur Braendeland 		/* No reconnect on a seqpacket socket */
788bece7b23SSjur Braendeland 		err = -EISCONN;
789bece7b23SSjur Braendeland 		goto out;
790bece7b23SSjur Braendeland 	case SS_DISCONNECTING:
791bece7b23SSjur Braendeland 	case SS_FREE:
792bece7b23SSjur Braendeland 		caif_assert(1); /*Should never happen */
793bece7b23SSjur Braendeland 		break;
794bece7b23SSjur Braendeland 	}
795bece7b23SSjur Braendeland 	sk->sk_state = CAIF_DISCONNECTED;
796bece7b23SSjur Braendeland 	sock->state = SS_UNCONNECTED;
797bece7b23SSjur Braendeland 	sk_stream_kill_queues(&cf_sk->sk);
798e6f95ec8SSjur Braendeland 
799bece7b23SSjur Braendeland 	err = -EINVAL;
800f5d72af9SDan Carpenter 	if (addr_len != sizeof(struct sockaddr_caif))
801bece7b23SSjur Braendeland 		goto out;
802bece7b23SSjur Braendeland 
803bece7b23SSjur Braendeland 	memcpy(&cf_sk->conn_req.sockaddr, uaddr,
804e6f95ec8SSjur Braendeland 		sizeof(struct sockaddr_caif));
805e6f95ec8SSjur Braendeland 
806bece7b23SSjur Braendeland 	/* Move to connecting socket, start sending Connect Requests */
807bece7b23SSjur Braendeland 	sock->state = SS_CONNECTING;
808bece7b23SSjur Braendeland 	sk->sk_state = CAIF_CONNECTING;
809e6f95ec8SSjur Braendeland 
81033b2f559Ssjur.brandeland@stericsson.com 	/* Check priority value comming from socket */
811f2527ec4SAndré Carvalho de Matos 	/* if priority value is out of range it will be ajusted */
812f2527ec4SAndré Carvalho de Matos 	if (cf_sk->sk.sk_priority > CAIF_PRIO_MAX)
813f2527ec4SAndré Carvalho de Matos 		cf_sk->conn_req.priority = CAIF_PRIO_MAX;
814f2527ec4SAndré Carvalho de Matos 	else if (cf_sk->sk.sk_priority < CAIF_PRIO_MIN)
815f2527ec4SAndré Carvalho de Matos 		cf_sk->conn_req.priority = CAIF_PRIO_MIN;
816f2527ec4SAndré Carvalho de Matos 	else
817f2527ec4SAndré Carvalho de Matos 		cf_sk->conn_req.priority = cf_sk->sk.sk_priority;
818f2527ec4SAndré Carvalho de Matos 
819f2527ec4SAndré Carvalho de Matos 	/*ifindex = id of the interface.*/
820f2527ec4SAndré Carvalho de Matos 	cf_sk->conn_req.ifindex = cf_sk->sk.sk_bound_dev_if;
821f2527ec4SAndré Carvalho de Matos 
822e6f95ec8SSjur Braendeland 	cf_sk->layer.receive = caif_sktrecv_cb;
823b3ccfbe4Ssjur.brandeland@stericsson.com 
824bee925dbSsjur.brandeland@stericsson.com 	err = caif_connect_client(sock_net(sk), &cf_sk->conn_req,
8252aa40aefSSjur Braendeland 				&cf_sk->layer, &ifindex, &headroom, &tailroom);
826b3ccfbe4Ssjur.brandeland@stericsson.com 
827bece7b23SSjur Braendeland 	if (err < 0) {
828bece7b23SSjur Braendeland 		cf_sk->sk.sk_socket->state = SS_UNCONNECTED;
829bece7b23SSjur Braendeland 		cf_sk->sk.sk_state = CAIF_DISCONNECTED;
830bece7b23SSjur Braendeland 		goto out;
831e6f95ec8SSjur Braendeland 	}
83279315068SEric Dumazet 
8332aa40aefSSjur Braendeland 	err = -ENODEV;
83479315068SEric Dumazet 	rcu_read_lock();
83579315068SEric Dumazet 	dev = dev_get_by_index_rcu(sock_net(sk), ifindex);
83679315068SEric Dumazet 	if (!dev) {
83779315068SEric Dumazet 		rcu_read_unlock();
83879315068SEric Dumazet 		goto out;
83979315068SEric Dumazet 	}
8402aa40aefSSjur Braendeland 	cf_sk->headroom = LL_RESERVED_SPACE_EXTRA(dev, headroom);
84179315068SEric Dumazet 	mtu = dev->mtu;
84279315068SEric Dumazet 	rcu_read_unlock();
84379315068SEric Dumazet 
8442aa40aefSSjur Braendeland 	cf_sk->tailroom = tailroom;
84579315068SEric Dumazet 	cf_sk->maxframe = mtu - (headroom + tailroom);
8462aa40aefSSjur Braendeland 	if (cf_sk->maxframe < 1) {
847b31fa5baSJoe Perches 		pr_warn("CAIF Interface MTU too small (%d)\n", dev->mtu);
848f2527ec4SAndré Carvalho de Matos 		err = -ENODEV;
8492aa40aefSSjur Braendeland 		goto out;
8502aa40aefSSjur Braendeland 	}
851e6f95ec8SSjur Braendeland 
852bece7b23SSjur Braendeland 	err = -EINPROGRESS;
853bece7b23SSjur Braendeland wait_connect:
854bece7b23SSjur Braendeland 
855bece7b23SSjur Braendeland 	if (sk->sk_state != CAIF_CONNECTED && (flags & O_NONBLOCK))
856bece7b23SSjur Braendeland 		goto out;
857bece7b23SSjur Braendeland 
858bece7b23SSjur Braendeland 	timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
859bece7b23SSjur Braendeland 
860bece7b23SSjur Braendeland 	release_sock(sk);
8619e4b816bSSjur Braendeland 	err = -ERESTARTSYS;
8629e4b816bSSjur Braendeland 	timeo = wait_event_interruptible_timeout(*sk_sleep(sk),
863bece7b23SSjur Braendeland 			sk->sk_state != CAIF_CONNECTING,
864bece7b23SSjur Braendeland 			timeo);
865bece7b23SSjur Braendeland 	lock_sock(sk);
8669e4b816bSSjur Braendeland 	if (timeo < 0)
867bece7b23SSjur Braendeland 		goto out; /* -ERESTARTSYS */
868e6f95ec8SSjur Braendeland 
8699e4b816bSSjur Braendeland 	err = -ETIMEDOUT;
8709e4b816bSSjur Braendeland 	if (timeo == 0 && sk->sk_state != CAIF_CONNECTED)
8719e4b816bSSjur Braendeland 		goto out;
872bece7b23SSjur Braendeland 	if (sk->sk_state != CAIF_CONNECTED) {
873e6f95ec8SSjur Braendeland 		sock->state = SS_UNCONNECTED;
874bece7b23SSjur Braendeland 		err = sock_error(sk);
875bece7b23SSjur Braendeland 		if (!err)
876bece7b23SSjur Braendeland 			err = -ECONNREFUSED;
877bece7b23SSjur Braendeland 		goto out;
878bece7b23SSjur Braendeland 	}
879bece7b23SSjur Braendeland 	sock->state = SS_CONNECTED;
880bece7b23SSjur Braendeland 	err = 0;
881e6f95ec8SSjur Braendeland out:
882bece7b23SSjur Braendeland 	release_sock(sk);
883bece7b23SSjur Braendeland 	return err;
884e6f95ec8SSjur Braendeland }
885e6f95ec8SSjur Braendeland 
886e6f95ec8SSjur Braendeland /*
887bece7b23SSjur Braendeland  * caif_release() - Disconnect a CAIF Socket
888bece7b23SSjur Braendeland  * Copied and modified af_irda.c:irda_release().
889e6f95ec8SSjur Braendeland  */
caif_release(struct socket * sock)890e6f95ec8SSjur Braendeland static int caif_release(struct socket *sock)
891e6f95ec8SSjur Braendeland {
892e6f95ec8SSjur Braendeland 	struct sock *sk = sock->sk;
893bece7b23SSjur Braendeland 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
894bece7b23SSjur Braendeland 
895bece7b23SSjur Braendeland 	if (!sk)
896bece7b23SSjur Braendeland 		return 0;
897bece7b23SSjur Braendeland 
898bece7b23SSjur Braendeland 	set_tx_flow_off(cf_sk);
899bece7b23SSjur Braendeland 
900bece7b23SSjur Braendeland 	/*
901bece7b23SSjur Braendeland 	 * Ensure that packets are not queued after this point in time.
902bece7b23SSjur Braendeland 	 * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock,
903bece7b23SSjur Braendeland 	 * this ensures no packets when sock is dead.
904bece7b23SSjur Braendeland 	 */
905c85c2951Ssjur.brandeland@stericsson.com 	spin_lock_bh(&sk->sk_receive_queue.lock);
906bece7b23SSjur Braendeland 	sock_set_flag(sk, SOCK_DEAD);
907c85c2951Ssjur.brandeland@stericsson.com 	spin_unlock_bh(&sk->sk_receive_queue.lock);
908bece7b23SSjur Braendeland 	sock->sk = NULL;
909bece7b23SSjur Braendeland 
91033b2f559Ssjur.brandeland@stericsson.com 	WARN_ON(IS_ERR(cf_sk->debugfs_socket_dir));
911e6f95ec8SSjur Braendeland 	debugfs_remove_recursive(cf_sk->debugfs_socket_dir);
912e6f95ec8SSjur Braendeland 
913e6f95ec8SSjur Braendeland 	lock_sock(&(cf_sk->sk));
914bece7b23SSjur Braendeland 	sk->sk_state = CAIF_DISCONNECTED;
915e6f95ec8SSjur Braendeland 	sk->sk_shutdown = SHUTDOWN_MASK;
916e6f95ec8SSjur Braendeland 
91754e90fb5Ssjur.brandeland@stericsson.com 	caif_disconnect_client(sock_net(sk), &cf_sk->layer);
918bece7b23SSjur Braendeland 	cf_sk->sk.sk_socket->state = SS_DISCONNECTING;
919a9a08845SLinus Torvalds 	wake_up_interruptible_poll(sk_sleep(sk), EPOLLERR|EPOLLHUP);
920e6f95ec8SSjur Braendeland 
921bece7b23SSjur Braendeland 	sock_orphan(sk);
922bece7b23SSjur Braendeland 	sk_stream_kill_queues(&cf_sk->sk);
923bece7b23SSjur Braendeland 	release_sock(sk);
924e6f95ec8SSjur Braendeland 	sock_put(sk);
92554e90fb5Ssjur.brandeland@stericsson.com 	return 0;
926e6f95ec8SSjur Braendeland }
927e6f95ec8SSjur Braendeland 
928bece7b23SSjur Braendeland /* Copied from af_unix.c:unix_poll(), added CAIF tx_flow handling */
caif_poll(struct file * file,struct socket * sock,poll_table * wait)929a11e1d43SLinus Torvalds static __poll_t caif_poll(struct file *file,
930a11e1d43SLinus Torvalds 			      struct socket *sock, poll_table *wait)
931bece7b23SSjur Braendeland {
932bece7b23SSjur Braendeland 	struct sock *sk = sock->sk;
933a11e1d43SLinus Torvalds 	__poll_t mask;
934bece7b23SSjur Braendeland 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
935a11e1d43SLinus Torvalds 
93689ab066dSKarsten Graul 	sock_poll_wait(file, sock, wait);
937a11e1d43SLinus Torvalds 	mask = 0;
938bece7b23SSjur Braendeland 
939bece7b23SSjur Braendeland 	/* exceptional events? */
940bece7b23SSjur Braendeland 	if (sk->sk_err)
941a9a08845SLinus Torvalds 		mask |= EPOLLERR;
942bece7b23SSjur Braendeland 	if (sk->sk_shutdown == SHUTDOWN_MASK)
943a9a08845SLinus Torvalds 		mask |= EPOLLHUP;
944bece7b23SSjur Braendeland 	if (sk->sk_shutdown & RCV_SHUTDOWN)
945a9a08845SLinus Torvalds 		mask |= EPOLLRDHUP;
946bece7b23SSjur Braendeland 
947bece7b23SSjur Braendeland 	/* readable? */
9483ef7cf57SEric Dumazet 	if (!skb_queue_empty_lockless(&sk->sk_receive_queue) ||
949bece7b23SSjur Braendeland 		(sk->sk_shutdown & RCV_SHUTDOWN))
950a9a08845SLinus Torvalds 		mask |= EPOLLIN | EPOLLRDNORM;
951bece7b23SSjur Braendeland 
952bece7b23SSjur Braendeland 	/*
953bece7b23SSjur Braendeland 	 * we set writable also when the other side has shut down the
954bece7b23SSjur Braendeland 	 * connection. This prevents stuck sockets.
955bece7b23SSjur Braendeland 	 */
956bece7b23SSjur Braendeland 	if (sock_writeable(sk) && tx_flow_is_on(cf_sk))
957a9a08845SLinus Torvalds 		mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
958bece7b23SSjur Braendeland 
959bece7b23SSjur Braendeland 	return mask;
960bece7b23SSjur Braendeland }
961bece7b23SSjur Braendeland 
962bece7b23SSjur Braendeland static const struct proto_ops caif_seqpacket_ops = {
963e6f95ec8SSjur Braendeland 	.family = PF_CAIF,
964e6f95ec8SSjur Braendeland 	.owner = THIS_MODULE,
965e6f95ec8SSjur Braendeland 	.release = caif_release,
966e6f95ec8SSjur Braendeland 	.bind = sock_no_bind,
967e6f95ec8SSjur Braendeland 	.connect = caif_connect,
968e6f95ec8SSjur Braendeland 	.socketpair = sock_no_socketpair,
969e6f95ec8SSjur Braendeland 	.accept = sock_no_accept,
970e6f95ec8SSjur Braendeland 	.getname = sock_no_getname,
971a11e1d43SLinus Torvalds 	.poll = caif_poll,
972e6f95ec8SSjur Braendeland 	.ioctl = sock_no_ioctl,
973e6f95ec8SSjur Braendeland 	.listen = sock_no_listen,
974bece7b23SSjur Braendeland 	.shutdown = sock_no_shutdown,
975e6f95ec8SSjur Braendeland 	.setsockopt = setsockopt,
976bece7b23SSjur Braendeland 	.sendmsg = caif_seqpkt_sendmsg,
977bece7b23SSjur Braendeland 	.recvmsg = caif_seqpkt_recvmsg,
978e6f95ec8SSjur Braendeland 	.mmap = sock_no_mmap,
979bece7b23SSjur Braendeland };
980bece7b23SSjur Braendeland 
981bece7b23SSjur Braendeland static const struct proto_ops caif_stream_ops = {
982bece7b23SSjur Braendeland 	.family = PF_CAIF,
983bece7b23SSjur Braendeland 	.owner = THIS_MODULE,
984bece7b23SSjur Braendeland 	.release = caif_release,
985bece7b23SSjur Braendeland 	.bind = sock_no_bind,
986bece7b23SSjur Braendeland 	.connect = caif_connect,
987bece7b23SSjur Braendeland 	.socketpair = sock_no_socketpair,
988bece7b23SSjur Braendeland 	.accept = sock_no_accept,
989bece7b23SSjur Braendeland 	.getname = sock_no_getname,
990a11e1d43SLinus Torvalds 	.poll = caif_poll,
991bece7b23SSjur Braendeland 	.ioctl = sock_no_ioctl,
992bece7b23SSjur Braendeland 	.listen = sock_no_listen,
993bece7b23SSjur Braendeland 	.shutdown = sock_no_shutdown,
994bece7b23SSjur Braendeland 	.setsockopt = setsockopt,
995bece7b23SSjur Braendeland 	.sendmsg = caif_stream_sendmsg,
996bece7b23SSjur Braendeland 	.recvmsg = caif_stream_recvmsg,
997bece7b23SSjur Braendeland 	.mmap = sock_no_mmap,
998e6f95ec8SSjur Braendeland };
999e6f95ec8SSjur Braendeland 
1000e6f95ec8SSjur Braendeland /* This function is called when a socket is finally destroyed. */
caif_sock_destructor(struct sock * sk)1001e6f95ec8SSjur Braendeland static void caif_sock_destructor(struct sock *sk)
1002e6f95ec8SSjur Braendeland {
1003bece7b23SSjur Braendeland 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
100414afee4bSReshetova, Elena 	caif_assert(!refcount_read(&sk->sk_wmem_alloc));
1005e6f95ec8SSjur Braendeland 	caif_assert(sk_unhashed(sk));
1006e6f95ec8SSjur Braendeland 	caif_assert(!sk->sk_socket);
1007e6f95ec8SSjur Braendeland 	if (!sock_flag(sk, SOCK_DEAD)) {
100833b2f559Ssjur.brandeland@stericsson.com 		pr_debug("Attempt to release alive CAIF socket: %p\n", sk);
1009e6f95ec8SSjur Braendeland 		return;
1010e6f95ec8SSjur Braendeland 	}
1011bece7b23SSjur Braendeland 	sk_stream_kill_queues(&cf_sk->sk);
1012*62ec33b4SKuniyuki Iwashima 	WARN_ON_ONCE(sk->sk_forward_alloc);
1013b3ccfbe4Ssjur.brandeland@stericsson.com 	caif_free_client(&cf_sk->layer);
1014e6f95ec8SSjur Braendeland }
1015e6f95ec8SSjur Braendeland 
caif_create(struct net * net,struct socket * sock,int protocol,int kern)1016e6f95ec8SSjur Braendeland static int caif_create(struct net *net, struct socket *sock, int protocol,
1017e6f95ec8SSjur Braendeland 		       int kern)
1018e6f95ec8SSjur Braendeland {
1019e6f95ec8SSjur Braendeland 	struct sock *sk = NULL;
1020e6f95ec8SSjur Braendeland 	struct caifsock *cf_sk = NULL;
1021e6f95ec8SSjur Braendeland 	static struct proto prot = {.name = "PF_CAIF",
1022e6f95ec8SSjur Braendeland 		.owner = THIS_MODULE,
1023e6f95ec8SSjur Braendeland 		.obj_size = sizeof(struct caifsock),
102493070d33SDavid Windsor 		.useroffset = offsetof(struct caifsock, conn_req.param),
102593070d33SDavid Windsor 		.usersize = sizeof_field(struct caifsock, conn_req.param)
1026e6f95ec8SSjur Braendeland 	};
1027e6f95ec8SSjur Braendeland 
1028bece7b23SSjur Braendeland 	if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN))
1029bece7b23SSjur Braendeland 		return -EPERM;
1030e6f95ec8SSjur Braendeland 	/*
1031e6f95ec8SSjur Braendeland 	 * The sock->type specifies the socket type to use.
1032bece7b23SSjur Braendeland 	 * The CAIF socket is a packet stream in the sense
1033bece7b23SSjur Braendeland 	 * that it is packet based. CAIF trusts the reliability
1034bece7b23SSjur Braendeland 	 * of the link, no resending is implemented.
1035e6f95ec8SSjur Braendeland 	 */
1036bece7b23SSjur Braendeland 	if (sock->type == SOCK_SEQPACKET)
1037bece7b23SSjur Braendeland 		sock->ops = &caif_seqpacket_ops;
1038bece7b23SSjur Braendeland 	else if (sock->type == SOCK_STREAM)
1039bece7b23SSjur Braendeland 		sock->ops = &caif_stream_ops;
1040bece7b23SSjur Braendeland 	else
1041e6f95ec8SSjur Braendeland 		return -ESOCKTNOSUPPORT;
1042e6f95ec8SSjur Braendeland 
1043e6f95ec8SSjur Braendeland 	if (protocol < 0 || protocol >= CAIFPROTO_MAX)
1044e6f95ec8SSjur Braendeland 		return -EPROTONOSUPPORT;
1045e6f95ec8SSjur Braendeland 	/*
1046bece7b23SSjur Braendeland 	 * Set the socket state to unconnected.	 The socket state
1047bece7b23SSjur Braendeland 	 * is really not used at all in the net/core or socket.c but the
1048e6f95ec8SSjur Braendeland 	 * initialization makes sure that sock->state is not uninitialized.
1049e6f95ec8SSjur Braendeland 	 */
105011aa9c28SEric W. Biederman 	sk = sk_alloc(net, PF_CAIF, GFP_KERNEL, &prot, kern);
1051e6f95ec8SSjur Braendeland 	if (!sk)
1052e6f95ec8SSjur Braendeland 		return -ENOMEM;
1053e6f95ec8SSjur Braendeland 
1054e6f95ec8SSjur Braendeland 	cf_sk = container_of(sk, struct caifsock, sk);
1055e6f95ec8SSjur Braendeland 
1056e6f95ec8SSjur Braendeland 	/* Store the protocol */
1057e6f95ec8SSjur Braendeland 	sk->sk_protocol = (unsigned char) protocol;
1058e6f95ec8SSjur Braendeland 
105944764812SDmitry Tarnyagin 	/* Initialize default priority for well-known cases */
106044764812SDmitry Tarnyagin 	switch (protocol) {
106144764812SDmitry Tarnyagin 	case CAIFPROTO_AT:
106244764812SDmitry Tarnyagin 		sk->sk_priority = TC_PRIO_CONTROL;
106344764812SDmitry Tarnyagin 		break;
106444764812SDmitry Tarnyagin 	case CAIFPROTO_RFM:
106544764812SDmitry Tarnyagin 		sk->sk_priority = TC_PRIO_INTERACTIVE_BULK;
106644764812SDmitry Tarnyagin 		break;
106744764812SDmitry Tarnyagin 	default:
106844764812SDmitry Tarnyagin 		sk->sk_priority = TC_PRIO_BESTEFFORT;
106944764812SDmitry Tarnyagin 	}
107044764812SDmitry Tarnyagin 
1071e6f95ec8SSjur Braendeland 	/*
1072e6f95ec8SSjur Braendeland 	 * Lock in order to try to stop someone from opening the socket
1073e6f95ec8SSjur Braendeland 	 * too early.
1074e6f95ec8SSjur Braendeland 	 */
1075e6f95ec8SSjur Braendeland 	lock_sock(&(cf_sk->sk));
1076e6f95ec8SSjur Braendeland 
1077e6f95ec8SSjur Braendeland 	/* Initialize the nozero default sock structure data. */
1078e6f95ec8SSjur Braendeland 	sock_init_data(sock, sk);
1079e6f95ec8SSjur Braendeland 	sk->sk_destruct = caif_sock_destructor;
1080e6f95ec8SSjur Braendeland 
1081bece7b23SSjur Braendeland 	mutex_init(&cf_sk->readlock); /* single task reading lock */
1082bece7b23SSjur Braendeland 	cf_sk->layer.ctrlcmd = caif_ctrl_cb;
1083bece7b23SSjur Braendeland 	cf_sk->sk.sk_socket->state = SS_UNCONNECTED;
1084bece7b23SSjur Braendeland 	cf_sk->sk.sk_state = CAIF_DISCONNECTED;
1085e6f95ec8SSjur Braendeland 
1086bece7b23SSjur Braendeland 	set_tx_flow_off(cf_sk);
1087bece7b23SSjur Braendeland 	set_rx_flow_on(cf_sk);
1088e6f95ec8SSjur Braendeland 
1089e6f95ec8SSjur Braendeland 	/* Set default options on configuration */
1090bece7b23SSjur Braendeland 	cf_sk->conn_req.link_selector = CAIF_LINK_LOW_LATENCY;
1091e6f95ec8SSjur Braendeland 	cf_sk->conn_req.protocol = protocol;
1092e6f95ec8SSjur Braendeland 	release_sock(&cf_sk->sk);
1093e6f95ec8SSjur Braendeland 	return 0;
1094e6f95ec8SSjur Braendeland }
1095e6f95ec8SSjur Braendeland 
1096bece7b23SSjur Braendeland 
1097173e7837Slinzhang static const struct net_proto_family caif_family_ops = {
1098e6f95ec8SSjur Braendeland 	.family = PF_CAIF,
1099e6f95ec8SSjur Braendeland 	.create = caif_create,
1100e6f95ec8SSjur Braendeland 	.owner = THIS_MODULE,
1101e6f95ec8SSjur Braendeland };
1102e6f95ec8SSjur Braendeland 
caif_sktinit_module(void)11034a695823Ssjur.brandeland@stericsson.com static int __init caif_sktinit_module(void)
1104e6f95ec8SSjur Braendeland {
1105c79e167cSPan Bian 	return sock_register(&caif_family_ops);
1106e6f95ec8SSjur Braendeland }
1107e6f95ec8SSjur Braendeland 
caif_sktexit_module(void)1108e6f95ec8SSjur Braendeland static void __exit caif_sktexit_module(void)
1109e6f95ec8SSjur Braendeland {
1110e6f95ec8SSjur Braendeland 	sock_unregister(PF_CAIF);
1111e6f95ec8SSjur Braendeland }
1112e6f95ec8SSjur Braendeland module_init(caif_sktinit_module);
1113e6f95ec8SSjur Braendeland module_exit(caif_sktexit_module);
1114