From: Randy Dunlap <randy.dunlap@oracle.com>
To: sjur.brandeland@stericsson.com
Cc: netdev@vger.kernel.org, stefano.babic@babic.homelinux.org,
kim.xx.lilliestierna@stericsson.com,
christian.bejram@stericsson.com,
daniel.martensson@stericsson.com
Subject: Re: [RFC PATCH v3 5/8] CAIF Protocol Stack
Date: Mon, 30 Nov 2009 08:41:55 -0800 [thread overview]
Message-ID: <4B13F5D3.6090009@oracle.com> (raw)
In-Reply-To: <1259593252-2493-6-git-send-email-sjur.brandeland@stericsson.com>
sjur.brandeland@stericsson.com wrote:
> From: Sjur Braendeland <sjur.brandeland@stericsson.com>
what Patrick said:
patch description should be here and each email subject should be different
and describe what that patch does.
Please read Documentation/SubmittingPatches.
(more below)
> Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
> ---
> net/caif/Kconfig | 51 ++
> net/caif/Makefile | 51 ++
> net/caif/caif_chnlif.c | 205 ++++++
> net/caif/caif_config_util.c | 163 +++++
> net/caif/caif_dev.c | 520 ++++++++++++++
> net/caif/caif_socket.c | 1560 +++++++++++++++++++++++++++++++++++++++++++
> net/caif/chnl_net.c | 655 ++++++++++++++++++
> 7 files changed, 3205 insertions(+), 0 deletions(-)
> create mode 100644 net/caif/Kconfig
> create mode 100644 net/caif/Makefile
> create mode 100644 net/caif/caif_chnlif.c
> create mode 100644 net/caif/caif_config_util.c
> create mode 100644 net/caif/caif_dev.c
> create mode 100644 net/caif/caif_socket.c
> create mode 100644 net/caif/chnl_net.c
>
> diff --git a/net/caif/Kconfig b/net/caif/Kconfig
> new file mode 100644
> index 0000000..9349123
> --- /dev/null
> +++ b/net/caif/Kconfig
> @@ -0,0 +1,51 @@
> +#
> +# CAIF net configurations
> +#
> +
> +#menu "CAIF Support"
> +comment "CAIF Support"
> +
> +menuconfig CAIF
> + tristate "Enable CAIF support"
> + default n
> + ---help---
Tell us what CAIF means, probably in the help text.
> + Say Y here if you need to use a phone modem that uses CAIF as transport.
> + You will also need to say yes to any CAIF physical devices that your platform
> + supports.
> + This can be either built-in or a loadable module; if you select to build it as module
> + then the rest of CAIF also needs to built as modules.
> + See Documentation/CAIF for a further explanation on how to use and configure.
> +
> +if CAIF
> +
> +config CAIF_NETDEV
> + tristate "CAIF Network device"
> + default CAIF
> + ---help---
> + Say Y if you will be using the CAIF based network device.
a (or any) CAIF-based
> + This can be either built-in or a loadable module.
> + If you select to build it as a built-in then the main CAIF device must also be a built-in.
> + If unsure say Y.
> +
> +config CAIF_SOCK
> + tristate "CAIF Sockets"
> + default CAIF
> + ---help---
> + Say Y if you will be using the CAIF Sockets.
drop "the" ----------------^^^
> + This can be either built-in or a loadable module.
> + If you select to build it as a built-in then the main CAIF device mist also be a built-in.
s/mist/must/
> + If unsure say Y.
> +
> +config CAIF_DEBUG
> + bool "Enable Debug"
> + default n
> + --- help ---
> + Enable the inclusion of debug code in the CAIF stack.
> + Be aware that doing this will impact performance.
> + If unsure say N.
> +
> +
> +# Include physical drivers
> +source "drivers/net/caif/Kconfig"
> +endif
> +#endmenu
> diff --git a/net/caif/caif_chnlif.c b/net/caif/caif_chnlif.c
> new file mode 100644
> index 0000000..9c8a656
> --- /dev/null
> +++ b/net/caif/caif_chnlif.c
> @@ -0,0 +1,205 @@
> +/*
> + * Copyright (C) ST-Ericsson AB 2009
> + * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/skbuff.h>
> +#include <net/caif/caif_kernel.h>
> +#include <net/caif/generic/caif_layer.h>
> +#include <net/caif/caif_config_util.h>
> +#include <net/caif/caif_log.h>
> +#include <net/caif/generic/cfpkt.h>
> +#include <net/caif/generic/cfcnfg.h>
> +#include <net/caif/generic/cfglue.h>
> +#include <net/caif/caif_chr.h>
> +struct caif_kernelif {
> + struct layer layer;
> + struct caif_device *dev;
> + struct cfctrl_link_param param;
> +};
> +
> +
> +/**
> + * func caif_create_skb - Creates a CAIF SKB buffer
Use documented/expected kernel-doc notation, please. I.e., drop "func".
> + * @data: data to add to buffer
> + * @data_length: length of data
> + */
> +struct sk_buff *caif_create_skb(unsigned char *data, unsigned int data_length)
> +{
> + /* NOTE: Make room for CAIF headers when using SKB inside CAIF. */
> + struct sk_buff *skb =
> + alloc_skb(data_length + CAIF_SKB_HEAD_RESERVE +
> + CAIF_SKB_TAIL_RESERVE, GFP_ATOMIC);
> + if (skb == NULL)
> + return NULL;
> + skb_reserve(skb, CAIF_SKB_HEAD_RESERVE);
> +
> + memcpy(skb_put(skb, data_length), data, data_length);
> + return skb;
> +}
> +EXPORT_SYMBOL(caif_create_skb);
> +
...
> +
> +module_init(caif_device_init);
> +module_exit(caif_device_exit);
> +
> +
> +
> +
> +
> +
> +
> +
> +
delete all of those trailing empty lines.
> diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
> new file mode 100644
> index 0000000..492fcfb
> --- /dev/null
> +++ b/net/caif/caif_socket.c
> @@ -0,0 +1,1560 @@
> +/*
> + * Copyright (C) ST-Ericsson AB 2009
> + * Author: Sjur Brændeland sjur.brandlenad@stericsson.com
> + * Per Sigmond / Per.Sigmond@stericsson.com
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/fs.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/sched.h>
> +#include <linux/spinlock.h>
> +#include <linux/mutex.h>
> +#include <linux/list.h>
> +#include <linux/wait.h>
> +#include <linux/poll.h>
> +#include <linux/tcp.h>
> +#include <asm/uaccess.h>
> +#include <asm/atomic.h>
> +
> +/* Caif header files. */
> +#include <linux/caif/caif_socket.h>
> +#include <net/caif/generic/caif_layer.h>
> +#include <linux/caif/caif_config.h>
> +#include <net/caif/caif_log.h>
> +#include <net/caif/caif_chr.h>
> +
> +MODULE_LICENSE("GPL");
> +
> +#define CHNL_SKT_READ_QUEUE_HIGH 2000
> +#define CHNL_SKT_READ_QUEUE_LOW 100
> +
> +#ifdef CAIF_USE_CACHE
> +int caif_max_links = 32;
> +#endif
> +
> +int caif_sockbuf_size = 40000; /* FIXME: Check this value! */
> +static struct kmem_cache *caif_sk_cachep;
> +static atomic_t caif_nr_socks = ATOMIC_INIT(0);
> +
> +#define CONN_STATE_OPEN_BIT 1
> +#define CONN_STATE_PENDING_BIT 2
> +#define CONN_STATE_PEND_DESTROY_BIT 3
> +#define CONN_REMOTE_SHUTDOWN_BIT 4
> +
> +#define TX_FLOW_ON_BIT 1
> +#define RX_FLOW_ON_BIT 2
> +
> +#define STATE_IS_OPEN(cf_sk) test_bit(CONN_STATE_OPEN_BIT,\
> + (void *) &(cf_sk)->conn_state)
> +#define STATE_IS_REMOTE_SHUTDOWN(cf_sk) test_bit(CONN_REMOTE_SHUTDOWN_BIT,\
> + (void *) &(cf_sk)->conn_state)
> +#define STATE_IS_PENDING(cf_sk) test_bit(CONN_STATE_PENDING_BIT,\
> + (void *) &(cf_sk)->conn_state)
> +#define STATE_IS_PENDING_DESTROY(cf_sk) test_bit(CONN_STATE_PEND_DESTROY_BIT,\
> + (void *) &(cf_sk)->conn_state)
> +
> +#define SET_STATE_PENDING_DESTROY(cf_sk) set_bit(CONN_STATE_PEND_DESTROY_BIT,\
> + (void *) &(cf_sk)->conn_state)
> +#define SET_STATE_OPEN(cf_sk) set_bit(CONN_STATE_OPEN_BIT,\
> + (void *) &(cf_sk)->conn_state)
> +#define SET_STATE_CLOSED(cf_sk) clear_bit(CONN_STATE_OPEN_BIT,\
> + (void *) &(cf_sk)->conn_state)
> +#define SET_PENDING_ON(cf_sk) set_bit(CONN_STATE_PENDING_BIT,\
> + (void *) &(cf_sk)->conn_state)
> +#define SET_PENDING_OFF(cf_sk) clear_bit(CONN_STATE_PENDING_BIT,\
> + (void *) &(cf_sk)->conn_state)
> +#define SET_REMOTE_SHUTDOWN(cf_sk) set_bit(CONN_REMOTE_SHUTDOWN_BIT,\
> + (void *) &(cf_sk)->conn_state)
> +
> +#define RX_FLOW_IS_ON(cf_sk) test_bit(RX_FLOW_ON_BIT,\
> + (void *) &(cf_sk)->flow_state)
> +#define TX_FLOW_IS_ON(cf_sk) test_bit(TX_FLOW_ON_BIT,\
> + (void *) &(cf_sk)->flow_state)
> +
> +#define SET_RX_FLOW_OFF(cf_sk) clear_bit(RX_FLOW_ON_BIT,\
> + (void *) &(cf_sk)->flow_state)
> +#define SET_RX_FLOW_ON(cf_sk) set_bit(RX_FLOW_ON_BIT,\
> + (void *) &(cf_sk)->flow_state)
> +#define SET_TX_FLOW_OFF(cf_sk) clear_bit(TX_FLOW_ON_BIT,\
> + (void *) &(cf_sk)->flow_state)
> +#define SET_TX_FLOW_ON(cf_sk) set_bit(TX_FLOW_ON_BIT,\
> + (void *) &(cf_sk)->flow_state)
> +
> +#define SKT_READ_FLAG 0x01
> +#define SKT_WRITE_FLAG 0x02
> +
> +#define MAX_CAIF_SOCKETS 200
> +
> +#ifdef CONFIG_DEBUG_FS
> +struct dentry *debugfsdir;
> +#include <linux/debugfs.h>
> +
> +static int max_caif_sockets = MAX_CAIF_SOCKETS;
> +#endif
> +
> +/* The AF_CAIF socket */
> +struct caifsock {
> + struct sock sk; /* NOTE: sk has to be the first member */
> + struct layer layer;
> + char name[CAIF_LAYER_NAME_SZ];
> + u32 conn_state;
> + u32 flow_state;
> + struct cfpktq *pktq;
> + int file_mode;
> + struct caif_channel_config config;
> + int read_queue_len;
> + spinlock_t read_queue_len_lock;
> +
> +#ifdef CONFIG_DEBUG_FS
> + struct dentry *debugfs_device_dir;
> + atomic_t num_open;
> + atomic_t num_close;
> + atomic_t num_init;
> + atomic_t num_init_resp;
> + atomic_t num_init_fail_resp;
> + atomic_t num_deinit;
> + atomic_t num_deinit_resp;
> + atomic_t num_remote_shutdown_ind;
> + atomic_t num_tx_flow_off_ind;
> + atomic_t num_tx_flow_on_ind;
> + atomic_t num_rx_flow_off;
> + atomic_t num_rx_flow_on;
> +#endif
> +};
> +
> +static void drain_queue(struct caifsock *cf_sk);
> +
> +/** Packet Receive Callback function called from CAIF Stack */
Do not use /** to begin comments that are not kernel-doc notation.
(more found below, but deleted for now)
> +static int caif_sktrecv_cb(struct layer *layr, struct cfpkt *pkt)
> +{
> +/* Send a signal as a consequence of sendmsg, sendto or caif_sendmsg. */
> +static int caif_sendmsg(struct kiocb *kiocb, struct socket *sock,
> + struct msghdr *msg, size_t len)
> +{
> +
> + struct sock *sk = sock->sk;
> + struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
> + void *payload;
> + size_t payload_size = msg->msg_iov->iov_len;
> + struct cfpkt *pkt = NULL;
> + struct transmt_info info;
> + unsigned char *txbuf;
> + int err = 0;
> + ssize_t ret = -EIO;
> + int result;
> + struct sk_buff *skb;
> + CAIFLOG_TRACE("Enter %s\n", __func__);
> + caif_assert(msg->msg_iovlen == 1);
> +
> + if (cf_sk == NULL) {
> + CAIFLOG_TRACE("[%s:%d] private_data not set!\n",
> + __func__, __LINE__);
> + ret = -EBADFD;
> + goto write_error_no_unlock;
> + }
> +
> + if (unlikely(msg->msg_iov->iov_base == NULL)) {
> + CAIFLOG_WARN("Buffer is NULL.\n");
> + ret = -EINVAL;
> + goto write_error_no_unlock;
> + }
> +
> + payload = msg->msg_iov->iov_base;
> + if (payload_size > CAIF_MAX_PAYLOAD_SIZE) {
> + CAIFLOG_TRACE("[%s:%d] buffer too long\n", __func__, __LINE__);
> + ret = -EINVAL;
> + goto write_error_no_unlock;
> + }
> + /* I want to be alone on cf_sk (except status and queue) */
> + lock_sock(&(cf_sk->sk));
> +
> + caif_assert(cf_sk->pktq);
> +
> + if (!STATE_IS_OPEN(cf_sk)) {
> + /* Socket is closed or closing */
> + if (!STATE_IS_PENDING(cf_sk)) {
> + CAIFLOG_TRACE("socket is closed (by remote end)\n");
> + ret = -EPIPE;
> + } else {
> + CAIFLOG_TRACE("socket is closing...\n");
> + ret = -EBADF;
> + }
> + goto write_error;
> + }
> +
> + /* Socket is open or opening */
> + if (STATE_IS_PENDING(cf_sk)) {
> + CAIFLOG_TRACE("socket is opening...\n");
> +
> + if (msg->msg_flags & MSG_DONTWAIT) {
> + /* We can't block */
> + CAIFLOG_TRACE("state pending and MSG_DONTWAIT\n");
> + ret = -EAGAIN;
> + goto write_error;
> + }
> +
> + /* Let readers in */
> + release_sock(&cf_sk->sk);
> +
> + /* Blocking mode; state is pending and we need to wait
> + for its conclusion */
> + result =
> + wait_event_interruptible(*cf_sk->sk.sk_sleep,
> + !STATE_IS_PENDING(cf_sk));
> +
> + /* I want to be alone on cf_sk (except status and queue) */
> + lock_sock(&(cf_sk->sk));
> +
> + if (result == -ERESTARTSYS) {
> + CAIFLOG_TRACE
> + (" wait_event_interruptible woken by a signal (1)");
> + ret = -ERESTARTSYS;
> + goto write_error;
> + }
> + }
> +
> + if (STATE_IS_REMOTE_SHUTDOWN(cf_sk)) {
> + CAIFLOG_TRACE("received remote_shutdown indication\n");
> + ret = -ESHUTDOWN;
> + goto write_error;
> + }
> +
> + if (!TX_FLOW_IS_ON(cf_sk)) {
> +
> + /* Flow is off. Check non-block flag */
> + if (msg->msg_flags & MSG_DONTWAIT) {
> + CAIFLOG_TRACE
> + ("caif_sendmsg: MSG_DONTWAIT and tx flow off");
> + ret = -EAGAIN;
> + goto write_error;
> + }
> +
> + /* release lock before waiting */
> + release_sock(&cf_sk->sk);
> +
> + /* Wait until flow is on or socket is closed */
> + if (wait_event_interruptible(*cf_sk->sk.sk_sleep,
> + TX_FLOW_IS_ON(cf_sk)
> + || !STATE_IS_OPEN(cf_sk)
> + || STATE_IS_REMOTE_SHUTDOWN(cf_sk)
> + ) == -ERESTARTSYS) {
> + CAIFLOG_TRACE
> + ("caif_sendmsg:"
> + " wait_event_interruptible woken by a signal");
> + ret = -ERESTARTSYS;
> + goto write_error_no_unlock;
> + }
> +
> + /* I want to be alone on cf_sk (except status and queue) */
> + lock_sock(&(cf_sk->sk));
> +
> + if (!STATE_IS_OPEN(cf_sk)) {
> + /* someone closed the link, report error */
> + CAIFLOG_TRACE("[%s:%d] remote end shutdown!\n",
> + __func__, __LINE__);
> + ret = -EPIPE;
> + goto write_error;
> + }
> +
> + if (STATE_IS_REMOTE_SHUTDOWN(cf_sk)) {
> + CAIFLOG_TRACE("received remote_shutdown indication\n");
> + ret = -ESHUTDOWN;
> + goto write_error;
> + }
> + }
> +
> + /* Create packet, buf=NULL means no copying */
> + skb = caif_alloc_send_skb(sk,
> + payload_size + CAIF_NEEDED_HEADROOM +
> + CAIF_NEEDED_TAILROOM,
> + &err);
> + skb_reserve(skb, CAIF_NEEDED_HEADROOM);
> + pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb);
> + caif_assert((void *)pkt == (void *)skb);
> +
> + if (pkt == NULL) {
> + CAIFLOG_TRACE
> + ("caif_sendmsg: cfpkt_create_pkt returned NULL\n");
> + ret = -EIO;
> + goto write_error;
> + }
> +
> + if (!cfpkt_raw_append(pkt, (void **) &txbuf, payload_size)) {
> + CAIFLOG_TRACE("caif_sendmsg: cfpkt_raw_append failed\n");
> + cfpkt_destroy(pkt);
> + ret = -EINVAL;
> + goto write_error;
> + }
> +
> + /* Copy data into buffer. */
> + if (copy_from_user(txbuf, payload, payload_size)) {
> + CAIFLOG_TRACE
> + ("caif_sendmsg: copy_from_user returned non zero.\n");
> + cfpkt_destroy(pkt);
> + ret = -EINVAL;
> + goto write_error;
> + }
> + memset(&info, 0, sizeof(info));
> +
> + /* Send the packet down the stack. */
> + caif_assert(cf_sk->layer.dn);
> + caif_assert(cf_sk->layer.dn->transmit);
> +
> + do {
> + ret = cf_sk->layer.dn->transmit(cf_sk->layer.dn,
> + &info, pkt);
odd indentation?
> + if (likely((ret >= 0) || (ret != -EAGAIN)))
> + break;
> +
> + /* EAGAIN - retry */
> + if (msg->msg_flags & MSG_DONTWAIT) {
> + CAIFLOG_TRACE
> + ("NONBLOCK and transmit failed, error = %d\n",
> + ret);
> + ret = -EAGAIN;
> + goto write_error;
> + }
> +
> + /* Let readers in */
> + release_sock(&cf_sk->sk);
> +
> + /* Wait until flow is on or socket is closed */
> + if (wait_event_interruptible(*cf_sk->sk.sk_sleep,
> + TX_FLOW_IS_ON(cf_sk)
> + || !STATE_IS_OPEN(cf_sk)
> + || STATE_IS_REMOTE_SHUTDOWN(cf_sk)
> + ) == -ERESTARTSYS) {
> + CAIFLOG_TRACE
> + ("wait_event_interruptible woken by a signal");
> + ret = -ERESTARTSYS;
> + goto write_error_no_unlock;
> + }
> +
> + /* I want to be alone on cf_sk (except status and queue) */
> + lock_sock(&(cf_sk->sk));
> +
> + } while (ret == -EAGAIN);
> +
> + if (ret < 0) {
> + cfpkt_destroy(pkt);
> + CAIFLOG_TRACE("transmit failed, error = %d\n",
> + ret);
> +
> + goto write_error;
> + }
> +
> + release_sock(&cf_sk->sk);
> + CAIFLOG_EXIT("");
> + return payload_size;
> +
> +write_error:
> + release_sock(&cf_sk->sk);
> +write_error_no_unlock:
> + CAIFLOG_EXIT("");
> + return ret;
> +}
> +
> +
> +static int setsockopt(struct socket *sock,
> + int lvl, int opt, char __user *ov, int ol)
> +{
> + struct sock *sk = sock->sk;
> + struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
> + struct caif_channel_opt confopt;
> + int res;
> +
> + if (lvl != SOL_CAIF) {
> + CAIFLOG_TRACE("setsockopt bad level\n");
> + return -ENOPROTOOPT;
odd indentation.
> + }
> +
> + switch (opt) {
> + case CAIF_CHANNEL_OPT:
> + if (ol < sizeof(struct caif_channel_opt)) {
> + CAIFLOG_TRACE("setsockopt"
> + " CAIF_CHANNEL_CONFIG bad size\n");
> + return -EINVAL;
odd indentation.
> + }
> + res = copy_from_user(&confopt, ov, sizeof(confopt));
> + if (res)
> + return res;
> + lock_sock(&(cf_sk->sk));
> + cf_sk->config.priority = confopt.priority;
> + cf_sk->config.phy_pref = confopt.link_selector;
> + strncpy(cf_sk->config.phy_name, confopt.link_name,
> + sizeof(cf_sk->config.phy_name));
> + CAIFLOG_TRACE("Setting sockopt pri=%d pref=%d name=%s\n",
> + cf_sk->config.priority,
> + cf_sk->config.phy_pref,
> + cf_sk->config.phy_name);
> + release_sock(&cf_sk->sk);
> + return 0;
> +/* TODO: Implement the remaining options:
> + * case CAIF_REQ_PARAM_OPT:
> + * case CAIF_RSP_PARAM_OPT:
> + * case CAIF_UTIL_FLOW_OPT:
> + * case CAIF_CONN_INFO_OPT:
> + * case CAIF_CONN_ID_OPT:
> + */
> + default:
> + CAIFLOG_TRACE("setsockopt: unhandled option %d\n",
> + opt);
> + return -EINVAL;
> + }
> +
> +
> +}
> +int caif_connect(struct socket *sock, struct sockaddr *uservaddr,
> + int sockaddr_len, int flags)
> +{
> + struct caifsock *cf_sk = NULL;
> + int result = -1;
> + int mode = 0;
> + int ret = -EIO;
> + struct sock *sk = sock->sk;
indent above line with tab, not spaces.
> +
> + CAIFLOG_TRACE("Enter %s\n", __func__);
> +
> + BUG_ON(sk == NULL);
> +
> + cf_sk = container_of(sk, struct caifsock, sk);
> +
> + CAIFLOG_TRACE("cf_sk=%p OPEN=%d, TX_FLOW=%d, RX_FLOW=%d\n", cf_sk,
> + STATE_IS_OPEN(cf_sk),
> + TX_FLOW_IS_ON(cf_sk), RX_FLOW_IS_ON(cf_sk));
> +
> + sk->sk_state = TCP_CLOSE;
> + sock->state = SS_UNCONNECTED;
> +
> + /* FIXME: SOCK_DGRAM should be removed? */
> + if (sock->type == SOCK_DGRAM || sock->type == SOCK_SEQPACKET) {
> + sock->state = SS_CONNECTED;
> + sk->sk_state = TCP_ESTABLISHED;
> + } else
> + goto out;
> +
> + /* I want to be alone on cf_sk (except status and queue) */
> + lock_sock(&(cf_sk->sk));
> +
> + ret = caif_channel_config(cf_sk, uservaddr, sockaddr_len,
> + &cf_sk->config);
> + if (ret) {
> + CAIFLOG_TRACE
> + ("[%s:%d] Cannot set socket address\n",
> + __func__, __LINE__);
> + goto open_error;
> + }
> +
> +
> +#ifdef CONFIG_DEBUG_FS
> + atomic_inc(&cf_sk->num_open);
> +#endif
> + mode = SKT_READ_FLAG | SKT_WRITE_FLAG;
> +
> + /* If socket is not open, make sure socket is in fully closed state */
> + if (!STATE_IS_OPEN(cf_sk)) {
> + /* Has link close response been received
> + (if we ever sent it)? */
> + if (STATE_IS_PENDING(cf_sk)) {
> + /* Still waiting for close response from remote.
> + If opened non-blocking, report "would block" */
> + if (flags & MSG_DONTWAIT) {
> + CAIFLOG_TRACE("MSG_DONTWAIT"
> + " && close pending\n");
> + ret = -EAGAIN;
> + goto open_error;
> + }
> +
> + CAIFLOG_TRACE
> + ("wait for close response from remote...\n");
> +
> + release_sock(&cf_sk->sk);
> +
> + /* Blocking mode; close is pending and we need to wait
> + for its conclusion */
> + result =
> + wait_event_interruptible(*cf_sk->sk.sk_sleep,
> + !STATE_IS_PENDING(cf_sk));
> +
> + lock_sock(&(cf_sk->sk));
> + if (result == -ERESTARTSYS) {
> + CAIFLOG_TRACE
> + ("wait_event_interruptible woken"
> + "by a signal (1)");
> + ret = -ERESTARTSYS;
> + goto open_error;
> + }
> + }
> + }
...
> +}
> +
> +/* This function is called as part of close. */
> +static int caif_release(struct socket *sock)
> +{
> + struct sock *sk = sock->sk;
> + struct caifsock *cf_sk = NULL;
> + CAIFLOG_TRACE("Enter %s\n", __func__);
> +
> + caif_assert(sk != NULL);
> + cf_sk = container_of(sk, struct caifsock, sk);
> +
> + caif_shutdown(sock, SHUT_RDWR);
> + lock_sock(&(cf_sk->sk));
> + /* NOTE: This is how the sock->sk structure is used all over the linux
> + * socket implementation. Since there is no locking protecting
> + * the sock->sk pointer, the linux socket implementation do not
> + * support multiple threads using the same socket descriptor,
> + * since if one of the threads close the socket, the other
> + * threads may end up accessing a pointer to NULL. See for
> + * instance sock_setsockopt in net/socket.c, it uses sock->sk
> + * without checking if its value is NULL. */
/*
* Note: This is the Linux long comment
* style. Please use it.
*/
> + sock->sk = NULL;
> +
> + /* Unlink the socket from the hunt name table. */
> +
> +
> + /* Trigger the pending attachs from and to the socket. This needs to
> + * be done before the socket starts to be released. */
> +
> +
> + /* Remove pending new link requests. */
> +
> + /* Detach the socket from its process context by making it orphan. */
> + sock_orphan(sk);
> +
> + /* Setting SHUTDOWN_MASK means that both send and receive are shutdown
> + * for the socket. */
> + sk->sk_shutdown = SHUTDOWN_MASK;
> +
> + /* Set the socket state to closed, the TCP_CLOSE macro is used when
> + * closing any socket. */
> + sk->sk_state = TCP_CLOSE;
> +
> + /* Flush out this sockets receive queue. */
> + drain_queue(cf_sk);
> +
> + /* Finally release the socket. */
> + STATE_IS_PENDING_DESTROY(cf_sk);
> + release_sock(&cf_sk->sk);
> + sock_put(sk);
> +
> + return 0;
> +
> + /* The rest of the cleanup will be handled from the
> + * caif_sock_destructor */
> +}
> +/* This function is called when a socket is finally destructed. */
destroyed. */
> +static void caif_sock_destructor(struct sock *sk)
> +{
> + struct caifsock *cf_sk = NULL;
> + CAIFLOG_TRACE("Enter %s\n", __func__);
> + cf_sk = container_of(sk, struct caifsock, sk);
> +
> + /* Error checks. */
> + caif_assert(!atomic_read(&sk->sk_wmem_alloc));
> + caif_assert(sk_unhashed(sk));
> + caif_assert(!sk->sk_socket);
> +
> + if (!sock_flag(sk, SOCK_DEAD)) {
> + CAIFLOG_TRACE("Attempt to release alive caif socket: 0x%p", sk);
> + return;
> + }
> +
> + lock_sock(&(cf_sk->sk));
> +
> + if (STATE_IS_OPEN(cf_sk)) {
> + CAIFLOG_TRACE
> + ("[%s:%d] socket is opened (cf_sk=%p)"
> + " file_mode = 0x%x\n", __func__, __LINE__,
> + cf_sk, cf_sk->file_mode);
> + release_sock(&cf_sk->sk);
> + return;
> + }
> +
> + CAIFLOG_TRACE("pktq = %p \n", cf_sk->pktq);
> + drain_queue(cf_sk);
> + CAIFLOG_TRACE("pktq = %p \n", cf_sk->pktq);
> +
> + cfglu_free(cf_sk->pktq);
> +
> +#ifdef CONFIG_DEBUG_FS
> + if (cf_sk->debugfs_device_dir != NULL)
> + debugfs_remove_recursive(cf_sk->debugfs_device_dir);
> +#endif
> +
> + release_sock(&cf_sk->sk);
> + CAIFLOG_WARN("caif_sock_destructor: Removing socket %s\n",
> + cf_sk->name);
> + /* Decrease the global caif socket counter. */
> + atomic_dec(&caif_nr_socks);
> + return;
> +}
> +
> diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
> new file mode 100644
> index 0000000..fbc8a64
> --- /dev/null
> +++ b/net/caif/chnl_net.c
> @@ -0,0 +1,655 @@
> +/*
> + * Copyright (C) ST-Ericsson AB 2009
> + * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/version.h>
> +#include <linux/fs.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/netdevice.h>
> +#include <linux/if_ether.h>
> +#include <linux/moduleparam.h>
> +#include <linux/ip.h>
> +#include <linux/sched.h>
> +#include <linux/sockios.h>
> +
> +/* CAIF header files. */
> +#include <net/caif/generic/caif_layer.h>
> +#include <net/caif/generic/cfcnfg.h>
> +#include <net/caif/generic/cfpkt.h>
> +#include <net/caif/caif_chr.h>
> +#include <net/caif/caif_log.h>
> +
> +/*NetLink Header files*/
> +#include <net/rtnetlink.h>
> +#include <linux/caif/if_caif.h>
> +
> +#define CAIF_CONNECT_TIMEOUT 30
> +#define SIZE_MTU 1500
> +#define SIZE_MTU_MAX 4080
> +#define SIZE_MTU_MIN 68
> +
> +static LIST_HEAD(chnl_net_list);
> +static spinlock_t list_lock;
> +
> +MODULE_LICENSE("GPL");
> +
> +struct chnl_net {
> + struct layer chnl;
> + struct net_device_stats stats;
> + spinlock_t lock;
> + struct caif_channel_config config;
> + struct list_head list_field;
> + struct net_device *netdev;
> + char name[256];
> + wait_queue_head_t netmgmt_wq;
> + /* Flow status to remember and control the transmission. */
> + bool flowenabled;
> +};
> +
> +
> +static struct chnl_net *find_device(char *name, bool remove_from_list)
> +{
> + struct list_head *list_node;
> + struct list_head *n;
> + struct chnl_net *dev = NULL;
> + struct chnl_net *tmp;
> + CAIFLOG_ENTER("");
> + spin_lock(&list_lock);
> + CAIFLOG_TRACE("[%s:%d] start looping \n", __func__,
> + __LINE__);
> + list_for_each_safe(list_node, n, &chnl_net_list) {
> + tmp =
> + list_entry(list_node, struct chnl_net, list_field);
Above doesn't need to be on 2 lines.
> + /* Find from name. */
> + if (name) {
> + if (!strncmp(tmp->name, name, sizeof(tmp->name)))
> + dev = tmp;
> + } else
> + /* Get the first element if name is not specified. */
> + dev = tmp;
> + if (dev) {
> + CAIFLOG_TRACE("[%s:%d] match %s \n",
> + __func__, __LINE__, name);
> + if (remove_from_list)
> + list_del(list_node);
> + break;
> + }
> + }
> + spin_unlock(&list_lock);
> + return dev;
> +}
--
~Randy
next prev parent reply other threads:[~2009-11-30 16:42 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-11-30 15:00 [RFC PATCH v3 0/8] CAIF Protocol Stack sjur.brandeland
2009-11-30 15:00 ` [RFC PATCH v3 1/8] " sjur.brandeland
2009-11-30 15:00 ` [RFC PATCH v3 2/8] " sjur.brandeland
2009-11-30 15:00 ` [RFC PATCH v3 3/8] " sjur.brandeland
2009-11-30 15:00 ` [RFC PATCH v3 4/8] " sjur.brandeland
2009-11-30 15:00 ` [RFC PATCH v3 5/8] " sjur.brandeland
2009-11-30 15:00 ` [RFC PATCH v3 6/8] " sjur.brandeland
2009-11-30 15:00 ` [RFC PATCH v3 7/8] " sjur.brandeland
2009-11-30 15:00 ` [RFC PATCH v3 8/8] " sjur.brandeland
2009-12-15 17:12 ` [RFC PATCH v3 7/8] " stefano babic
2009-11-30 16:41 ` Randy Dunlap [this message]
2009-12-10 13:05 ` [RFC PATCH v3 5/8] " Sjur Brændeland
2009-12-10 16:44 ` Randy Dunlap
2009-12-15 16:47 ` [RFC PATCH v3 4/8] " stefano babic
2009-12-16 16:16 ` Sjur Brændeland
2009-12-15 16:00 ` [RFC PATCH v3 3/8] " stefano babic
2009-12-16 16:15 ` Sjur Brændeland
2009-12-09 0:18 ` [RFC PATCH v3 2/8] " stefano babic
2009-12-10 11:20 ` Sjur Brændeland
2009-12-08 23:42 ` [RFC PATCH v3 1/8] " stefano babic
2009-12-10 11:11 ` Sjur Brændeland
2009-11-30 16:08 ` [RFC PATCH v3 0/8] " Patrick McHardy
2009-11-30 18:26 ` Sjur Brændeland
2009-12-02 17:02 ` Stefano Babic
2009-12-03 17:49 ` Sjur Brændeland
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4B13F5D3.6090009@oracle.com \
--to=randy.dunlap@oracle.com \
--cc=christian.bejram@stericsson.com \
--cc=daniel.martensson@stericsson.com \
--cc=kim.xx.lilliestierna@stericsson.com \
--cc=netdev@vger.kernel.org \
--cc=sjur.brandeland@stericsson.com \
--cc=stefano.babic@babic.homelinux.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.