1e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland/* 2e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland * Copyright (C) ST-Ericsson AB 2010 326ee65e680f4a2291f6258e11beceae0ad4eeba3sjur.brandeland@stericsson.com * Author: Sjur Brendeland 4e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland * License terms: GNU General Public License (GPL) version 2 5e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland */ 6e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 7b31fa5bad576cd8180a5ad70c648333b44320d44Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ 8b31fa5bad576cd8180a5ad70c648333b44320d44Joe Perches 9e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/fs.h> 10e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/init.h> 11e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/module.h> 12e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/sched.h> 13e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/spinlock.h> 14e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/mutex.h> 15e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/list.h> 16e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/wait.h> 17e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/poll.h> 18e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/tcp.h> 19e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/uaccess.h> 20bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland#include <linux/debugfs.h> 21e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <linux/caif/caif_socket.h> 22447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin#include <linux/pkt_sched.h> 23bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland#include <net/sock.h> 24bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland#include <net/tcp_states.h> 25e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <net/caif/caif_layer.h> 26e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <net/caif/caif_dev.h> 27e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland#include <net/caif/cfpkt.h> 28e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 29e6f95ec8db312491235b4f06343fbd991a82ce20Sjur BraendelandMODULE_LICENSE("GPL"); 30bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur BraendelandMODULE_ALIAS_NETPROTO(AF_CAIF); 31bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 32bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* 33bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * CAIF state is re-using the TCP socket states. 34bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * caif_states stored in sk_state reflect the state as reported by 35bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * the CAIF stack, while sk_socket->state is the state of the socket. 36bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 37bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandenum caif_states { 38bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland CAIF_CONNECTED = TCP_ESTABLISHED, 39bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland CAIF_CONNECTING = TCP_SYN_SENT, 40bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland CAIF_DISCONNECTED = TCP_CLOSE 41bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland}; 42bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 43bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland#define TX_FLOW_ON_BIT 1 44bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland#define RX_FLOW_ON_BIT 2 45e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 46e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendelandstruct caifsock { 47bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct sock sk; /* must be first member */ 48e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct cflayer layer; 49e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland u32 flow_state; 50e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct caif_connect_request conn_req; 51bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct mutex readlock; 52e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct dentry *debugfs_socket_dir; 532aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland int headroom, tailroom, maxframe; 54e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland}; 55e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 56bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic int rx_flow_is_on(struct caifsock *cf_sk) 57bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 58bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return test_bit(RX_FLOW_ON_BIT, 59bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland (void *) &cf_sk->flow_state); 60bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 61bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 62bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic int tx_flow_is_on(struct caifsock *cf_sk) 63bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 64bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return test_bit(TX_FLOW_ON_BIT, 65bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland (void *) &cf_sk->flow_state); 66bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 67e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 68bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic void set_rx_flow_off(struct caifsock *cf_sk) 69e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland{ 70bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland clear_bit(RX_FLOW_ON_BIT, 71bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland (void *) &cf_sk->flow_state); 72bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 73e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 74bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic void set_rx_flow_on(struct caifsock *cf_sk) 75bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 76bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_bit(RX_FLOW_ON_BIT, 77bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland (void *) &cf_sk->flow_state); 78bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 79e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 80bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic void set_tx_flow_off(struct caifsock *cf_sk) 81bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 82bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland clear_bit(TX_FLOW_ON_BIT, 83bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland (void *) &cf_sk->flow_state); 84bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 85e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 86bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic void set_tx_flow_on(struct caifsock *cf_sk) 87bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 88bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_bit(TX_FLOW_ON_BIT, 89bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland (void *) &cf_sk->flow_state); 90bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 91e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 92bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic void caif_read_lock(struct sock *sk) 93bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 94bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk; 95bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk = container_of(sk, struct caifsock, sk); 96bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland mutex_lock(&cf_sk->readlock); 97bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 98e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 99bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic void caif_read_unlock(struct sock *sk) 100bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 101bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk; 102bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk = container_of(sk, struct caifsock, sk); 103bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland mutex_unlock(&cf_sk->readlock); 104bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 105e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 106a9a8f1070d8733b37418b3a2d58df4e771b61f88Sjur Braendelandstatic int sk_rcvbuf_lowwater(struct caifsock *cf_sk) 107bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 108bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* A quarter of full buffer is used a low water mark */ 109bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return cf_sk->sk.sk_rcvbuf / 4; 110bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 111e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 112a9a8f1070d8733b37418b3a2d58df4e771b61f88Sjur Braendelandstatic void caif_flow_ctrl(struct sock *sk, int mode) 113bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 114bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk; 115bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk = container_of(sk, struct caifsock, sk); 116ca6a09f25cde1d2d86f8e821cf69f4f650c30dbfSjur Braendeland if (cf_sk->layer.dn && cf_sk->layer.dn->modemcmd) 117bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, mode); 118bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 119e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 120bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* 121bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are 122bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * not dropped, but CAIF is sending flow off instead. 123bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 124a9a8f1070d8733b37418b3a2d58df4e771b61f88Sjur Braendelandstatic int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) 125bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 126bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int err; 127bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland unsigned long flags; 128bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct sk_buff_head *list = &sk->sk_receive_queue; 129bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); 130e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 131bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= 13295c961747284a6b83a5e2d81240e214b0fa3464dEric Dumazet (unsigned int)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { 133e87cc4728f0e2fb663e592a1141742b1d6c63256Joe Perches net_dbg_ratelimited("sending flow OFF (queue len = %d %d)\n", 134e87cc4728f0e2fb663e592a1141742b1d6c63256Joe Perches atomic_read(&cf_sk->sk.sk_rmem_alloc), 135e87cc4728f0e2fb663e592a1141742b1d6c63256Joe Perches sk_rcvbuf_lowwater(cf_sk)); 136bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_rx_flow_off(cf_sk); 137ca6a09f25cde1d2d86f8e821cf69f4f650c30dbfSjur Braendeland caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); 138bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } 139e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 140bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = sk_filter(sk, skb); 141bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (err) 142bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return err; 143c76562b6709fee5eff8a6a779be41c0bce661fd7Mel Gorman if (!sk_rmem_schedule(sk, skb, skb->truesize) && rx_flow_is_on(cf_sk)) { 144bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_rx_flow_off(cf_sk); 145e87cc4728f0e2fb663e592a1141742b1d6c63256Joe Perches net_dbg_ratelimited("sending flow OFF due to rmem_schedule\n"); 146ca6a09f25cde1d2d86f8e821cf69f4f650c30dbfSjur Braendeland caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); 147bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } 148bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb->dev = NULL; 149bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb_set_owner_r(skb, sk); 150bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* Cache the SKB length before we tack it onto the receive 151bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * queue. Once it is added it no longer belongs to us and 152bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * may be freed by other threads of control pulling packets 153bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * from the queue. 154bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 155bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland spin_lock_irqsave(&list->lock, flags); 156bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (!sock_flag(sk, SOCK_DEAD)) 157bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland __skb_queue_tail(list, skb); 158bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland spin_unlock_irqrestore(&list->lock, flags); 159bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 160bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (!sock_flag(sk, SOCK_DEAD)) 161676d23690fb62b5d51ba5d659935e9f7d9da9f8eDavid S. Miller sk->sk_data_ready(sk); 162bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland else 163bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland kfree_skb(skb); 164e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return 0; 165e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland} 166e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 167bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* Packet Receive Callback function called from CAIF Stack */ 168bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt) 169e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland{ 170e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct caifsock *cf_sk; 171bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct sk_buff *skb; 172e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 173e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland cf_sk = container_of(layr, struct caifsock, layer); 174bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb = cfpkt_tonative(pkt); 175bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 176bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (unlikely(cf_sk->sk.sk_state != CAIF_CONNECTED)) { 1773f874adc4ae80828b79e8aac6891c108c1f6be6dsjur.brandeland@stericsson.com kfree_skb(skb); 178bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return 0; 179bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } 180bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland caif_queue_rcv_skb(&cf_sk->sk, skb); 181bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return 0; 182bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 183e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 184b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.comstatic void cfsk_hold(struct cflayer *layr) 185b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com{ 186b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); 187b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com sock_hold(&cf_sk->sk); 188b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com} 189b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com 190b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.comstatic void cfsk_put(struct cflayer *layr) 191b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com{ 192b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); 193b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com sock_put(&cf_sk->sk); 194b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com} 195b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com 196bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* Packet Control Callback function called from CAIF */ 197bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic void caif_ctrl_cb(struct cflayer *layr, 1983bffc475f9995843fa23a4978a4c112d8c8f4a6eSilviu-Mihai Popescu enum caif_ctrlcmd flow, 1993bffc475f9995843fa23a4978a4c112d8c8f4a6eSilviu-Mihai Popescu int phyid) 200bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 201bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); 202e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland switch (flow) { 203e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland case CAIF_CTRLCMD_FLOW_ON_IND: 204bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* OK from modem to start sending again */ 205bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_tx_flow_on(cf_sk); 206bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_state_change(&cf_sk->sk); 207e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland break; 208e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 209e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland case CAIF_CTRLCMD_FLOW_OFF_IND: 210bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* Modem asks us to shut up */ 211bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_tx_flow_off(cf_sk); 212bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_state_change(&cf_sk->sk); 213e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland break; 214e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 215e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland case CAIF_CTRLCMD_INIT_RSP: 216bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* We're now connected */ 217b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com caif_client_register_refcnt(&cf_sk->layer, 218b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com cfsk_hold, cfsk_put); 219bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_state = CAIF_CONNECTED; 220bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_tx_flow_on(cf_sk); 221eaa8c5f3cf6555294632c176e81439ca420ad07fSjur Brændeland cf_sk->sk.sk_shutdown = 0; 222bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_state_change(&cf_sk->sk); 223e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland break; 224e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 225e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland case CAIF_CTRLCMD_DEINIT_RSP: 226bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* We're now disconnected */ 227bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_state = CAIF_DISCONNECTED; 228bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_state_change(&cf_sk->sk); 229e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland break; 230e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 231e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland case CAIF_CTRLCMD_INIT_FAIL_RSP: 232bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* Connect request failed */ 233bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_err = ECONNREFUSED; 234bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_state = CAIF_DISCONNECTED; 235bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_shutdown = SHUTDOWN_MASK; 236bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* 237bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Socket "standards" seems to require POLLOUT to 238bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * be set at connect failure. 239bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 240bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_tx_flow_on(cf_sk); 241bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_state_change(&cf_sk->sk); 242e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland break; 243e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 244e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: 245bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* Modem has closed this connection, or device is down. */ 246bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_shutdown = SHUTDOWN_MASK; 247bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_err = ECONNRESET; 248bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_rx_flow_on(cf_sk); 249bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_error_report(&cf_sk->sk); 250e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland break; 251e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 252e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland default: 253b31fa5bad576cd8180a5ad70c648333b44320d44Joe Perches pr_debug("Unexpected flow command %d\n", flow); 254e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 255e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland} 256e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 257bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic void caif_check_flow_release(struct sock *sk) 258e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland{ 259bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); 260e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 261bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (rx_flow_is_on(cf_sk)) 262bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return; 263e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 264bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (atomic_read(&sk->sk_rmem_alloc) <= sk_rcvbuf_lowwater(cf_sk)) { 265bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_rx_flow_on(cf_sk); 266ca6a09f25cde1d2d86f8e821cf69f4f650c30dbfSjur Braendeland caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_ON_REQ); 267bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } 268bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 269dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland 270bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* 271dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland * Copied from unix_dgram_recvmsg, but removed credit checks, 272dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland * changed locking, address handling and added MSG_TRUNC. 273bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 274bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, 2753bffc475f9995843fa23a4978a4c112d8c8f4a6eSilviu-Mihai Popescu struct msghdr *m, size_t len, int flags) 276e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 277e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland{ 278e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct sock *sk = sock->sk; 279e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct sk_buff *skb; 280dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland int ret; 281dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland int copylen; 282e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 283dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland ret = -EOPNOTSUPP; 284dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland if (m->msg_flags&MSG_OOB) 285dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland goto read_error; 286e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 287bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb = skb_recv_datagram(sk, flags, 0 , &ret); 288bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (!skb) 289e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland goto read_error; 290dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland copylen = skb->len; 291dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland if (len < copylen) { 292dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland m->msg_flags |= MSG_TRUNC; 293dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland copylen = len; 294e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 295e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 296dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland ret = skb_copy_datagram_iovec(skb, 0, m->msg_iov, copylen); 297bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (ret) 298dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland goto out_free; 299e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 300dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland ret = (flags & MSG_TRUNC) ? skb->len : copylen; 301dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendelandout_free: 302bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb_free_datagram(sk, skb); 303bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland caif_check_flow_release(sk); 304dcda138d2f27e32bd0d6250cc42839b0d70bb4b8Sjur Braendeland return ret; 305e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 306bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandread_error: 307bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return ret; 308bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 309e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 310e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 311bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* Copied from unix_stream_wait_data, identical except for lock call. */ 312bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic long caif_stream_data_wait(struct sock *sk, long timeo) 313bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 314bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland DEFINE_WAIT(wait); 315bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland lock_sock(sk); 316bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 317bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland for (;;) { 318bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 319bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 320bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (!skb_queue_empty(&sk->sk_receive_queue) || 321bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sk->sk_err || 322bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sk->sk_state != CAIF_CONNECTED || 323bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock_flag(sk, SOCK_DEAD) || 324bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland (sk->sk_shutdown & RCV_SHUTDOWN) || 325bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland signal_pending(current) || 326bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland !timeo) 327bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 328e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 329bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); 330bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland release_sock(sk); 331bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland timeo = schedule_timeout(timeo); 332bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland lock_sock(sk); 333727a5cbb8c0baf4719913d7af423e38f406f209eMark Salyzyn 334727a5cbb8c0baf4719913d7af423e38f406f209eMark Salyzyn if (sock_flag(sk, SOCK_DEAD)) 335727a5cbb8c0baf4719913d7af423e38f406f209eMark Salyzyn break; 336727a5cbb8c0baf4719913d7af423e38f406f209eMark Salyzyn 337bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); 338e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 339e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 340bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland finish_wait(sk_sleep(sk), &wait); 341bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland release_sock(sk); 342bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return timeo; 343bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 344e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 345e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 346bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* 347bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Copied from unix_stream_recvmsg, but removed credit checks, 348bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * changed locking calls, changed address handling. 349bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 350bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock, 3513bffc475f9995843fa23a4978a4c112d8c8f4a6eSilviu-Mihai Popescu struct msghdr *msg, size_t size, 3523bffc475f9995843fa23a4978a4c112d8c8f4a6eSilviu-Mihai Popescu int flags) 353bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 354bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct sock *sk = sock->sk; 355bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int copied = 0; 356bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int target; 357bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int err = 0; 358bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland long timeo; 359e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 360bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EOPNOTSUPP; 361bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (flags&MSG_OOB) 362bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out; 363e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 364bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* 365bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Lock the socket to prevent queue disordering 366bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * while sleeps in memcpy_tomsg 367bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 368bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EAGAIN; 369bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sk->sk_state == CAIF_CONNECTING) 370bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out; 371e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 372bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland caif_read_lock(sk); 373bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); 374bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT); 375e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 376bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland do { 377bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int chunk; 378bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct sk_buff *skb; 379e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 380bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland lock_sock(sk); 381727a5cbb8c0baf4719913d7af423e38f406f209eMark Salyzyn if (sock_flag(sk, SOCK_DEAD)) { 382727a5cbb8c0baf4719913d7af423e38f406f209eMark Salyzyn err = -ECONNRESET; 383727a5cbb8c0baf4719913d7af423e38f406f209eMark Salyzyn goto unlock; 384727a5cbb8c0baf4719913d7af423e38f406f209eMark Salyzyn } 385bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb = skb_dequeue(&sk->sk_receive_queue); 386bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland caif_check_flow_release(sk); 387e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 388bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (skb == NULL) { 389bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (copied >= target) 390bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto unlock; 391bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* 392bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * POSIX 1003.1g mandates this order. 393bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 394bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = sock_error(sk); 395bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (err) 396bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto unlock; 397bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -ECONNRESET; 398bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sk->sk_shutdown & RCV_SHUTDOWN) 399bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto unlock; 400e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 401bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EPIPE; 402bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sk->sk_state != CAIF_CONNECTED) 403bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto unlock; 404bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sock_flag(sk, SOCK_DEAD)) 405bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto unlock; 406e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 407bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland release_sock(sk); 408e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 409bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EAGAIN; 410bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (!timeo) 411bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 412e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 413bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland caif_read_unlock(sk); 414e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 415bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland timeo = caif_stream_data_wait(sk, timeo); 416e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 417bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (signal_pending(current)) { 418bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = sock_intr_errno(timeo); 419bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out; 420bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } 421bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland caif_read_lock(sk); 422bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland continue; 423bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandunlock: 424bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland release_sock(sk); 425bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 426e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 427bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland release_sock(sk); 428bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland chunk = min_t(unsigned int, skb->len, size); 429bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { 430bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb_queue_head(&sk->sk_receive_queue, skb); 431bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (copied == 0) 432bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland copied = -EFAULT; 433bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 434bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } 435bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland copied += chunk; 436bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland size -= chunk; 437e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 438bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* Mark read part of skb as used */ 439bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (!(flags & MSG_PEEK)) { 440bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb_pull(skb, chunk); 441e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 442bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* put the skb back if we didn't use it up. */ 443bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (skb->len) { 444bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb_queue_head(&sk->sk_receive_queue, skb); 445bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 446bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } 447bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland kfree_skb(skb); 448e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 449e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } else { 450bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* 451bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * It is questionable, see note in unix_dgram_recvmsg. 452bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 453bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* put message back and return */ 454bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb_queue_head(&sk->sk_receive_queue, skb); 455bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 456e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 457bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } while (size); 458bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland caif_read_unlock(sk); 459e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 460bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandout: 461bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return copied ? : err; 462bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 463e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 464bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* 465bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Copied from sock.c:sock_wait_for_wmem, but change to wait for 466bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * CAIF flow-on and sock_writable. 467bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 468bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic long caif_wait_for_flow_on(struct caifsock *cf_sk, 4693bffc475f9995843fa23a4978a4c112d8c8f4a6eSilviu-Mihai Popescu int wait_writeable, long timeo, int *err) 470bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 471bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct sock *sk = &cf_sk->sk; 472bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland DEFINE_WAIT(wait); 473bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland for (;;) { 474bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland *err = 0; 475bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (tx_flow_is_on(cf_sk) && 476bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland (!wait_writeable || sock_writeable(&cf_sk->sk))) 477bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 478bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland *err = -ETIMEDOUT; 479bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (!timeo) 480bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 481bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland *err = -ERESTARTSYS; 482bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (signal_pending(current)) 483bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 484bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 485bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland *err = -ECONNRESET; 486bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sk->sk_shutdown & SHUTDOWN_MASK) 487bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 488bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland *err = -sk->sk_err; 489bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sk->sk_err) 490bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 491bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland *err = -EPIPE; 492bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (cf_sk->sk.sk_state != CAIF_CONNECTED) 493bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 494bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland timeo = schedule_timeout(timeo); 495e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 496bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland finish_wait(sk_sleep(sk), &wait); 497bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return timeo; 498bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 499e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 500bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* 501bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Transmit a SKB. The device may temporarily request re-transmission 502bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * by returning EAGAIN. 503bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 504bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk, 505bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int noblock, long timeo) 506bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 507bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct cfpkt *pkt; 508e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 509bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb); 5103f874adc4ae80828b79e8aac6891c108c1f6be6dsjur.brandeland@stericsson.com memset(skb->cb, 0, sizeof(struct caif_payload_info)); 511447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin cfpkt_set_prio(pkt, cf_sk->sk.sk_priority); 512e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 513ba7605745d5c99f0e71b3ec6c7cb5ed6afe540adDmitry Tarnyagin if (cf_sk->layer.dn == NULL) { 514ba7605745d5c99f0e71b3ec6c7cb5ed6afe540adDmitry Tarnyagin kfree_skb(skb); 5154dd820c088d201e526840c9dbc2f0b87a0a41868Sjur Brændeland return -EINVAL; 516ba7605745d5c99f0e71b3ec6c7cb5ed6afe540adDmitry Tarnyagin } 517e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 5184dd820c088d201e526840c9dbc2f0b87a0a41868Sjur Brændeland return cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt); 519bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 520e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 521bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */ 522bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock, 5233bffc475f9995843fa23a4978a4c112d8c8f4a6eSilviu-Mihai Popescu struct msghdr *msg, size_t len) 524bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 525bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct sock *sk = sock->sk; 526bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); 527bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int buffer_size; 528bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int ret = 0; 529bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct sk_buff *skb = NULL; 530bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int noblock; 531bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland long timeo; 532bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland caif_assert(cf_sk); 533bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland ret = sock_error(sk); 534bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (ret) 535bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto err; 536bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 537bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland ret = -EOPNOTSUPP; 538bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (msg->msg_flags&MSG_OOB) 539bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto err; 540bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 541bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland ret = -EOPNOTSUPP; 542bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (msg->msg_namelen) 543bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto err; 544bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 545bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland ret = -EINVAL; 546bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (unlikely(msg->msg_iov->iov_base == NULL)) 547bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto err; 548bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland noblock = msg->msg_flags & MSG_DONTWAIT; 549bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 550bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland timeo = sock_sndtimeo(sk, noblock); 551bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk), 552bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 1, timeo, &ret); 553bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 5542aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland if (ret) 5552aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland goto err; 556bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland ret = -EPIPE; 557bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (cf_sk->sk.sk_state != CAIF_CONNECTED || 558bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock_flag(sk, SOCK_DEAD) || 559bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland (sk->sk_shutdown & RCV_SHUTDOWN)) 560bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto err; 561bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 5622aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland /* Error if trying to write more than maximum frame size. */ 5632aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland ret = -EMSGSIZE; 5642aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland if (len > cf_sk->maxframe && cf_sk->sk.sk_protocol != CAIFPROTO_RFM) 5652aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland goto err; 5662aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland 5672aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland buffer_size = len + cf_sk->headroom + cf_sk->tailroom; 5682aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland 569bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland ret = -ENOMEM; 570bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret); 5712aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland 5722aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland if (!skb || skb_tailroom(skb) < buffer_size) 573bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto err; 5742aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland 5752aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland skb_reserve(skb, cf_sk->headroom); 576bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 577bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland ret = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); 578bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 579bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (ret) 580bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto err; 581bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland ret = transmit_skb(skb, cf_sk, noblock, timeo); 582bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (ret < 0) 583c85c2951d4da1236e32f1858db418221e624aba5sjur.brandeland@stericsson.com /* skb is already freed */ 584c85c2951d4da1236e32f1858db418221e624aba5sjur.brandeland@stericsson.com return ret; 585c85c2951d4da1236e32f1858db418221e624aba5sjur.brandeland@stericsson.com 586bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return len; 587bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelanderr: 588bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland kfree_skb(skb); 589bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return ret; 590bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 591e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 592bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* 593bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Copied from unix_stream_sendmsg and adapted to CAIF: 594bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Changed removed permission handling and added waiting for flow on 595bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * and other minor adaptations. 596bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 597bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, 5983bffc475f9995843fa23a4978a4c112d8c8f4a6eSilviu-Mihai Popescu struct msghdr *msg, size_t len) 599bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 600bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct sock *sk = sock->sk; 601bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); 602bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int err, size; 603bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct sk_buff *skb; 604bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int sent = 0; 605bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland long timeo; 606e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 607bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EOPNOTSUPP; 608bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (unlikely(msg->msg_flags&MSG_OOB)) 609bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out_err; 610e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 611bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (unlikely(msg->msg_namelen)) 612bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out_err; 613e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 614bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); 615bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland timeo = caif_wait_for_flow_on(cf_sk, 1, timeo, &err); 616e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 617bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (unlikely(sk->sk_shutdown & SEND_SHUTDOWN)) 618bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto pipe_err; 619e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 620bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland while (sent < len) { 621e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 622bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland size = len-sent; 623e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 6242aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland if (size > cf_sk->maxframe) 6252aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland size = cf_sk->maxframe; 626e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 627bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* If size is more than half of sndbuf, chop up message */ 628bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (size > ((sk->sk_sndbuf >> 1) - 64)) 629bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland size = (sk->sk_sndbuf >> 1) - 64; 630e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 631bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (size > SKB_MAX_ALLOC) 632bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland size = SKB_MAX_ALLOC; 633e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 634bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland skb = sock_alloc_send_skb(sk, 6352aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland size + cf_sk->headroom + 6362aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland cf_sk->tailroom, 637bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland msg->msg_flags&MSG_DONTWAIT, 638bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland &err); 639bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (skb == NULL) 640bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out_err; 641e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 6422aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland skb_reserve(skb, cf_sk->headroom); 643bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* 644bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * If you pass two values to the sock_alloc_send_skb 645bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * it tries to grab the large buffer with GFP_NOFS 646bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * (which can fail easily), and if it fails grab the 647bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * fallback size buffer which is under a page and will 648bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * succeed. [Alan] 649bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 650bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland size = min_t(int, size, skb_tailroom(skb)); 651e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 652bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); 653bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (err) { 654bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland kfree_skb(skb); 655bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out_err; 656bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } 657bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = transmit_skb(skb, cf_sk, 658bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland msg->msg_flags&MSG_DONTWAIT, timeo); 659ba7605745d5c99f0e71b3ec6c7cb5ed6afe540adDmitry Tarnyagin if (err < 0) 660ba7605745d5c99f0e71b3ec6c7cb5ed6afe540adDmitry Tarnyagin /* skb is already freed */ 661bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto pipe_err; 662ba7605745d5c99f0e71b3ec6c7cb5ed6afe540adDmitry Tarnyagin 663bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sent += size; 664e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 665e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 666bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return sent; 667e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 668bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandpipe_err: 669bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL)) 670bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland send_sig(SIGPIPE, current, 0); 671bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EPIPE; 672bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandout_err: 673bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return sent ? : err; 674e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland} 675e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 676e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendelandstatic int setsockopt(struct socket *sock, 6773bffc475f9995843fa23a4978a4c112d8c8f4a6eSilviu-Mihai Popescu int lvl, int opt, char __user *ov, unsigned int ol) 678e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland{ 679e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct sock *sk = sock->sk; 680e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); 681f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos int linksel; 682e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 683bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (cf_sk->sk.sk_socket->state != SS_UNCONNECTED) 684e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return -ENOPROTOOPT; 685bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 686e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland switch (opt) { 687e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland case CAIFSO_LINK_SELECT: 688bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (ol < sizeof(int)) 689e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return -EINVAL; 690e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland if (lvl != SOL_CAIF) 691e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland goto bad_sol; 692e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland if (copy_from_user(&linksel, ov, sizeof(int))) 693e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return -EINVAL; 694e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland lock_sock(&(cf_sk->sk)); 695e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland cf_sk->conn_req.link_selector = linksel; 696e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland release_sock(&cf_sk->sk); 697e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return 0; 698e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 699e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland case CAIFSO_REQ_PARAM: 700e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland if (lvl != SOL_CAIF) 701e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland goto bad_sol; 702e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland if (cf_sk->sk.sk_protocol != CAIFPROTO_UTIL) 703e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return -ENOPROTOOPT; 704e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland lock_sock(&(cf_sk->sk)); 705bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (ol > sizeof(cf_sk->conn_req.param.data) || 706bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland copy_from_user(&cf_sk->conn_req.param.data, ov, ol)) { 707e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland release_sock(&cf_sk->sk); 708e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return -EINVAL; 709e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 71091b5c98c2e062f982423686c77b8bf31f37fa196Dan Rosenberg cf_sk->conn_req.param.size = ol; 711e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland release_sock(&cf_sk->sk); 712e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return 0; 713e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 714e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland default: 715bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return -ENOPROTOOPT; 716e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 717e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 718e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return 0; 719e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendelandbad_sol: 720e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return -ENOPROTOOPT; 721e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 722e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland} 723e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 724bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* 725bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * caif_connect() - Connect a CAIF Socket 726bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Copied and modified af_irda.c:irda_connect(). 727bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * 728bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Note : by consulting "errno", the user space caller may learn the cause 729bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * of the failure. Most of them are visible in the function, others may come 730bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * from subroutines called and are listed here : 731bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o -EAFNOSUPPORT: bad socket family or type. 732bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o -ESOCKTNOSUPPORT: bad socket type or protocol 733bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o -EINVAL: bad socket address, or CAIF link type 734bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o -ECONNREFUSED: remote end refused the connection. 735bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o -EINPROGRESS: connect request sent but timed out (or non-blocking) 736bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o -EISCONN: already connected. 737bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o -ETIMEDOUT: Connection timed out (send timeout) 738bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o -ENODEV: No link layer to send request 739bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o -ECONNRESET: Received Shutdown indication or lost link layer 740bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o -ENOMEM: Out of memory 741bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * 742bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * State Strategy: 743bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o sk_state: holds the CAIF_* protocol state, it's updated by 744bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * caif_ctrl_cb. 745bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * o sock->state: holds the SS_* socket state and is updated by connect and 746bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * disconnect. 747bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 748bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic int caif_connect(struct socket *sock, struct sockaddr *uaddr, 749bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int addr_len, int flags) 750e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland{ 751e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct sock *sk = sock->sk; 752bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); 753bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland long timeo; 754bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int err; 7552aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland int ifindex, headroom, tailroom; 75679315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet unsigned int mtu; 7572aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland struct net_device *dev; 7582aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland 759bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland lock_sock(sk); 760e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 761bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EAFNOSUPPORT; 762bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (uaddr->sa_family != AF_CAIF) 763e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland goto out; 764e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 765bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland switch (sock->state) { 766bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland case SS_UNCONNECTED: 767bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* Normal case, a fresh connect */ 768bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland caif_assert(sk->sk_state == CAIF_DISCONNECTED); 769bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 770bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland case SS_CONNECTING: 771bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland switch (sk->sk_state) { 772bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland case CAIF_CONNECTED: 773bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock->state = SS_CONNECTED; 774bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EISCONN; 775bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out; 776bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland case CAIF_DISCONNECTED: 777bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* Reconnect allowed */ 778bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 779bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland case CAIF_CONNECTING: 780bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EALREADY; 781bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (flags & O_NONBLOCK) 782bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out; 783bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto wait_connect; 784bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } 785bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 786bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland case SS_CONNECTED: 787bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland caif_assert(sk->sk_state == CAIF_CONNECTED || 788bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sk->sk_state == CAIF_DISCONNECTED); 789bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sk->sk_shutdown & SHUTDOWN_MASK) { 790bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* Allow re-connect after SHUTDOWN_IND */ 791bee925db9a77a5736596dcf6f91d0879f5ee915bsjur.brandeland@stericsson.com caif_disconnect_client(sock_net(sk), &cf_sk->layer); 79254e90fb5ca8050156d3e748ddc690ed6ea9d71acsjur.brandeland@stericsson.com caif_free_client(&cf_sk->layer); 793bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 794bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } 795bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* No reconnect on a seqpacket socket */ 796bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EISCONN; 797bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out; 798bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland case SS_DISCONNECTING: 799bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland case SS_FREE: 800bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland caif_assert(1); /*Should never happen */ 801bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland break; 802e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 803bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sk->sk_state = CAIF_DISCONNECTED; 804bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock->state = SS_UNCONNECTED; 805bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sk_stream_kill_queues(&cf_sk->sk); 806e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 807bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EINVAL; 808f5d72af9f3dfea67f014f880d00665f96622f57fDan Carpenter if (addr_len != sizeof(struct sockaddr_caif)) 809bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out; 810e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 811bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland memcpy(&cf_sk->conn_req.sockaddr, uaddr, 812e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland sizeof(struct sockaddr_caif)); 813e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 814bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* Move to connecting socket, start sending Connect Requests */ 815bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock->state = SS_CONNECTING; 816bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sk->sk_state = CAIF_CONNECTING; 817bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 81833b2f5598b4ee68021364a7b795c09ad66bc0aa8sjur.brandeland@stericsson.com /* Check priority value comming from socket */ 819f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos /* if priority value is out of range it will be ajusted */ 820f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos if (cf_sk->sk.sk_priority > CAIF_PRIO_MAX) 821f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos cf_sk->conn_req.priority = CAIF_PRIO_MAX; 822f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos else if (cf_sk->sk.sk_priority < CAIF_PRIO_MIN) 823f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos cf_sk->conn_req.priority = CAIF_PRIO_MIN; 824f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos else 825f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos cf_sk->conn_req.priority = cf_sk->sk.sk_priority; 826f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos 827f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos /*ifindex = id of the interface.*/ 828f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos cf_sk->conn_req.ifindex = cf_sk->sk.sk_bound_dev_if; 829f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos 830bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->layer.receive = caif_sktrecv_cb; 831b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com 832bee925db9a77a5736596dcf6f91d0879f5ee915bsjur.brandeland@stericsson.com err = caif_connect_client(sock_net(sk), &cf_sk->conn_req, 8332aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland &cf_sk->layer, &ifindex, &headroom, &tailroom); 834b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com 835bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (err < 0) { 836bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_socket->state = SS_UNCONNECTED; 837bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_state = CAIF_DISCONNECTED; 838bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out; 839e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 84079315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet 84179315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet err = -ENODEV; 84279315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet rcu_read_lock(); 84379315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet dev = dev_get_by_index_rcu(sock_net(sk), ifindex); 84479315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet if (!dev) { 84579315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet rcu_read_unlock(); 84679315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet goto out; 84779315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet } 8482aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland cf_sk->headroom = LL_RESERVED_SPACE_EXTRA(dev, headroom); 84979315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet mtu = dev->mtu; 85079315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet rcu_read_unlock(); 85179315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet 8522aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland cf_sk->tailroom = tailroom; 85379315068f4560f3f7bd6e9790190dcb43059770cEric Dumazet cf_sk->maxframe = mtu - (headroom + tailroom); 8542aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland if (cf_sk->maxframe < 1) { 855b31fa5bad576cd8180a5ad70c648333b44320d44Joe Perches pr_warn("CAIF Interface MTU too small (%d)\n", dev->mtu); 856f2527ec436fd675f08a8e7434f6e940688cb96d0André Carvalho de Matos err = -ENODEV; 8572aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland goto out; 8582aa40aef9debc77d55cc87a50d335b6fe97fbeb0Sjur Braendeland } 859e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 860bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -EINPROGRESS; 861bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandwait_connect: 862e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 863bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sk->sk_state != CAIF_CONNECTED && (flags & O_NONBLOCK)) 864bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out; 865e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 866bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); 867bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 868bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland release_sock(sk); 8699e4b816bc31962ebbb8784d602acd5fa25a08ad8Sjur Braendeland err = -ERESTARTSYS; 8709e4b816bc31962ebbb8784d602acd5fa25a08ad8Sjur Braendeland timeo = wait_event_interruptible_timeout(*sk_sleep(sk), 871bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sk->sk_state != CAIF_CONNECTING, 872bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland timeo); 873bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland lock_sock(sk); 8749e4b816bc31962ebbb8784d602acd5fa25a08ad8Sjur Braendeland if (timeo < 0) 875bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out; /* -ERESTARTSYS */ 876e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 8779e4b816bc31962ebbb8784d602acd5fa25a08ad8Sjur Braendeland err = -ETIMEDOUT; 8789e4b816bc31962ebbb8784d602acd5fa25a08ad8Sjur Braendeland if (timeo == 0 && sk->sk_state != CAIF_CONNECTED) 8799e4b816bc31962ebbb8784d602acd5fa25a08ad8Sjur Braendeland goto out; 880bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sk->sk_state != CAIF_CONNECTED) { 881bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock->state = SS_UNCONNECTED; 882bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = sock_error(sk); 883bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (!err) 884bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = -ECONNREFUSED; 885bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland goto out; 886bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland } 887bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock->state = SS_CONNECTED; 888bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland err = 0; 889e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendelandout: 890bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland release_sock(sk); 891bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return err; 892e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland} 893e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 894bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* 895bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * caif_release() - Disconnect a CAIF Socket 896bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Copied and modified af_irda.c:irda_release(). 897bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland */ 898bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic int caif_release(struct socket *sock) 899e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland{ 900e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct sock *sk = sock->sk; 901bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); 902e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 903bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (!sk) 904bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return 0; 905e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 906bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_tx_flow_off(cf_sk); 907e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 908e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland /* 909bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Ensure that packets are not queued after this point in time. 910bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock, 911bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * this ensures no packets when sock is dead. 912e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland */ 913c85c2951d4da1236e32f1858db418221e624aba5sjur.brandeland@stericsson.com spin_lock_bh(&sk->sk_receive_queue.lock); 914bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock_set_flag(sk, SOCK_DEAD); 915c85c2951d4da1236e32f1858db418221e624aba5sjur.brandeland@stericsson.com spin_unlock_bh(&sk->sk_receive_queue.lock); 916bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock->sk = NULL; 917e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 91833b2f5598b4ee68021364a7b795c09ad66bc0aa8sjur.brandeland@stericsson.com WARN_ON(IS_ERR(cf_sk->debugfs_socket_dir)); 919fb0d164cc1e46ddb22e8fac9f9cb94fdaeddd70fFabian Frederick debugfs_remove_recursive(cf_sk->debugfs_socket_dir); 920e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 921e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland lock_sock(&(cf_sk->sk)); 922bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sk->sk_state = CAIF_DISCONNECTED; 923bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sk->sk_shutdown = SHUTDOWN_MASK; 924e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 92554e90fb5ca8050156d3e748ddc690ed6ea9d71acsjur.brandeland@stericsson.com caif_disconnect_client(sock_net(sk), &cf_sk->layer); 926bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_socket->state = SS_DISCONNECTING; 927bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP); 928e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 929bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock_orphan(sk); 930bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sk_stream_kill_queues(&cf_sk->sk); 931bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland release_sock(sk); 932bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock_put(sk); 93354e90fb5ca8050156d3e748ddc690ed6ea9d71acsjur.brandeland@stericsson.com return 0; 934bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland} 935e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 936bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland/* Copied from af_unix.c:unix_poll(), added CAIF tx_flow handling */ 937bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic unsigned int caif_poll(struct file *file, 9383bffc475f9995843fa23a4978a4c112d8c8f4a6eSilviu-Mihai Popescu struct socket *sock, poll_table *wait) 939bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland{ 940bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct sock *sk = sock->sk; 941bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland unsigned int mask; 942bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); 943e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 944bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock_poll_wait(file, sk_sleep(sk), wait); 945bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland mask = 0; 946e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 947bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* exceptional events? */ 948bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sk->sk_err) 949bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland mask |= POLLERR; 950bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sk->sk_shutdown == SHUTDOWN_MASK) 951bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland mask |= POLLHUP; 952bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sk->sk_shutdown & RCV_SHUTDOWN) 953bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland mask |= POLLRDHUP; 954e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 955bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland /* readable? */ 956bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (!skb_queue_empty(&sk->sk_receive_queue) || 957bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland (sk->sk_shutdown & RCV_SHUTDOWN)) 958bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland mask |= POLLIN | POLLRDNORM; 959e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 960e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland /* 961bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * we set writable also when the other side has shut down the 962bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * connection. This prevents stuck sockets. 963e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland */ 964bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sock_writeable(sk) && tx_flow_is_on(cf_sk)) 965bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland mask |= POLLOUT | POLLWRNORM | POLLWRBAND; 966bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 967bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return mask; 968e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland} 969e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 970bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic const struct proto_ops caif_seqpacket_ops = { 971bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .family = PF_CAIF, 972bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .owner = THIS_MODULE, 973bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .release = caif_release, 974bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .bind = sock_no_bind, 975bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .connect = caif_connect, 976bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .socketpair = sock_no_socketpair, 977bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .accept = sock_no_accept, 978bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .getname = sock_no_getname, 979bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .poll = caif_poll, 980bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .ioctl = sock_no_ioctl, 981bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .listen = sock_no_listen, 982bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .shutdown = sock_no_shutdown, 983bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .setsockopt = setsockopt, 984bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .getsockopt = sock_no_getsockopt, 985bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .sendmsg = caif_seqpkt_sendmsg, 986bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .recvmsg = caif_seqpkt_recvmsg, 987bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .mmap = sock_no_mmap, 988bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .sendpage = sock_no_sendpage, 989bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland}; 990bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 991bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendelandstatic const struct proto_ops caif_stream_ops = { 992e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .family = PF_CAIF, 993e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .owner = THIS_MODULE, 994e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .release = caif_release, 995e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .bind = sock_no_bind, 996e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .connect = caif_connect, 997e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .socketpair = sock_no_socketpair, 998e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .accept = sock_no_accept, 999e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .getname = sock_no_getname, 1000e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .poll = caif_poll, 1001e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .ioctl = sock_no_ioctl, 1002e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .listen = sock_no_listen, 1003bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .shutdown = sock_no_shutdown, 1004e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .setsockopt = setsockopt, 1005e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .getsockopt = sock_no_getsockopt, 1006bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .sendmsg = caif_stream_sendmsg, 1007bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .recvmsg = caif_stream_recvmsg, 1008e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .mmap = sock_no_mmap, 1009bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland .sendpage = sock_no_sendpage, 1010e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland}; 1011e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1012e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland/* This function is called when a socket is finally destroyed. */ 1013e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendelandstatic void caif_sock_destructor(struct sock *sk) 1014e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland{ 1015bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); 1016e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland caif_assert(!atomic_read(&sk->sk_wmem_alloc)); 1017e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland caif_assert(sk_unhashed(sk)); 1018e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland caif_assert(!sk->sk_socket); 1019e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland if (!sock_flag(sk, SOCK_DEAD)) { 102033b2f5598b4ee68021364a7b795c09ad66bc0aa8sjur.brandeland@stericsson.com pr_debug("Attempt to release alive CAIF socket: %p\n", sk); 1021e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return; 1022e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland } 1023bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sk_stream_kill_queues(&cf_sk->sk); 1024b3ccfbe4098a5542177d0f34e8979f32e7d606e1sjur.brandeland@stericsson.com caif_free_client(&cf_sk->layer); 1025e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland} 1026e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1027e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendelandstatic int caif_create(struct net *net, struct socket *sock, int protocol, 10283bffc475f9995843fa23a4978a4c112d8c8f4a6eSilviu-Mihai Popescu int kern) 1029e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland{ 1030e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct sock *sk = NULL; 1031e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland struct caifsock *cf_sk = NULL; 1032e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland static struct proto prot = {.name = "PF_CAIF", 1033e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .owner = THIS_MODULE, 1034e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .obj_size = sizeof(struct caifsock), 1035e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland }; 1036e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1037bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN)) 1038bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland return -EPERM; 1039e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland /* 1040e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland * The sock->type specifies the socket type to use. 1041bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * The CAIF socket is a packet stream in the sense 1042bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * that it is packet based. CAIF trusts the reliability 1043bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * of the link, no resending is implemented. 1044e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland */ 1045bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland if (sock->type == SOCK_SEQPACKET) 1046bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock->ops = &caif_seqpacket_ops; 1047bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland else if (sock->type == SOCK_STREAM) 1048bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland sock->ops = &caif_stream_ops; 1049bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland else 1050e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return -ESOCKTNOSUPPORT; 1051e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1052e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland if (protocol < 0 || protocol >= CAIFPROTO_MAX) 1053e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return -EPROTONOSUPPORT; 1054e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland /* 1055bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * Set the socket state to unconnected. The socket state 1056bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland * is really not used at all in the net/core or socket.c but the 1057e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland * initialization makes sure that sock->state is not uninitialized. 1058e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland */ 1059e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland sk = sk_alloc(net, PF_CAIF, GFP_KERNEL, &prot); 1060e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland if (!sk) 1061e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return -ENOMEM; 1062e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1063e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland cf_sk = container_of(sk, struct caifsock, sk); 1064e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1065e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland /* Store the protocol */ 1066e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland sk->sk_protocol = (unsigned char) protocol; 1067e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1068447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin /* Initialize default priority for well-known cases */ 1069447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin switch (protocol) { 1070447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin case CAIFPROTO_AT: 1071447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin sk->sk_priority = TC_PRIO_CONTROL; 1072447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin break; 1073447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin case CAIFPROTO_RFM: 1074447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin sk->sk_priority = TC_PRIO_INTERACTIVE_BULK; 1075447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin break; 1076447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin default: 1077447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin sk->sk_priority = TC_PRIO_BESTEFFORT; 1078447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin } 1079447648128ec22e294604674ffe1064aa3ec3b767Dmitry Tarnyagin 1080e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland /* 1081e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland * Lock in order to try to stop someone from opening the socket 1082e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland * too early. 1083e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland */ 1084e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland lock_sock(&(cf_sk->sk)); 1085e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1086e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland /* Initialize the nozero default sock structure data. */ 1087e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland sock_init_data(sock, sk); 1088e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland sk->sk_destruct = caif_sock_destructor; 1089e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1090bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland mutex_init(&cf_sk->readlock); /* single task reading lock */ 1091bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->layer.ctrlcmd = caif_ctrl_cb; 1092bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_socket->state = SS_UNCONNECTED; 1093bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->sk.sk_state = CAIF_DISCONNECTED; 1094e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1095bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_tx_flow_off(cf_sk); 1096bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland set_rx_flow_on(cf_sk); 1097e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1098e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland /* Set default options on configuration */ 1099bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland cf_sk->conn_req.link_selector = CAIF_LINK_LOW_LATENCY; 1100e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland cf_sk->conn_req.protocol = protocol; 1101e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland release_sock(&cf_sk->sk); 1102e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return 0; 1103e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland} 1104e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1105bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland 1106e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendelandstatic struct net_proto_family caif_family_ops = { 1107e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .family = PF_CAIF, 1108e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .create = caif_create, 1109e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland .owner = THIS_MODULE, 1110e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland}; 1111e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 11124a695823b580124c3ab750d8d528f7c6522628c3sjur.brandeland@stericsson.comstatic int __init caif_sktinit_module(void) 1113e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland{ 1114bece7b2398d073d11b2e352405a3ecd3a1e39c60Sjur Braendeland int err = sock_register(&caif_family_ops); 1115e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland if (!err) 1116e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return err; 1117e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland return 0; 1118e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland} 1119e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland 1120e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendelandstatic void __exit caif_sktexit_module(void) 1121e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland{ 1122e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland sock_unregister(PF_CAIF); 1123e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendeland} 1124e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendelandmodule_init(caif_sktinit_module); 1125e6f95ec8db312491235b4f06343fbd991a82ce20Sjur Braendelandmodule_exit(caif_sktexit_module); 1126