* [PATCH net-next-2.6 6/7] caif: Bugfixes in CAIF netdevice for close and flow control
From: sjur.brandeland @ 2010-04-28 18:54 UTC (permalink / raw)
To: netdev, davem
Cc: marcel, daniel.martensson, sjurbr, linus.walleij,
Sjur Braendeland
In-Reply-To: <1272480880-30672-5-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Changes:
o Bugfix: Flow control was causing the device to be destroyed.
o Bugfix: Handle CAIF channel connect failures.
o If the underlying link layer is gone the net-device is no longer removed,
but closed.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
net/caif/chnl_net.c | 130 ++++++++++++++++++++++++++++----------------------
1 files changed, 73 insertions(+), 57 deletions(-)
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
index f622ff1..610966a 100644
--- a/net/caif/chnl_net.c
+++ b/net/caif/chnl_net.c
@@ -22,10 +22,10 @@
#include <net/caif/cfpkt.h>
#include <net/caif/caif_dev.h>
-#define CAIF_CONNECT_TIMEOUT 30
+/* GPRS PDP connection has MTU to 1500 */
#define SIZE_MTU 1500
-#define SIZE_MTU_MAX 4080
-#define SIZE_MTU_MIN 68
+/* 5 sec. connect timeout */
+#define CONNECT_TIMEOUT (5 * HZ)
#define CAIF_NET_DEFAULT_QUEUE_LEN 500
#undef pr_debug
@@ -37,6 +37,13 @@ static LIST_HEAD(chnl_net_list);
MODULE_LICENSE("GPL");
MODULE_ALIAS_RTNL_LINK("caif");
+enum caif_states {
+ CAIF_CONNECTED = 1,
+ CAIF_CONNECTING,
+ CAIF_DISCONNECTED,
+ CAIF_SHUTDOWN
+};
+
struct chnl_net {
struct cflayer chnl;
struct net_device_stats stats;
@@ -47,7 +54,7 @@ struct chnl_net {
wait_queue_head_t netmgmt_wq;
/* Flow status to remember and control the transmission. */
bool flowenabled;
- bool pending_close;
+ enum caif_states state;
};
static void robust_list_del(struct list_head *delete_node)
@@ -58,15 +65,16 @@ static void robust_list_del(struct list_head *delete_node)
list_for_each_safe(list_node, n, &chnl_net_list) {
if (list_node == delete_node) {
list_del(list_node);
- break;
+ return;
}
}
+ WARN_ON(1);
}
static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)
{
struct sk_buff *skb;
- struct chnl_net *priv = NULL;
+ struct chnl_net *priv = container_of(layr, struct chnl_net, chnl);
int pktlen;
int err = 0;
@@ -91,7 +99,6 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)
else
skb->ip_summed = CHECKSUM_NONE;
- /* FIXME: Drivers should call this in tasklet context. */
if (in_interrupt())
netif_rx(skb);
else
@@ -117,23 +124,25 @@ static void close_work(struct work_struct *work)
struct chnl_net *dev = NULL;
struct list_head *list_node;
struct list_head *_tmp;
- rtnl_lock();
+ /* May be called with or without RTNL lock held */
+ int islocked = rtnl_is_locked();
+ if (!islocked)
+ rtnl_lock();
list_for_each_safe(list_node, _tmp, &chnl_net_list) {
dev = list_entry(list_node, struct chnl_net, list_field);
- if (!dev->pending_close)
- continue;
- list_del(list_node);
- delete_device(dev);
+ if (dev->state == CAIF_SHUTDOWN)
+ dev_close(dev->netdev);
}
- rtnl_unlock();
+ if (!islocked)
+ rtnl_unlock();
}
static DECLARE_WORK(close_worker, close_work);
static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow,
int phyid)
{
- struct chnl_net *priv;
- pr_debug("CAIF: %s(): NET flowctrl func called flow: %s.\n",
+ struct chnl_net *priv = container_of(layr, struct chnl_net, chnl);
+ pr_debug("CAIF: %s(): NET flowctrl func called flow: %s\n",
__func__,
flow == CAIF_CTRLCMD_FLOW_ON_IND ? "ON" :
flow == CAIF_CTRLCMD_INIT_RSP ? "INIT" :
@@ -143,21 +152,31 @@ static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow,
flow == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND ?
"REMOTE_SHUTDOWN" : "UKNOWN CTRL COMMAND");
- priv = container_of(layr, struct chnl_net, chnl);
+
switch (flow) {
case CAIF_CTRLCMD_FLOW_OFF_IND:
+ priv->flowenabled = false;
+ netif_stop_queue(priv->netdev);
+ break;
case CAIF_CTRLCMD_DEINIT_RSP:
+ priv->state = CAIF_DISCONNECTED;
+ break;
case CAIF_CTRLCMD_INIT_FAIL_RSP:
+ priv->state = CAIF_DISCONNECTED;
+ wake_up_interruptible(&priv->netmgmt_wq);
+ break;
case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND:
- priv->flowenabled = false;
+ priv->state = CAIF_SHUTDOWN;
netif_tx_disable(priv->netdev);
- pr_warning("CAIF: %s(): done\n", __func__);
- priv->pending_close = 1;
schedule_work(&close_worker);
break;
case CAIF_CTRLCMD_FLOW_ON_IND:
+ priv->flowenabled = true;
+ netif_wake_queue(priv->netdev);
+ break;
case CAIF_CTRLCMD_INIT_RSP:
+ priv->state = CAIF_CONNECTED;
priv->flowenabled = true;
netif_wake_queue(priv->netdev);
wake_up_interruptible(&priv->netmgmt_wq);
@@ -194,9 +213,6 @@ static int chnl_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
pkt = cfpkt_fromnative(CAIF_DIR_OUT, (void *) skb);
- pr_debug("CAIF: %s(): transmit inst %s %d,%p\n",
- __func__, dev->name, priv->chnl.dn->id, &priv->chnl.dn);
-
/* Send the packet down the stack. */
result = priv->chnl.dn->transmit(priv->chnl.dn, pkt);
if (result) {
@@ -217,61 +233,59 @@ static int chnl_net_open(struct net_device *dev)
struct chnl_net *priv = NULL;
int result = -1;
ASSERT_RTNL();
-
priv = netdev_priv(dev);
- pr_debug("CAIF: %s(): dev name: %s\n", __func__, priv->name);
-
if (!priv) {
pr_debug("CAIF: %s(): chnl_net_open: no priv\n", __func__);
return -ENODEV;
}
- result = caif_connect_client(&priv->conn_req, &priv->chnl);
- if (result != 0) {
- pr_debug("CAIF: %s(): err: "
- "Unable to register and open device, Err:%d\n",
- __func__,
- result);
- return -ENODEV;
+
+ if (priv->state != CAIF_CONNECTING) {
+ priv->state = CAIF_CONNECTING;
+ result = caif_connect_client(&priv->conn_req, &priv->chnl);
+ if (result != 0) {
+ priv->state = CAIF_DISCONNECTED;
+ pr_debug("CAIF: %s(): err: "
+ "Unable to register and open device,"
+ " Err:%d\n",
+ __func__,
+ result);
+ return result;
+ }
}
- result = wait_event_interruptible(priv->netmgmt_wq, priv->flowenabled);
+
+ result = wait_event_interruptible_timeout(priv->netmgmt_wq,
+ priv->state != CAIF_CONNECTING,
+ CONNECT_TIMEOUT);
if (result == -ERESTARTSYS) {
pr_debug("CAIF: %s(): wait_event_interruptible"
" woken by a signal\n", __func__);
return -ERESTARTSYS;
- } else
- pr_debug("CAIF: %s(): Flow on recieved\n", __func__);
+ }
+ if (result == 0) {
+ pr_debug("CAIF: %s(): connect timeout\n", __func__);
+ caif_disconnect_client(&priv->chnl);
+ priv->state = CAIF_DISCONNECTED;
+ pr_debug("CAIF: %s(): state disconnected\n", __func__);
+ return -ETIMEDOUT;
+ }
+ if (priv->state != CAIF_CONNECTED) {
+ pr_debug("CAIF: %s(): connect failed\n", __func__);
+ return -ECONNREFUSED;
+ }
+ pr_debug("CAIF: %s(): CAIF Netdevice connected\n", __func__);
return 0;
}
static int chnl_net_stop(struct net_device *dev)
{
struct chnl_net *priv;
- int result = -1;
+
ASSERT_RTNL();
priv = netdev_priv(dev);
-
- result = caif_disconnect_client(&priv->chnl);
- if (result != 0) {
- pr_debug("CAIF: %s(): chnl_net_stop: err: "
- "Unable to STOP device, Err:%d\n",
- __func__, result);
- return -EBUSY;
- }
- result = wait_event_interruptible(priv->netmgmt_wq,
- !priv->flowenabled);
-
- if (result == -ERESTARTSYS) {
- pr_debug("CAIF: %s(): wait_event_interruptible woken by"
- " signal, signal_pending(current) = %d\n",
- __func__,
- signal_pending(current));
- } else {
- pr_debug("CAIF: %s(): disconnect received\n", __func__);
-
- }
-
+ priv->state = CAIF_DISCONNECTED;
+ caif_disconnect_client(&priv->chnl);
return 0;
}
@@ -377,6 +391,8 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev,
ASSERT_RTNL();
caifdev = netdev_priv(dev);
caif_netlink_parms(data, &caifdev->conn_req);
+ dev_net_set(caifdev->netdev, src_net);
+
ret = register_netdevice(dev);
if (ret)
pr_warning("CAIF: %s(): device rtml registration failed\n",
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 5/7] caif: Rewritten socket implementation
From: sjur.brandeland @ 2010-04-28 18:54 UTC (permalink / raw)
To: netdev, davem
Cc: marcel, daniel.martensson, sjurbr, linus.walleij,
Sjur Braendeland
In-Reply-To: <1272480880-30672-4-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Changes:
This is a complete re-write of the socket layer. Making the socket
implementation more aligned with the other socket layers and using more
of the support functions available in sock.c. Lots of code is copied
from af_unix (and some from af_irda).
Non-blocking mode should be working as well.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
include/linux/caif/caif_socket.h | 5 +-
net/caif/caif_socket.c | 2643 ++++++++++++++++++--------------------
2 files changed, 1255 insertions(+), 1393 deletions(-)
rewrite net/caif/caif_socket.c (76%)
diff --git a/include/linux/caif/caif_socket.h b/include/linux/caif/caif_socket.h
index 8e5c844..2a61eb1 100644
--- a/include/linux/caif/caif_socket.h
+++ b/include/linux/caif/caif_socket.h
@@ -16,7 +16,6 @@
#include <sys/socket.h>
#endif
-
/**
* enum caif_link_selector - Physical Link Selection.
* @CAIF_LINK_HIGH_BANDW: Physical interface for high-bandwidth
@@ -59,7 +58,7 @@ enum caif_channel_priority {
/**
* enum caif_protocol_type - CAIF Channel type.
* @CAIFPROTO_AT: Classic AT channel.
- * @CAIFPROTO_DATAGRAM: Datagram channel.
+ * @CAIFPROTO_DATAGRAM: Datagram channel.
* @CAIFPROTO_DATAGRAM_LOOP: Datagram loopback channel, used for testing.
* @CAIFPROTO_UTIL: Utility (Psock) channel.
* @CAIFPROTO_RFM: Remote File Manager
@@ -87,6 +86,7 @@ enum caif_at_type {
/**
* struct sockaddr_caif - the sockaddr structure for CAIF sockets.
+ * @family: Address family number, must be AF_CAIF.
* @u: Union of address data 'switched' by family.
* :
* @u.at: Applies when family = CAIFPROTO_AT.
@@ -153,6 +153,7 @@ struct sockaddr_caif {
*
*
* This enum defines the CAIF Socket options to be used on a socket
+ * of type PF_CAIF.
*
*/
enum caif_socket_opts {
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
dissimilarity index 76%
index d455375..c3a70c5 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -1,1391 +1,1252 @@
-/*
- * Copyright (C) ST-Ericsson AB 2010
- * Author: Sjur Brendeland sjur.brandeland@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 <linux/uaccess.h>
-#include <asm/atomic.h>
-
-#include <linux/caif/caif_socket.h>
-#include <net/caif/caif_layer.h>
-#include <net/caif/caif_dev.h>
-#include <net/caif/cfpkt.h>
-
-MODULE_LICENSE("GPL");
-
-#define CHNL_SKT_READ_QUEUE_HIGH 200
-#define CHNL_SKT_READ_QUEUE_LOW 100
-
-static int caif_sockbuf_size = 40000;
-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 SET_REMOTE_SHUTDOWN_OFF(dev) clear_bit(CONN_REMOTE_SHUTDOWN_BIT,\
- (void *) &(dev)->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
-static struct dentry *debugfsdir;
-#include <linux/debugfs.h>
-
-#ifdef CONFIG_DEBUG_FS
-struct debug_fs_counter {
- 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;
- atomic_t skb_in_use;
- atomic_t skb_alloc;
- atomic_t skb_free;
-};
-static struct debug_fs_counter cnt;
-#define dbfs_atomic_inc(v) atomic_inc(v)
-#define dbfs_atomic_dec(v) atomic_dec(v)
-#else
-#define dbfs_atomic_inc(v)
-#define dbfs_atomic_dec(v)
-#endif
-
-/* The AF_CAIF socket */
-struct caifsock {
- /* NOTE: sk has to be the first member */
- struct sock sk;
- struct cflayer layer;
- char name[CAIF_LAYER_NAME_SZ];
- u32 conn_state;
- u32 flow_state;
- struct cfpktq *pktq;
- int file_mode;
- struct caif_connect_request conn_req;
- int read_queue_len;
- /* protect updates of read_queue_len */
- spinlock_t read_queue_len_lock;
- struct dentry *debugfs_socket_dir;
-};
-
-static void drain_queue(struct caifsock *cf_sk);
-
-/* Packet Receive Callback function called from CAIF Stack */
-static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt)
-{
- struct caifsock *cf_sk;
- int read_queue_high;
- cf_sk = container_of(layr, struct caifsock, layer);
-
- if (!STATE_IS_OPEN(cf_sk)) {
- /*FIXME: This should be allowed finally!*/
- pr_debug("CAIF: %s(): called after close request\n", __func__);
- cfpkt_destroy(pkt);
- return 0;
- }
- /* NOTE: This function may be called in Tasklet context! */
-
- /* The queue has its own lock */
- cfpkt_queue(cf_sk->pktq, pkt, 0);
-
- spin_lock(&cf_sk->read_queue_len_lock);
- cf_sk->read_queue_len++;
-
- read_queue_high = (cf_sk->read_queue_len > CHNL_SKT_READ_QUEUE_HIGH);
- spin_unlock(&cf_sk->read_queue_len_lock);
-
- if (RX_FLOW_IS_ON(cf_sk) && read_queue_high) {
- dbfs_atomic_inc(&cnt.num_rx_flow_off);
- SET_RX_FLOW_OFF(cf_sk);
-
- /* Send flow off (NOTE: must not sleep) */
- pr_debug("CAIF: %s():"
- " sending flow OFF (queue len = %d)\n",
- __func__,
- cf_sk->read_queue_len);
- caif_assert(cf_sk->layer.dn);
- caif_assert(cf_sk->layer.dn->ctrlcmd);
-
- (void) cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
- CAIF_MODEMCMD_FLOW_OFF_REQ);
- }
-
- /* Signal reader that data is available. */
-
- wake_up_interruptible(sk_sleep(&cf_sk->sk));
-
- return 0;
-}
-
-/* Packet Flow Control Callback function called from CAIF */
-static void caif_sktflowctrl_cb(struct cflayer *layr,
- enum caif_ctrlcmd flow,
- int phyid)
-{
- struct caifsock *cf_sk;
-
- /* NOTE: This function may be called in Tasklet context! */
- pr_debug("CAIF: %s(): flowctrl func called: %s.\n",
- __func__,
- flow == CAIF_CTRLCMD_FLOW_ON_IND ? "ON" :
- flow == CAIF_CTRLCMD_FLOW_OFF_IND ? "OFF" :
- flow == CAIF_CTRLCMD_INIT_RSP ? "INIT_RSP" :
- flow == CAIF_CTRLCMD_DEINIT_RSP ? "DEINIT_RSP" :
- flow == CAIF_CTRLCMD_INIT_FAIL_RSP ? "INIT_FAIL_RSP" :
- flow ==
- CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND ? "REMOTE_SHUTDOWN" :
- "UKNOWN CTRL COMMAND");
-
- if (layr == NULL)
- return;
-
- cf_sk = container_of(layr, struct caifsock, layer);
-
- switch (flow) {
- case CAIF_CTRLCMD_FLOW_ON_IND:
- dbfs_atomic_inc(&cnt.num_tx_flow_on_ind);
- /* Signal reader that data is available. */
- SET_TX_FLOW_ON(cf_sk);
- wake_up_interruptible(sk_sleep(&cf_sk->sk));
- break;
-
- case CAIF_CTRLCMD_FLOW_OFF_IND:
- dbfs_atomic_inc(&cnt.num_tx_flow_off_ind);
- SET_TX_FLOW_OFF(cf_sk);
- break;
-
- case CAIF_CTRLCMD_INIT_RSP:
- dbfs_atomic_inc(&cnt.num_init_resp);
- /* Signal reader that data is available. */
- caif_assert(STATE_IS_OPEN(cf_sk));
- SET_PENDING_OFF(cf_sk);
- SET_TX_FLOW_ON(cf_sk);
- wake_up_interruptible(sk_sleep(&cf_sk->sk));
- break;
-
- case CAIF_CTRLCMD_DEINIT_RSP:
- dbfs_atomic_inc(&cnt.num_deinit_resp);
- caif_assert(!STATE_IS_OPEN(cf_sk));
- SET_PENDING_OFF(cf_sk);
- if (!STATE_IS_PENDING_DESTROY(cf_sk)) {
- if (sk_sleep(&cf_sk->sk) != NULL)
- wake_up_interruptible(sk_sleep(&cf_sk->sk));
- }
- dbfs_atomic_inc(&cnt.num_deinit);
- sock_put(&cf_sk->sk);
- break;
-
- case CAIF_CTRLCMD_INIT_FAIL_RSP:
- dbfs_atomic_inc(&cnt.num_init_fail_resp);
- caif_assert(STATE_IS_OPEN(cf_sk));
- SET_STATE_CLOSED(cf_sk);
- SET_PENDING_OFF(cf_sk);
- SET_TX_FLOW_OFF(cf_sk);
- wake_up_interruptible(sk_sleep(&cf_sk->sk));
- break;
-
- case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND:
- dbfs_atomic_inc(&cnt.num_remote_shutdown_ind);
- SET_REMOTE_SHUTDOWN(cf_sk);
- /* Use sk_shutdown to indicate remote shutdown indication */
- cf_sk->sk.sk_shutdown |= RCV_SHUTDOWN;
- cf_sk->file_mode = 0;
- wake_up_interruptible(sk_sleep(&cf_sk->sk));
- break;
-
- default:
- pr_debug("CAIF: %s(): Unexpected flow command %d\n",
- __func__, flow);
- }
-}
-
-static void skb_destructor(struct sk_buff *skb)
-{
- dbfs_atomic_inc(&cnt.skb_free);
- dbfs_atomic_dec(&cnt.skb_in_use);
-}
-
-
-static int caif_recvmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *m, size_t buf_len, int flags)
-
-{
- struct sock *sk = sock->sk;
- struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
- struct cfpkt *pkt = NULL;
- size_t len;
- int result;
- struct sk_buff *skb;
- ssize_t ret = -EIO;
- int read_queue_low;
-
- if (cf_sk == NULL) {
- pr_debug("CAIF: %s(): private_data not set!\n",
- __func__);
- ret = -EBADFD;
- goto read_error;
- }
-
- /* Don't do multiple iovec entries yet */
- if (m->msg_iovlen != 1)
- return -EOPNOTSUPP;
-
- if (unlikely(!buf_len))
- return -EINVAL;
-
- 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)) {
- pr_debug("CAIF: %s(): socket is closed (by remote)\n",
- __func__);
- ret = -EPIPE;
- } else {
- pr_debug("CAIF: %s(): socket is closing..\n", __func__);
- ret = -EBADF;
- }
- goto read_error;
- }
- /* Socket is open or opening. */
- if (STATE_IS_PENDING(cf_sk)) {
- pr_debug("CAIF: %s(): socket is opening...\n", __func__);
-
- if (flags & MSG_DONTWAIT) {
- /* We can't block. */
- pr_debug("CAIF: %s():state pending and MSG_DONTWAIT\n",
- __func__);
- ret = -EAGAIN;
- goto read_error;
- }
-
- /*
- * Blocking mode; state is pending and we need to wait
- * for its conclusion.
- */
- release_sock(&cf_sk->sk);
-
- result =
- wait_event_interruptible(*sk_sleep(&cf_sk->sk),
- !STATE_IS_PENDING(cf_sk));
-
- lock_sock(&(cf_sk->sk));
-
- if (result == -ERESTARTSYS) {
- pr_debug("CAIF: %s(): wait_event_interruptible"
- " woken by a signal (1)", __func__);
- ret = -ERESTARTSYS;
- goto read_error;
- }
- }
-
- if (STATE_IS_REMOTE_SHUTDOWN(cf_sk) ||
- !STATE_IS_OPEN(cf_sk) ||
- STATE_IS_PENDING(cf_sk)) {
-
- pr_debug("CAIF: %s(): socket closed\n",
- __func__);
- ret = -ESHUTDOWN;
- goto read_error;
- }
-
- /*
- * Block if we don't have any received buffers.
- * The queue has its own lock.
- */
- while ((pkt = cfpkt_qpeek(cf_sk->pktq)) == NULL) {
-
- if (flags & MSG_DONTWAIT) {
- pr_debug("CAIF: %s(): MSG_DONTWAIT\n", __func__);
- ret = -EAGAIN;
- goto read_error;
- }
- trace_printk("CAIF: %s() wait_event\n", __func__);
-
- /* Let writers in. */
- release_sock(&cf_sk->sk);
-
- /* Block reader until data arrives or socket is closed. */
- if (wait_event_interruptible(*sk_sleep(&cf_sk->sk),
- cfpkt_qpeek(cf_sk->pktq)
- || STATE_IS_REMOTE_SHUTDOWN(cf_sk)
- || !STATE_IS_OPEN(cf_sk)) ==
- -ERESTARTSYS) {
- pr_debug("CAIF: %s():"
- " wait_event_interruptible woken by "
- "a signal, signal_pending(current) = %d\n",
- __func__,
- signal_pending(current));
- return -ERESTARTSYS;
- }
-
- trace_printk("CAIF: %s() awake\n", __func__);
- if (STATE_IS_REMOTE_SHUTDOWN(cf_sk)) {
- pr_debug("CAIF: %s(): "
- "received remote_shutdown indication\n",
- __func__);
- ret = -ESHUTDOWN;
- goto read_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. */
- pr_debug("CAIF: %s(): remote end shutdown!\n",
- __func__);
- ret = -EPIPE;
- goto read_error;
- }
- }
-
- /* The queue has its own lock. */
- len = cfpkt_getlen(pkt);
-
- /* Check max length that can be copied. */
- if (len <= buf_len)
- pkt = cfpkt_dequeue(cf_sk->pktq);
- else {
- pr_debug("CAIF: %s(): user buffer too small (%ld,%ld)\n",
- __func__, (long) len, (long) buf_len);
- if (sock->type == SOCK_SEQPACKET) {
- ret = -EMSGSIZE;
- goto read_error;
- }
- len = buf_len;
- }
-
-
- spin_lock(&cf_sk->read_queue_len_lock);
- cf_sk->read_queue_len--;
- read_queue_low = (cf_sk->read_queue_len < CHNL_SKT_READ_QUEUE_LOW);
- spin_unlock(&cf_sk->read_queue_len_lock);
-
- if (!RX_FLOW_IS_ON(cf_sk) && read_queue_low) {
- dbfs_atomic_inc(&cnt.num_rx_flow_on);
- SET_RX_FLOW_ON(cf_sk);
-
- /* Send flow on. */
- pr_debug("CAIF: %s(): sending flow ON (queue len = %d)\n",
- __func__, cf_sk->read_queue_len);
- caif_assert(cf_sk->layer.dn);
- caif_assert(cf_sk->layer.dn->ctrlcmd);
- (void) cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
- CAIF_MODEMCMD_FLOW_ON_REQ);
-
- caif_assert(cf_sk->read_queue_len >= 0);
- }
-
- skb = cfpkt_tonative(pkt);
- result = skb_copy_datagram_iovec(skb, 0, m->msg_iov, len);
- skb_pull(skb, len);
-
- if (result) {
- pr_debug("CAIF: %s(): copy to_iovec failed\n", __func__);
- cfpkt_destroy(pkt);
- ret = -EFAULT;
- goto read_error;
- }
-
- /* Free packet and remove from queue */
- if (skb->len == 0)
- skb_free_datagram(sk, skb);
-
- /* Let the others in. */
- release_sock(&cf_sk->sk);
- return len;
-
-read_error:
- release_sock(&cf_sk->sk);
-read_error_no_unlock:
- return ret;
-}
-
-/* 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);
- size_t payload_size = msg->msg_iov->iov_len;
- struct cfpkt *pkt = NULL;
- struct caif_payload_info info;
- unsigned char *txbuf;
- ssize_t ret = -EIO;
- int result;
- struct sk_buff *skb;
- caif_assert(msg->msg_iovlen == 1);
-
- if (cf_sk == NULL) {
- pr_debug("CAIF: %s(): private_data not set!\n",
- __func__);
- ret = -EBADFD;
- goto write_error_no_unlock;
- }
-
- if (unlikely(msg->msg_iov->iov_base == NULL)) {
- pr_warning("CAIF: %s(): Buffer is NULL.\n", __func__);
- ret = -EINVAL;
- goto write_error_no_unlock;
- }
-
- if (payload_size > CAIF_MAX_PAYLOAD_SIZE) {
- pr_debug("CAIF: %s(): buffer too long\n", __func__);
- if (sock->type == SOCK_SEQPACKET) {
- ret = -EINVAL;
- goto write_error_no_unlock;
- }
- payload_size = CAIF_MAX_PAYLOAD_SIZE;
- }
-
- /* 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)) {
- pr_debug("CAIF: %s(): socket is closed (by remote)\n",
- __func__);
- ret = -EPIPE;
- } else {
- pr_debug("CAIF: %s(): socket is closing...\n",
- __func__);
- ret = -EBADF;
- }
- goto write_error;
- }
-
- /* Socket is open or opening */
- if (STATE_IS_PENDING(cf_sk)) {
- pr_debug("CAIF: %s(): socket is opening...\n", __func__);
-
- if (msg->msg_flags & MSG_DONTWAIT) {
- /* We can't block */
- trace_printk("CAIF: %s():state pending:"
- "state=MSG_DONTWAIT\n", __func__);
- 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(*sk_sleep(&cf_sk->sk),
- !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) {
- pr_debug("CAIF: %s(): wait_event_interruptible"
- " woken by a signal (1)", __func__);
- ret = -ERESTARTSYS;
- goto write_error;
- }
- }
- if (STATE_IS_REMOTE_SHUTDOWN(cf_sk) ||
- !STATE_IS_OPEN(cf_sk) ||
- STATE_IS_PENDING(cf_sk)) {
-
- pr_debug("CAIF: %s(): socket closed\n",
- __func__);
- 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) {
- trace_printk("CAIF: %s(): MSG_DONTWAIT and tx flow off",
- __func__);
- 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(*sk_sleep(&cf_sk->sk),
- TX_FLOW_IS_ON(cf_sk)
- || !STATE_IS_OPEN(cf_sk)
- || STATE_IS_REMOTE_SHUTDOWN(cf_sk)
- ) == -ERESTARTSYS) {
- pr_debug("CAIF: %s():"
- " wait_event_interruptible woken by a signal",
- __func__);
- 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 */
- pr_debug("CAIF: %s(): remote end shutdown!\n",
- __func__);
- ret = -EPIPE;
- goto write_error;
- }
-
- if (STATE_IS_REMOTE_SHUTDOWN(cf_sk)) {
- pr_debug("CAIF: %s(): "
- "received remote_shutdown indication\n",
- __func__);
- ret = -ESHUTDOWN;
- goto write_error;
- }
- }
-
- pkt = cfpkt_create(payload_size);
- skb = (struct sk_buff *)pkt;
- skb->destructor = skb_destructor;
- skb->sk = sk;
- dbfs_atomic_inc(&cnt.skb_alloc);
- dbfs_atomic_inc(&cnt.skb_in_use);
- if (cfpkt_raw_append(pkt, (void **) &txbuf, payload_size) < 0) {
- pr_debug("CAIF: %s(): cfpkt_raw_append failed\n", __func__);
- cfpkt_destroy(pkt);
- ret = -EINVAL;
- goto write_error;
- }
-
- /* Copy data into buffer. */
- if (copy_from_user(txbuf, msg->msg_iov->iov_base, payload_size)) {
- pr_debug("CAIF: %s(): copy_from_user returned non zero.\n",
- __func__);
- 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, pkt);
-
- if (likely((ret >= 0) || (ret != -EAGAIN)))
- break;
-
- /* EAGAIN - retry */
- if (msg->msg_flags & MSG_DONTWAIT) {
- pr_debug("CAIF: %s(): NONBLOCK and transmit failed,"
- " error = %ld\n", __func__, (long) 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(*sk_sleep(&cf_sk->sk),
- TX_FLOW_IS_ON(cf_sk)
- || !STATE_IS_OPEN(cf_sk)
- || STATE_IS_REMOTE_SHUTDOWN(cf_sk)
- ) == -ERESTARTSYS) {
- pr_debug("CAIF: %s(): wait_event_interruptible"
- " woken by a signal", __func__);
- 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);
- pr_debug("CAIF: %s(): transmit failed, error = %ld\n",
- __func__, (long) ret);
-
- goto write_error;
- }
-
- release_sock(&cf_sk->sk);
- return payload_size;
-
-write_error:
- release_sock(&cf_sk->sk);
-write_error_no_unlock:
- return ret;
-}
-
-static unsigned int caif_poll(struct file *file, struct socket *sock,
- poll_table *wait)
-{
- struct sock *sk = sock->sk;
- struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
- u32 mask = 0;
- poll_wait(file, sk_sleep(sk), wait);
- lock_sock(&(cf_sk->sk));
- if (!STATE_IS_OPEN(cf_sk)) {
- if (!STATE_IS_PENDING(cf_sk))
- mask |= POLLHUP;
- } else {
- if (cfpkt_qpeek(cf_sk->pktq) != NULL)
- mask |= (POLLIN | POLLRDNORM);
- if (TX_FLOW_IS_ON(cf_sk))
- mask |= (POLLOUT | POLLWRNORM);
- }
- release_sock(&cf_sk->sk);
- trace_printk("CAIF: %s(): poll mask=0x%04x\n",
- __func__, mask);
- return mask;
-}
-
-static void drain_queue(struct caifsock *cf_sk)
-{
- struct cfpkt *pkt = NULL;
-
- /* Empty the queue */
- do {
- /* The queue has its own lock */
- if (!cf_sk->pktq)
- break;
-
- pkt = cfpkt_dequeue(cf_sk->pktq);
- if (!pkt)
- break;
- pr_debug("CAIF: %s(): freeing packet from read queue\n",
- __func__);
- cfpkt_destroy(pkt);
-
- } while (1);
-
- cf_sk->read_queue_len = 0;
-}
-
-static int setsockopt(struct socket *sock,
- int lvl, int opt, char __user *ov, unsigned int ol)
-{
- struct sock *sk = sock->sk;
- struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
- int prio, linksel;
- struct ifreq ifreq;
-
- if (STATE_IS_OPEN(cf_sk)) {
- pr_debug("CAIF: %s(): setsockopt "
- "cannot be done on a connected socket\n",
- __func__);
- return -ENOPROTOOPT;
- }
- switch (opt) {
- case CAIFSO_LINK_SELECT:
- if (ol < sizeof(int)) {
- pr_debug("CAIF: %s(): setsockopt"
- " CAIFSO_CHANNEL_CONFIG bad size\n", __func__);
- return -EINVAL;
- }
- if (lvl != SOL_CAIF)
- goto bad_sol;
- if (copy_from_user(&linksel, ov, sizeof(int)))
- return -EINVAL;
- lock_sock(&(cf_sk->sk));
- cf_sk->conn_req.link_selector = linksel;
- release_sock(&cf_sk->sk);
- return 0;
-
- case SO_PRIORITY:
- if (lvl != SOL_SOCKET)
- goto bad_sol;
- if (ol < sizeof(int)) {
- pr_debug("CAIF: %s(): setsockopt"
- " SO_PRIORITY bad size\n", __func__);
- return -EINVAL;
- }
- if (copy_from_user(&prio, ov, sizeof(int)))
- return -EINVAL;
- lock_sock(&(cf_sk->sk));
- cf_sk->conn_req.priority = prio;
- pr_debug("CAIF: %s(): Setting sockopt priority=%d\n", __func__,
- cf_sk->conn_req.priority);
- release_sock(&cf_sk->sk);
- return 0;
-
- case SO_BINDTODEVICE:
- if (lvl != SOL_SOCKET)
- goto bad_sol;
- if (ol < sizeof(struct ifreq)) {
- pr_debug("CAIF: %s(): setsockopt"
- " SO_PRIORITY bad size\n", __func__);
- return -EINVAL;
- }
- if (copy_from_user(&ifreq, ov, sizeof(ifreq)))
- return -EFAULT;
- lock_sock(&(cf_sk->sk));
- strncpy(cf_sk->conn_req.link_name, ifreq.ifr_name,
- sizeof(cf_sk->conn_req.link_name));
- cf_sk->conn_req.link_name
- [sizeof(cf_sk->conn_req.link_name)-1] = 0;
- release_sock(&cf_sk->sk);
- return 0;
-
- case CAIFSO_REQ_PARAM:
- if (lvl != SOL_CAIF)
- goto bad_sol;
- if (cf_sk->sk.sk_protocol != CAIFPROTO_UTIL)
- return -ENOPROTOOPT;
- if (ol > sizeof(cf_sk->conn_req.param.data))
- goto req_param_bad_size;
-
- lock_sock(&(cf_sk->sk));
- cf_sk->conn_req.param.size = ol;
- if (copy_from_user(&cf_sk->conn_req.param.data, ov, ol)) {
- release_sock(&cf_sk->sk);
-req_param_bad_size:
- pr_debug("CAIF: %s(): setsockopt"
- " CAIFSO_CHANNEL_CONFIG bad size\n", __func__);
- return -EINVAL;
- }
-
- release_sock(&cf_sk->sk);
- return 0;
-
- default:
- pr_debug("CAIF: %s(): unhandled option %d\n", __func__, opt);
- return -EINVAL;
- }
-
- return 0;
-bad_sol:
- pr_debug("CAIF: %s(): setsockopt bad level\n", __func__);
- return -ENOPROTOOPT;
-
-}
-
-static 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;
- BUG_ON(sk == NULL);
-
- cf_sk = container_of(sk, struct caifsock, sk);
-
- trace_printk("CAIF: %s(): cf_sk=%p OPEN=%d, TX_FLOW=%d, RX_FLOW=%d\n",
- __func__, cf_sk,
- STATE_IS_OPEN(cf_sk),
- TX_FLOW_IS_ON(cf_sk), RX_FLOW_IS_ON(cf_sk));
-
-
- if (sock->type == SOCK_SEQPACKET || sock->type == SOCK_STREAM)
- sock->state = SS_CONNECTING;
- else
- goto out;
-
- /* I want to be alone on cf_sk (except status and queue) */
- lock_sock(&(cf_sk->sk));
-
- if (sockaddr_len != sizeof(struct sockaddr_caif)) {
- pr_debug("CAIF: %s(): Bad address len (%ld,%lu)\n",
- __func__, (long) sockaddr_len,
- (long unsigned) sizeof(struct sockaddr_caif));
- ret = -EINVAL;
- goto open_error;
- }
-
- if (uservaddr->sa_family != AF_CAIF) {
- pr_debug("CAIF: %s(): Bad address family (%d)\n",
- __func__, uservaddr->sa_family);
- ret = -EAFNOSUPPORT;
- goto open_error;
- }
-
- memcpy(&cf_sk->conn_req.sockaddr, uservaddr,
- sizeof(struct sockaddr_caif));
-
- dbfs_atomic_inc(&cnt.num_open);
- 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 & O_NONBLOCK) {
- pr_debug("CAIF: %s(): O_NONBLOCK"
- " && close pending\n", __func__);
- ret = -EAGAIN;
- goto open_error;
- }
-
- pr_debug("CAIF: %s(): Wait for close response"
- " from remote...\n", __func__);
-
- release_sock(&cf_sk->sk);
-
- /*
- * Blocking mode; close is pending and we need to wait
- * for its conclusion.
- */
- result =
- wait_event_interruptible(*sk_sleep(&cf_sk->sk),
- !STATE_IS_PENDING(cf_sk));
-
- lock_sock(&(cf_sk->sk));
- if (result == -ERESTARTSYS) {
- pr_debug("CAIF: %s(): wait_event_interruptible"
- "woken by a signal (1)", __func__);
- ret = -ERESTARTSYS;
- goto open_error;
- }
- }
- }
-
- /* socket is now either closed, pending open or open */
- if (STATE_IS_OPEN(cf_sk) && !STATE_IS_PENDING(cf_sk)) {
- /* Open */
- pr_debug("CAIF: %s(): Socket is already opened (cf_sk=%p)"
- " check access f_flags = 0x%x file_mode = 0x%x\n",
- __func__, cf_sk, mode, cf_sk->file_mode);
-
- } else {
- /* We are closed or pending open.
- * If closed: send link setup
- * If pending open: link setup already sent (we could have been
- * interrupted by a signal last time)
- */
- if (!STATE_IS_OPEN(cf_sk)) {
- /* First opening of file; connect lower layers: */
- /* Drain queue (very unlikely) */
- drain_queue(cf_sk);
-
- cf_sk->layer.receive = caif_sktrecv_cb;
- SET_STATE_OPEN(cf_sk);
- SET_PENDING_ON(cf_sk);
-
- /* Register this channel. */
- result =
- caif_connect_client(&cf_sk->conn_req,
- &cf_sk->layer);
- if (result < 0) {
- pr_debug("CAIF: %s(): can't register channel\n",
- __func__);
- ret = -EIO;
- SET_STATE_CLOSED(cf_sk);
- SET_PENDING_OFF(cf_sk);
- goto open_error;
- }
- dbfs_atomic_inc(&cnt.num_init);
- }
-
- /* If opened non-blocking, report "success".
- */
- if (flags & O_NONBLOCK) {
- pr_debug("CAIF: %s(): O_NONBLOCK success\n",
- __func__);
- ret = -EINPROGRESS;
- cf_sk->sk.sk_err = -EINPROGRESS;
- goto open_error;
- }
-
- trace_printk("CAIF: %s(): Wait for connect response\n",
- __func__);
-
- /* release lock before waiting */
- release_sock(&cf_sk->sk);
-
- result =
- wait_event_interruptible(*sk_sleep(&cf_sk->sk),
- !STATE_IS_PENDING(cf_sk));
-
- lock_sock(&(cf_sk->sk));
-
- if (result == -ERESTARTSYS) {
- pr_debug("CAIF: %s(): wait_event_interruptible"
- "woken by a signal (2)", __func__);
- ret = -ERESTARTSYS;
- goto open_error;
- }
-
- if (!STATE_IS_OPEN(cf_sk)) {
- /* Lower layers said "no" */
- pr_debug("CAIF: %s(): Closed received\n", __func__);
- ret = -EPIPE;
- goto open_error;
- }
-
- trace_printk("CAIF: %s(): Connect received\n", __func__);
- }
- /* Open is ok */
- cf_sk->file_mode |= mode;
-
- trace_printk("CAIF: %s(): Connected - file mode = %x\n",
- __func__, cf_sk->file_mode);
-
- release_sock(&cf_sk->sk);
- return 0;
-open_error:
- sock->state = SS_UNCONNECTED;
- release_sock(&cf_sk->sk);
-out:
- return ret;
-}
-
-static int caif_shutdown(struct socket *sock, int how)
-{
- struct caifsock *cf_sk = NULL;
- int result = 0;
- int tx_flow_state_was_on;
- struct sock *sk = sock->sk;
-
- trace_printk("CAIF: %s(): enter\n", __func__);
- pr_debug("f_flags=%x\n", sock->file->f_flags);
-
- if (how != SHUT_RDWR)
- return -EOPNOTSUPP;
-
- cf_sk = container_of(sk, struct caifsock, sk);
- if (cf_sk == NULL) {
- pr_debug("CAIF: %s(): COULD NOT FIND SOCKET\n", __func__);
- return -EBADF;
- }
-
- /* I want to be alone on cf_sk (except status queue) */
- lock_sock(&(cf_sk->sk));
- sock_hold(&cf_sk->sk);
-
- /* IS_CLOSED have double meaning:
- * 1) Spontanous Remote Shutdown Request.
- * 2) Ack on a channel teardown(disconnect)
- * Must clear bit in case we previously received
- * remote shudown request.
- */
- if (STATE_IS_OPEN(cf_sk) && !STATE_IS_PENDING(cf_sk)) {
- SET_STATE_CLOSED(cf_sk);
- SET_PENDING_ON(cf_sk);
- tx_flow_state_was_on = TX_FLOW_IS_ON(cf_sk);
- SET_TX_FLOW_OFF(cf_sk);
-
- /* Hold the socket until DEINIT_RSP is received */
- sock_hold(&cf_sk->sk);
- result = caif_disconnect_client(&cf_sk->layer);
-
- if (result < 0) {
- pr_debug("CAIF: %s(): "
- "caif_disconnect_client() failed\n",
- __func__);
- SET_STATE_CLOSED(cf_sk);
- SET_PENDING_OFF(cf_sk);
- SET_TX_FLOW_OFF(cf_sk);
- release_sock(&cf_sk->sk);
- sock_put(&cf_sk->sk);
- return -EIO;
- }
-
- }
- if (STATE_IS_REMOTE_SHUTDOWN(cf_sk)) {
- SET_PENDING_OFF(cf_sk);
- SET_REMOTE_SHUTDOWN_OFF(cf_sk);
- }
-
- /*
- * Socket is no longer in state pending close,
- * and we can release the reference.
- */
-
- dbfs_atomic_inc(&cnt.num_close);
- drain_queue(cf_sk);
- SET_RX_FLOW_ON(cf_sk);
- cf_sk->file_mode = 0;
- sock_put(&cf_sk->sk);
- release_sock(&cf_sk->sk);
- if (!result && (sock->file->f_flags & O_NONBLOCK)) {
- pr_debug("nonblocking shutdown returing -EAGAIN\n");
- return -EAGAIN;
- } else
- return result;
-}
-
-static ssize_t caif_sock_no_sendpage(struct socket *sock,
- struct page *page,
- int offset, size_t size, int flags)
-{
- return -EOPNOTSUPP;
-}
-
-/* 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;
- int res;
- caif_assert(sk != NULL);
- cf_sk = container_of(sk, struct caifsock, sk);
-
- if (cf_sk->debugfs_socket_dir != NULL)
- debugfs_remove_recursive(cf_sk->debugfs_socket_dir);
-
- res = caif_shutdown(sock, SHUT_RDWR);
- if (res && res != -EINPROGRESS)
- return res;
-
- /*
- * FIXME: Shutdown should probably be possible to do async
- * without flushing queues, allowing reception of frames while
- * waiting for DEINIT_IND.
- * Release should always block, to allow secure decoupling of
- * CAIF stack.
- */
- if (!(sock->file->f_flags & O_NONBLOCK)) {
- res = wait_event_interruptible(*sk_sleep(&cf_sk->sk),
- !STATE_IS_PENDING(cf_sk));
-
- if (res == -ERESTARTSYS) {
- pr_debug("CAIF: %s(): wait_event_interruptible"
- "woken by a signal (1)", __func__);
- }
- }
- lock_sock(&(cf_sk->sk));
-
- sock->sk = NULL;
-
- /* 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.
- */
-
- /* Flush out this sockets receive queue. */
- drain_queue(cf_sk);
-
- /* Finally release the socket. */
- SET_STATE_PENDING_DESTROY(cf_sk);
-
- release_sock(&cf_sk->sk);
-
- sock_put(sk);
-
- /*
- * The rest of the cleanup will be handled from the
- * caif_sock_destructor
- */
- return res;
-}
-
-static const struct proto_ops caif_ops = {
- .family = PF_CAIF,
- .owner = THIS_MODULE,
- .release = caif_release,
- .bind = sock_no_bind,
- .connect = caif_connect,
- .socketpair = sock_no_socketpair,
- .accept = sock_no_accept,
- .getname = sock_no_getname,
- .poll = caif_poll,
- .ioctl = sock_no_ioctl,
- .listen = sock_no_listen,
- .shutdown = caif_shutdown,
- .setsockopt = setsockopt,
- .getsockopt = sock_no_getsockopt,
- .sendmsg = caif_sendmsg,
- .recvmsg = caif_recvmsg,
- .mmap = sock_no_mmap,
- .sendpage = caif_sock_no_sendpage,
-};
-
-/* This function is called when a socket is finally destroyed. */
-static void caif_sock_destructor(struct sock *sk)
-{
- struct caifsock *cf_sk = NULL;
- 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)) {
- pr_debug("CAIF: %s(): 0x%p", __func__, sk);
- return;
- }
-
- if (STATE_IS_OPEN(cf_sk)) {
- pr_debug("CAIF: %s(): socket is opened (cf_sk=%p)"
- " file_mode = 0x%x\n", __func__,
- cf_sk, cf_sk->file_mode);
- return;
- }
- drain_queue(cf_sk);
- kfree(cf_sk->pktq);
-
- trace_printk("CAIF: %s(): caif_sock_destructor: Removing socket %s\n",
- __func__, cf_sk->name);
- atomic_dec(&caif_nr_socks);
-}
-
-static int caif_create(struct net *net, struct socket *sock, int protocol,
- int kern)
-{
- struct sock *sk = NULL;
- struct caifsock *cf_sk = NULL;
- int result = 0;
- static struct proto prot = {.name = "PF_CAIF",
- .owner = THIS_MODULE,
- .obj_size = sizeof(struct caifsock),
- };
-
- /*
- * The sock->type specifies the socket type to use.
- * in SEQPACKET mode packet boundaries are enforced.
- */
- if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
- return -ESOCKTNOSUPPORT;
-
- if (net != &init_net)
- return -EAFNOSUPPORT;
-
- if (protocol < 0 || protocol >= CAIFPROTO_MAX)
- return -EPROTONOSUPPORT;
- /*
- * Set the socket state to unconnected. The socket state is really
- * not used at all in the net/core or socket.c but the
- * initialization makes sure that sock->state is not uninitialized.
- */
- sock->state = SS_UNCONNECTED;
-
- sk = sk_alloc(net, PF_CAIF, GFP_KERNEL, &prot);
- if (!sk)
- return -ENOMEM;
-
- cf_sk = container_of(sk, struct caifsock, sk);
-
- /* Store the protocol */
- sk->sk_protocol = (unsigned char) protocol;
-
- spin_lock_init(&cf_sk->read_queue_len_lock);
-
- /* Fill in some information concerning the misc socket. */
- snprintf(cf_sk->name, sizeof(cf_sk->name), "cf_sk%d",
- atomic_read(&caif_nr_socks));
-
- /*
- * Lock in order to try to stop someone from opening the socket
- * too early.
- */
- lock_sock(&(cf_sk->sk));
-
- /* Initialize the nozero default sock structure data. */
- sock_init_data(sock, sk);
- sock->ops = &caif_ops;
- sk->sk_destruct = caif_sock_destructor;
- sk->sk_sndbuf = caif_sockbuf_size;
- sk->sk_rcvbuf = caif_sockbuf_size;
-
- cf_sk->pktq = cfpktq_create();
-
- if (!cf_sk->pktq) {
- pr_err("CAIF: %s(): queue create failed.\n", __func__);
- result = -ENOMEM;
- release_sock(&cf_sk->sk);
- goto err_failed;
- }
- cf_sk->layer.ctrlcmd = caif_sktflowctrl_cb;
- SET_STATE_CLOSED(cf_sk);
- SET_PENDING_OFF(cf_sk);
- SET_TX_FLOW_OFF(cf_sk);
- SET_RX_FLOW_ON(cf_sk);
-
- /* Set default options on configuration */
- cf_sk->conn_req.priority = CAIF_PRIO_NORMAL;
- cf_sk->conn_req.link_selector = CAIF_LINK_HIGH_BANDW;
- cf_sk->conn_req.protocol = protocol;
- /* Increase the number of sockets created. */
- atomic_inc(&caif_nr_socks);
- if (!IS_ERR(debugfsdir)) {
- cf_sk->debugfs_socket_dir =
- debugfs_create_dir(cf_sk->name, debugfsdir);
- debugfs_create_u32("conn_state", S_IRUSR | S_IWUSR,
- cf_sk->debugfs_socket_dir, &cf_sk->conn_state);
- debugfs_create_u32("flow_state", S_IRUSR | S_IWUSR,
- cf_sk->debugfs_socket_dir, &cf_sk->flow_state);
- debugfs_create_u32("read_queue_len", S_IRUSR | S_IWUSR,
- cf_sk->debugfs_socket_dir,
- (u32 *) &cf_sk->read_queue_len);
- debugfs_create_u32("identity", S_IRUSR | S_IWUSR,
- cf_sk->debugfs_socket_dir,
- (u32 *) &cf_sk->layer.id);
- }
- release_sock(&cf_sk->sk);
- return 0;
-err_failed:
- sk_free(sk);
- return result;
-}
-
-static struct net_proto_family caif_family_ops = {
- .family = PF_CAIF,
- .create = caif_create,
- .owner = THIS_MODULE,
-};
-
-static int af_caif_init(void)
-{
- int err;
- err = sock_register(&caif_family_ops);
-
- if (!err)
- return err;
-
- return 0;
-}
-
-static int __init caif_sktinit_module(void)
-{
- int stat;
-#ifdef CONFIG_DEBUG_FS
- debugfsdir = debugfs_create_dir("chnl_skt", NULL);
- if (!IS_ERR(debugfsdir)) {
- debugfs_create_u32("skb_inuse", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.skb_in_use);
- debugfs_create_u32("skb_alloc", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.skb_alloc);
- debugfs_create_u32("skb_free", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.skb_free);
- debugfs_create_u32("num_sockets", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &caif_nr_socks);
- debugfs_create_u32("num_open", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.num_open);
- debugfs_create_u32("num_close", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.num_close);
- debugfs_create_u32("num_init", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.num_init);
- debugfs_create_u32("num_init_resp", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.num_init_resp);
- debugfs_create_u32("num_init_fail_resp", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.num_init_fail_resp);
- debugfs_create_u32("num_deinit", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.num_deinit);
- debugfs_create_u32("num_deinit_resp", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.num_deinit_resp);
- debugfs_create_u32("num_remote_shutdown_ind",
- S_IRUSR | S_IWUSR, debugfsdir,
- (u32 *) &cnt.num_remote_shutdown_ind);
- debugfs_create_u32("num_tx_flow_off_ind", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.num_tx_flow_off_ind);
- debugfs_create_u32("num_tx_flow_on_ind", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.num_tx_flow_on_ind);
- debugfs_create_u32("num_rx_flow_off", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.num_rx_flow_off);
- debugfs_create_u32("num_rx_flow_on", S_IRUSR | S_IWUSR,
- debugfsdir,
- (u32 *) &cnt.num_rx_flow_on);
- }
-#endif
- stat = af_caif_init();
- if (stat) {
- pr_err("CAIF: %s(): Failed to initialize CAIF socket layer.",
- __func__);
- return stat;
- }
- return 0;
-}
-
-static void __exit caif_sktexit_module(void)
-{
- sock_unregister(PF_CAIF);
- if (debugfsdir != NULL)
- debugfs_remove_recursive(debugfsdir);
-}
-
-module_init(caif_sktinit_module);
-module_exit(caif_sktexit_module);
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ * Author: Sjur Brendeland sjur.brandeland@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 <linux/uaccess.h>
+#include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/caif/caif_socket.h>
+#include <asm/atomic.h>
+#include <net/sock.h>
+#include <net/tcp_states.h>
+#include <net/caif/caif_layer.h>
+#include <net/caif/caif_dev.h>
+#include <net/caif/cfpkt.h>
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETPROTO(AF_CAIF);
+
+#define CAIF_DEF_SNDBUF (CAIF_MAX_PAYLOAD_SIZE*10)
+#define CAIF_DEF_RCVBUF (CAIF_MAX_PAYLOAD_SIZE*100)
+
+/*
+ * CAIF state is re-using the TCP socket states.
+ * caif_states stored in sk_state reflect the state as reported by
+ * the CAIF stack, while sk_socket->state is the state of the socket.
+ */
+enum caif_states {
+ CAIF_CONNECTED = TCP_ESTABLISHED,
+ CAIF_CONNECTING = TCP_SYN_SENT,
+ CAIF_DISCONNECTED = TCP_CLOSE
+};
+
+#define TX_FLOW_ON_BIT 1
+#define RX_FLOW_ON_BIT 2
+
+static struct dentry *debugfsdir;
+
+#ifdef CONFIG_DEBUG_FS
+struct debug_fs_counter {
+ atomic_t caif_nr_socks;
+ atomic_t num_connect_req;
+ atomic_t num_connect_resp;
+ atomic_t num_connect_fail_resp;
+ atomic_t num_disconnect;
+ 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;
+};
+struct debug_fs_counter cnt;
+#define dbfs_atomic_inc(v) atomic_inc(v)
+#define dbfs_atomic_dec(v) atomic_dec(v)
+#else
+#define dbfs_atomic_inc(v)
+#define dbfs_atomic_dec(v)
+#endif
+
+struct caifsock {
+ struct sock sk; /* must be first member */
+ struct cflayer layer;
+ char name[CAIF_LAYER_NAME_SZ]; /* Used for debugging */
+ u32 flow_state;
+ struct caif_connect_request conn_req;
+ struct mutex readlock;
+ struct dentry *debugfs_socket_dir;
+};
+
+static int rx_flow_is_on(struct caifsock *cf_sk)
+{
+ return test_bit(RX_FLOW_ON_BIT,
+ (void *) &cf_sk->flow_state);
+}
+
+static int tx_flow_is_on(struct caifsock *cf_sk)
+{
+ return test_bit(TX_FLOW_ON_BIT,
+ (void *) &cf_sk->flow_state);
+}
+
+static void set_rx_flow_off(struct caifsock *cf_sk)
+{
+ clear_bit(RX_FLOW_ON_BIT,
+ (void *) &cf_sk->flow_state);
+}
+
+static void set_rx_flow_on(struct caifsock *cf_sk)
+{
+ set_bit(RX_FLOW_ON_BIT,
+ (void *) &cf_sk->flow_state);
+}
+
+static void set_tx_flow_off(struct caifsock *cf_sk)
+{
+ clear_bit(TX_FLOW_ON_BIT,
+ (void *) &cf_sk->flow_state);
+}
+
+static void set_tx_flow_on(struct caifsock *cf_sk)
+{
+ set_bit(TX_FLOW_ON_BIT,
+ (void *) &cf_sk->flow_state);
+}
+
+static void caif_read_lock(struct sock *sk)
+{
+ struct caifsock *cf_sk;
+ cf_sk = container_of(sk, struct caifsock, sk);
+ mutex_lock(&cf_sk->readlock);
+}
+
+static void caif_read_unlock(struct sock *sk)
+{
+ struct caifsock *cf_sk;
+ cf_sk = container_of(sk, struct caifsock, sk);
+ mutex_unlock(&cf_sk->readlock);
+}
+
+int sk_rcvbuf_lowwater(struct caifsock *cf_sk)
+{
+ /* A quarter of full buffer is used a low water mark */
+ return cf_sk->sk.sk_rcvbuf / 4;
+}
+
+void caif_flow_ctrl(struct sock *sk, int mode)
+{
+ struct caifsock *cf_sk;
+ cf_sk = container_of(sk, struct caifsock, sk);
+ if (cf_sk->layer.dn)
+ cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, mode);
+}
+
+/*
+ * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are
+ * not dropped, but CAIF is sending flow off instead.
+ */
+int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+ int err;
+ int skb_len;
+ unsigned long flags;
+ struct sk_buff_head *list = &sk->sk_receive_queue;
+ struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
+
+ if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
+ (unsigned)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) {
+ trace_printk("CAIF: %s():"
+ " sending flow OFF (queue len = %d %d)\n",
+ __func__,
+ atomic_read(&cf_sk->sk.sk_rmem_alloc),
+ sk_rcvbuf_lowwater(cf_sk));
+ set_rx_flow_off(cf_sk);
+ if (cf_sk->layer.dn)
+ cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
+ CAIF_MODEMCMD_FLOW_OFF_REQ);
+ }
+
+ err = sk_filter(sk, skb);
+ if (err)
+ return err;
+ if (!sk_rmem_schedule(sk, skb->truesize) && rx_flow_is_on(cf_sk)) {
+ set_rx_flow_off(cf_sk);
+ trace_printk("CAIF: %s():"
+ " sending flow OFF due to rmem_schedule\n",
+ __func__);
+ if (cf_sk->layer.dn)
+ cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
+ CAIF_MODEMCMD_FLOW_OFF_REQ);
+ }
+ skb->dev = NULL;
+ skb_set_owner_r(skb, sk);
+ /* Cache the SKB length before we tack it onto the receive
+ * queue. Once it is added it no longer belongs to us and
+ * may be freed by other threads of control pulling packets
+ * from the queue.
+ */
+ skb_len = skb->len;
+ spin_lock_irqsave(&list->lock, flags);
+ if (!sock_flag(sk, SOCK_DEAD))
+ __skb_queue_tail(list, skb);
+ spin_unlock_irqrestore(&list->lock, flags);
+
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_data_ready(sk, skb_len);
+ else
+ kfree_skb(skb);
+ return 0;
+}
+
+/* Packet Receive Callback function called from CAIF Stack */
+static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt)
+{
+ struct caifsock *cf_sk;
+ struct sk_buff *skb;
+
+ cf_sk = container_of(layr, struct caifsock, layer);
+ skb = cfpkt_tonative(pkt);
+
+ if (unlikely(cf_sk->sk.sk_state != CAIF_CONNECTED)) {
+ cfpkt_destroy(pkt);
+ return 0;
+ }
+ caif_queue_rcv_skb(&cf_sk->sk, skb);
+ return 0;
+}
+
+/* Packet Control Callback function called from CAIF */
+static void caif_ctrl_cb(struct cflayer *layr,
+ enum caif_ctrlcmd flow,
+ int phyid)
+{
+ struct caifsock *cf_sk = container_of(layr, struct caifsock, layer);
+ switch (flow) {
+ case CAIF_CTRLCMD_FLOW_ON_IND:
+ /* OK from modem to start sending again */
+ dbfs_atomic_inc(&cnt.num_tx_flow_on_ind);
+ set_tx_flow_on(cf_sk);
+ cf_sk->sk.sk_state_change(&cf_sk->sk);
+ break;
+
+ case CAIF_CTRLCMD_FLOW_OFF_IND:
+ /* Modem asks us to shut up */
+ dbfs_atomic_inc(&cnt.num_tx_flow_off_ind);
+ set_tx_flow_off(cf_sk);
+ cf_sk->sk.sk_state_change(&cf_sk->sk);
+ break;
+
+ case CAIF_CTRLCMD_INIT_RSP:
+ /* We're now connected */
+ dbfs_atomic_inc(&cnt.num_connect_resp);
+ cf_sk->sk.sk_state = CAIF_CONNECTED;
+ set_tx_flow_on(cf_sk);
+ cf_sk->sk.sk_state_change(&cf_sk->sk);
+ break;
+
+ case CAIF_CTRLCMD_DEINIT_RSP:
+ /* We're now disconnected */
+ cf_sk->sk.sk_state = CAIF_DISCONNECTED;
+ cf_sk->sk.sk_state_change(&cf_sk->sk);
+ cfcnfg_release_adap_layer(&cf_sk->layer);
+ break;
+
+ case CAIF_CTRLCMD_INIT_FAIL_RSP:
+ /* Connect request failed */
+ dbfs_atomic_inc(&cnt.num_connect_fail_resp);
+ cf_sk->sk.sk_err = ECONNREFUSED;
+ cf_sk->sk.sk_state = CAIF_DISCONNECTED;
+ cf_sk->sk.sk_shutdown = SHUTDOWN_MASK;
+ /*
+ * Socket "standards" seems to require POLLOUT to
+ * be set at connect failure.
+ */
+ set_tx_flow_on(cf_sk);
+ cf_sk->sk.sk_state_change(&cf_sk->sk);
+ break;
+
+ case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND:
+ /* Modem has closed this connection, or device is down. */
+ dbfs_atomic_inc(&cnt.num_remote_shutdown_ind);
+ cf_sk->sk.sk_shutdown = SHUTDOWN_MASK;
+ cf_sk->sk.sk_err = ECONNRESET;
+ set_rx_flow_on(cf_sk);
+ cf_sk->sk.sk_error_report(&cf_sk->sk);
+ break;
+
+ default:
+ pr_debug("CAIF: %s(): Unexpected flow command %d\n",
+ __func__, flow);
+ }
+}
+
+static void caif_check_flow_release(struct sock *sk)
+{
+ struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
+
+ if (cf_sk->layer.dn == NULL || cf_sk->layer.dn->modemcmd == NULL)
+ return;
+ if (rx_flow_is_on(cf_sk))
+ return;
+
+ if (atomic_read(&sk->sk_rmem_alloc) <= sk_rcvbuf_lowwater(cf_sk)) {
+ dbfs_atomic_inc(&cnt.num_rx_flow_on);
+ set_rx_flow_on(cf_sk);
+ cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
+ CAIF_MODEMCMD_FLOW_ON_REQ);
+ }
+}
+/*
+ * Copied from sock.c:sock_queue_rcv_skb(), and added check that user buffer
+ * has sufficient size.
+ */
+
+static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t buf_len, int flags)
+
+{
+ struct sock *sk = sock->sk;
+ struct sk_buff *skb;
+ int ret = 0;
+ int len;
+
+ if (unlikely(!buf_len))
+ return -EINVAL;
+
+ skb = skb_recv_datagram(sk, flags, 0 , &ret);
+ if (!skb)
+ goto read_error;
+
+ len = skb->len;
+
+ if (skb && skb->len > buf_len && !(flags & MSG_PEEK)) {
+ len = buf_len;
+ /*
+ * Push skb back on receive queue if buffer too small.
+ * This has a built-in race where multi-threaded receive
+ * may get packet in wrong order, but multiple read does
+ * not really guarantee ordered delivery anyway.
+ * Let's optimize for speed without taking locks.
+ */
+
+ skb_queue_head(&sk->sk_receive_queue, skb);
+ ret = -EMSGSIZE;
+ goto read_error;
+ }
+
+ ret = skb_copy_datagram_iovec(skb, 0, m->msg_iov, len);
+ if (ret)
+ goto read_error;
+
+ skb_free_datagram(sk, skb);
+
+ caif_check_flow_release(sk);
+
+ return len;
+
+read_error:
+ return ret;
+}
+
+
+/* Copied from unix_stream_wait_data, identical except for lock call. */
+static long caif_stream_data_wait(struct sock *sk, long timeo)
+{
+ DEFINE_WAIT(wait);
+ lock_sock(sk);
+
+ for (;;) {
+ prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+
+ if (!skb_queue_empty(&sk->sk_receive_queue) ||
+ sk->sk_err ||
+ sk->sk_state != CAIF_CONNECTED ||
+ sock_flag(sk, SOCK_DEAD) ||
+ (sk->sk_shutdown & RCV_SHUTDOWN) ||
+ signal_pending(current) ||
+ !timeo)
+ break;
+
+ set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+ release_sock(sk);
+ timeo = schedule_timeout(timeo);
+ lock_sock(sk);
+ clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
+ }
+
+ finish_wait(sk_sleep(sk), &wait);
+ release_sock(sk);
+ return timeo;
+}
+
+
+/*
+ * Copied from unix_stream_recvmsg, but removed credit checks,
+ * changed locking calls, changed address handling.
+ */
+static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t size,
+ int flags)
+{
+ struct sock *sk = sock->sk;
+ int copied = 0;
+ int target;
+ int err = 0;
+ long timeo;
+
+ err = -EOPNOTSUPP;
+ if (flags&MSG_OOB)
+ goto out;
+
+ msg->msg_namelen = 0;
+
+ /*
+ * Lock the socket to prevent queue disordering
+ * while sleeps in memcpy_tomsg
+ */
+ err = -EAGAIN;
+ if (sk->sk_state == CAIF_CONNECTING)
+ goto out;
+
+ caif_read_lock(sk);
+ target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
+ timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
+
+ do {
+ int chunk;
+ struct sk_buff *skb;
+
+ lock_sock(sk);
+ skb = skb_dequeue(&sk->sk_receive_queue);
+ caif_check_flow_release(sk);
+
+ if (skb == NULL) {
+ if (copied >= target)
+ goto unlock;
+ /*
+ * POSIX 1003.1g mandates this order.
+ */
+ err = sock_error(sk);
+ if (err)
+ goto unlock;
+ err = -ECONNRESET;
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ goto unlock;
+
+ err = -EPIPE;
+ if (sk->sk_state != CAIF_CONNECTED)
+ goto unlock;
+ if (sock_flag(sk, SOCK_DEAD))
+ goto unlock;
+
+ release_sock(sk);
+
+ err = -EAGAIN;
+ if (!timeo)
+ break;
+
+ caif_read_unlock(sk);
+
+ timeo = caif_stream_data_wait(sk, timeo);
+
+ if (signal_pending(current)) {
+ err = sock_intr_errno(timeo);
+ goto out;
+ }
+ caif_read_lock(sk);
+ continue;
+unlock:
+ release_sock(sk);
+ break;
+ }
+ release_sock(sk);
+ chunk = min_t(unsigned int, skb->len, size);
+ if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
+ skb_queue_head(&sk->sk_receive_queue, skb);
+ if (copied == 0)
+ copied = -EFAULT;
+ break;
+ }
+ copied += chunk;
+ size -= chunk;
+
+ /* Mark read part of skb as used */
+ if (!(flags & MSG_PEEK)) {
+ skb_pull(skb, chunk);
+
+ /* put the skb back if we didn't use it up. */
+ if (skb->len) {
+ skb_queue_head(&sk->sk_receive_queue, skb);
+ break;
+ }
+ kfree_skb(skb);
+
+ } else {
+ /*
+ * It is questionable, see note in unix_dgram_recvmsg.
+ */
+ /* put message back and return */
+ skb_queue_head(&sk->sk_receive_queue, skb);
+ break;
+ }
+ } while (size);
+ caif_read_unlock(sk);
+
+out:
+ return copied ? : err;
+}
+
+/*
+ * Copied from sock.c:sock_wait_for_wmem, but change to wait for
+ * CAIF flow-on and sock_writable.
+ */
+static long caif_wait_for_flow_on(struct caifsock *cf_sk,
+ int wait_writeable, long timeo, int *err)
+{
+ struct sock *sk = &cf_sk->sk;
+ DEFINE_WAIT(wait);
+ for (;;) {
+ *err = 0;
+ if (tx_flow_is_on(cf_sk) &&
+ (!wait_writeable || sock_writeable(&cf_sk->sk)))
+ break;
+ *err = -ETIMEDOUT;
+ if (!timeo)
+ break;
+ *err = -ERESTARTSYS;
+ if (signal_pending(current))
+ break;
+ prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+ *err = -ECONNRESET;
+ if (sk->sk_shutdown & SHUTDOWN_MASK)
+ break;
+ *err = -sk->sk_err;
+ if (sk->sk_err)
+ break;
+ *err = -EPIPE;
+ if (cf_sk->sk.sk_state != CAIF_CONNECTED)
+ break;
+ timeo = schedule_timeout(timeo);
+ }
+ finish_wait(sk_sleep(sk), &wait);
+ return timeo;
+}
+
+/*
+ * Transmit a SKB. The device may temporarily request re-transmission
+ * by returning EAGAIN.
+ */
+static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk,
+ int noblock, long timeo)
+{
+ struct cfpkt *pkt;
+ int ret, loopcnt = 0;
+
+ pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb);
+ memset(cfpkt_info(pkt), 0, sizeof(struct caif_payload_info));
+ do {
+
+ ret = -ETIMEDOUT;
+
+ /* Slight paranoia, probably not needed. */
+ if (unlikely(loopcnt++ > 1000)) {
+ pr_warning("CAIF: %s(): transmit retries failed,"
+ " error = %d\n", __func__, ret);
+ break;
+ }
+
+ if (cf_sk->layer.dn != NULL)
+ ret = cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt);
+ if (likely(ret >= 0))
+ break;
+ /* if transmit return -EAGAIN, then retry */
+ if (noblock && ret == -EAGAIN)
+ break;
+ timeo = caif_wait_for_flow_on(cf_sk, 0, timeo, &ret);
+ if (signal_pending(current)) {
+ ret = sock_intr_errno(timeo);
+ break;
+ }
+ if (ret)
+ break;
+ if (cf_sk->sk.sk_state != CAIF_CONNECTED ||
+ sock_flag(&cf_sk->sk, SOCK_DEAD) ||
+ (cf_sk->sk.sk_shutdown & RCV_SHUTDOWN)) {
+ ret = -EPIPE;
+ cf_sk->sk.sk_err = EPIPE;
+ break;
+ }
+ } while (ret == -EAGAIN);
+ return ret;
+}
+
+/* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */
+static int caif_seqpkt_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);
+ int buffer_size;
+ int ret = 0;
+ struct sk_buff *skb = NULL;
+ int noblock;
+ long timeo;
+ caif_assert(cf_sk);
+ ret = sock_error(sk);
+ if (ret)
+ goto err;
+
+ ret = -EOPNOTSUPP;
+ if (msg->msg_flags&MSG_OOB)
+ goto err;
+
+ ret = -EOPNOTSUPP;
+ if (msg->msg_namelen)
+ goto err;
+
+ ret = -EINVAL;
+ if (unlikely(msg->msg_iov->iov_base == NULL))
+ goto err;
+ noblock = msg->msg_flags & MSG_DONTWAIT;
+
+ buffer_size = len + CAIF_NEEDED_HEADROOM + CAIF_NEEDED_TAILROOM;
+
+ ret = -EMSGSIZE;
+ if (buffer_size > CAIF_MAX_PAYLOAD_SIZE)
+ goto err;
+
+ timeo = sock_sndtimeo(sk, noblock);
+ timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk),
+ 1, timeo, &ret);
+
+ ret = -EPIPE;
+ if (cf_sk->sk.sk_state != CAIF_CONNECTED ||
+ sock_flag(sk, SOCK_DEAD) ||
+ (sk->sk_shutdown & RCV_SHUTDOWN))
+ goto err;
+
+ ret = -ENOMEM;
+ skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret);
+ if (!skb)
+ goto err;
+ skb_reserve(skb, CAIF_NEEDED_HEADROOM);
+
+ ret = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
+
+ if (ret)
+ goto err;
+ ret = transmit_skb(skb, cf_sk, noblock, timeo);
+ if (ret < 0)
+ goto err;
+ return len;
+err:
+ kfree_skb(skb);
+ return ret;
+}
+
+/*
+ * Copied from unix_stream_sendmsg and adapted to CAIF:
+ * Changed removed permission handling and added waiting for flow on
+ * and other minor adaptations.
+ */
+static int caif_stream_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);
+ int err, size;
+ struct sk_buff *skb;
+ int sent = 0;
+ long timeo;
+
+ err = -EOPNOTSUPP;
+
+ if (unlikely(msg->msg_flags&MSG_OOB))
+ goto out_err;
+
+ if (unlikely(msg->msg_namelen))
+ goto out_err;
+
+ timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
+ timeo = caif_wait_for_flow_on(cf_sk, 1, timeo, &err);
+
+ if (unlikely(sk->sk_shutdown & SEND_SHUTDOWN))
+ goto pipe_err;
+
+ while (sent < len) {
+
+ size = len-sent;
+
+ if (size > CAIF_MAX_PAYLOAD_SIZE)
+ size = CAIF_MAX_PAYLOAD_SIZE;
+
+ /* If size is more than half of sndbuf, chop up message */
+ if (size > ((sk->sk_sndbuf >> 1) - 64))
+ size = (sk->sk_sndbuf >> 1) - 64;
+
+ if (size > SKB_MAX_ALLOC)
+ size = SKB_MAX_ALLOC;
+
+ skb = sock_alloc_send_skb(sk,
+ size + CAIF_NEEDED_HEADROOM
+ + CAIF_NEEDED_TAILROOM,
+ msg->msg_flags&MSG_DONTWAIT,
+ &err);
+ if (skb == NULL)
+ goto out_err;
+
+ skb_reserve(skb, CAIF_NEEDED_HEADROOM);
+ /*
+ * If you pass two values to the sock_alloc_send_skb
+ * it tries to grab the large buffer with GFP_NOFS
+ * (which can fail easily), and if it fails grab the
+ * fallback size buffer which is under a page and will
+ * succeed. [Alan]
+ */
+ size = min_t(int, size, skb_tailroom(skb));
+
+ err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
+ if (err) {
+ kfree_skb(skb);
+ goto out_err;
+ }
+ err = transmit_skb(skb, cf_sk,
+ msg->msg_flags&MSG_DONTWAIT, timeo);
+ if (err < 0) {
+ kfree_skb(skb);
+ goto pipe_err;
+ }
+ sent += size;
+ }
+
+ return sent;
+
+pipe_err:
+ if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
+ send_sig(SIGPIPE, current, 0);
+ err = -EPIPE;
+out_err:
+ return sent ? : err;
+}
+
+static int setsockopt(struct socket *sock,
+ int lvl, int opt, char __user *ov, unsigned int ol)
+{
+ struct sock *sk = sock->sk;
+ struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
+ int prio, linksel;
+ struct ifreq ifreq;
+
+ if (cf_sk->sk.sk_socket->state != SS_UNCONNECTED)
+ return -ENOPROTOOPT;
+
+ switch (opt) {
+ case CAIFSO_LINK_SELECT:
+ if (ol < sizeof(int))
+ return -EINVAL;
+ if (lvl != SOL_CAIF)
+ goto bad_sol;
+ if (copy_from_user(&linksel, ov, sizeof(int)))
+ return -EINVAL;
+ lock_sock(&(cf_sk->sk));
+ cf_sk->conn_req.link_selector = linksel;
+ release_sock(&cf_sk->sk);
+ return 0;
+
+ case SO_PRIORITY:
+ if (lvl != SOL_SOCKET)
+ goto bad_sol;
+ if (ol < sizeof(int))
+ return -EINVAL;
+ if (copy_from_user(&prio, ov, sizeof(int)))
+ return -EINVAL;
+ lock_sock(&(cf_sk->sk));
+ cf_sk->conn_req.priority = prio;
+ release_sock(&cf_sk->sk);
+ return 0;
+
+ case SO_BINDTODEVICE:
+ if (lvl != SOL_SOCKET)
+ goto bad_sol;
+ if (ol < sizeof(struct ifreq))
+ return -EINVAL;
+ if (copy_from_user(&ifreq, ov, sizeof(ifreq)))
+ return -EFAULT;
+ lock_sock(&(cf_sk->sk));
+ strncpy(cf_sk->conn_req.link_name, ifreq.ifr_name,
+ sizeof(cf_sk->conn_req.link_name));
+ cf_sk->conn_req.link_name
+ [sizeof(cf_sk->conn_req.link_name)-1] = 0;
+ release_sock(&cf_sk->sk);
+ return 0;
+
+ case CAIFSO_REQ_PARAM:
+ if (lvl != SOL_CAIF)
+ goto bad_sol;
+ if (cf_sk->sk.sk_protocol != CAIFPROTO_UTIL)
+ return -ENOPROTOOPT;
+ lock_sock(&(cf_sk->sk));
+ cf_sk->conn_req.param.size = ol;
+ if (ol > sizeof(cf_sk->conn_req.param.data) ||
+ copy_from_user(&cf_sk->conn_req.param.data, ov, ol)) {
+ release_sock(&cf_sk->sk);
+ return -EINVAL;
+ }
+ release_sock(&cf_sk->sk);
+ return 0;
+
+ default:
+ return -ENOPROTOOPT;
+ }
+
+ return 0;
+bad_sol:
+ return -ENOPROTOOPT;
+
+}
+
+/*
+ * caif_connect() - Connect a CAIF Socket
+ * Copied and modified af_irda.c:irda_connect().
+ *
+ * Note : by consulting "errno", the user space caller may learn the cause
+ * of the failure. Most of them are visible in the function, others may come
+ * from subroutines called and are listed here :
+ * o -EAFNOSUPPORT: bad socket family or type.
+ * o -ESOCKTNOSUPPORT: bad socket type or protocol
+ * o -EINVAL: bad socket address, or CAIF link type
+ * o -ECONNREFUSED: remote end refused the connection.
+ * o -EINPROGRESS: connect request sent but timed out (or non-blocking)
+ * o -EISCONN: already connected.
+ * o -ETIMEDOUT: Connection timed out (send timeout)
+ * o -ENODEV: No link layer to send request
+ * o -ECONNRESET: Received Shutdown indication or lost link layer
+ * o -ENOMEM: Out of memory
+ *
+ * State Strategy:
+ * o sk_state: holds the CAIF_* protocol state, it's updated by
+ * caif_ctrl_cb.
+ * o sock->state: holds the SS_* socket state and is updated by connect and
+ * disconnect.
+ */
+static int caif_connect(struct socket *sock, struct sockaddr *uaddr,
+ int addr_len, int flags)
+{
+ struct sock *sk = sock->sk;
+ struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
+ long timeo;
+ int err;
+ lock_sock(sk);
+
+ err = -EAFNOSUPPORT;
+ if (uaddr->sa_family != AF_CAIF)
+ goto out;
+
+ err = -ESOCKTNOSUPPORT;
+ if (unlikely(!(sk->sk_type == SOCK_STREAM &&
+ cf_sk->sk.sk_protocol == CAIFPROTO_AT) &&
+ sk->sk_type != SOCK_SEQPACKET))
+ goto out;
+ switch (sock->state) {
+ case SS_UNCONNECTED:
+ /* Normal case, a fresh connect */
+ caif_assert(sk->sk_state == CAIF_DISCONNECTED);
+ break;
+ case SS_CONNECTING:
+ switch (sk->sk_state) {
+ case CAIF_CONNECTED:
+ sock->state = SS_CONNECTED;
+ err = -EISCONN;
+ goto out;
+ case CAIF_DISCONNECTED:
+ /* Reconnect allowed */
+ break;
+ case CAIF_CONNECTING:
+ err = -EALREADY;
+ if (flags & O_NONBLOCK)
+ goto out;
+ goto wait_connect;
+ }
+ break;
+ case SS_CONNECTED:
+ caif_assert(sk->sk_state == CAIF_CONNECTED ||
+ sk->sk_state == CAIF_DISCONNECTED);
+ if (sk->sk_shutdown & SHUTDOWN_MASK) {
+ /* Allow re-connect after SHUTDOWN_IND */
+ caif_disconnect_client(&cf_sk->layer);
+ break;
+ }
+ /* No reconnect on a seqpacket socket */
+ err = -EISCONN;
+ goto out;
+ case SS_DISCONNECTING:
+ case SS_FREE:
+ caif_assert(1); /*Should never happen */
+ break;
+ }
+ sk->sk_state = CAIF_DISCONNECTED;
+ sock->state = SS_UNCONNECTED;
+ sk_stream_kill_queues(&cf_sk->sk);
+
+ err = -EINVAL;
+ if (addr_len != sizeof(struct sockaddr_caif) ||
+ !uaddr)
+ goto out;
+
+ memcpy(&cf_sk->conn_req.sockaddr, uaddr,
+ sizeof(struct sockaddr_caif));
+
+ /* Move to connecting socket, start sending Connect Requests */
+ sock->state = SS_CONNECTING;
+ sk->sk_state = CAIF_CONNECTING;
+
+ dbfs_atomic_inc(&cnt.num_connect_req);
+ cf_sk->layer.receive = caif_sktrecv_cb;
+ err = caif_connect_client(&cf_sk->conn_req,
+ &cf_sk->layer);
+ if (err < 0) {
+ cf_sk->sk.sk_socket->state = SS_UNCONNECTED;
+ cf_sk->sk.sk_state = CAIF_DISCONNECTED;
+ goto out;
+ }
+
+ err = -EINPROGRESS;
+wait_connect:
+
+ if (sk->sk_state != CAIF_CONNECTED && (flags & O_NONBLOCK))
+ goto out;
+
+ timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
+
+ release_sock(sk);
+ err = wait_event_interruptible_timeout(*sk_sleep(sk),
+ sk->sk_state != CAIF_CONNECTING,
+ timeo);
+ lock_sock(sk);
+ if (err < 0)
+ goto out; /* -ERESTARTSYS */
+ if (err == 0 && sk->sk_state != CAIF_CONNECTED) {
+ err = -ETIMEDOUT;
+ goto out;
+ }
+
+ if (sk->sk_state != CAIF_CONNECTED) {
+ sock->state = SS_UNCONNECTED;
+ err = sock_error(sk);
+ if (!err)
+ err = -ECONNREFUSED;
+ goto out;
+ }
+ sock->state = SS_CONNECTED;
+ err = 0;
+out:
+ release_sock(sk);
+ return err;
+}
+
+
+/*
+ * caif_release() - Disconnect a CAIF Socket
+ * Copied and modified af_irda.c:irda_release().
+ */
+static int caif_release(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
+ int res = 0;
+
+ if (!sk)
+ return 0;
+
+ set_tx_flow_off(cf_sk);
+
+ /*
+ * Ensure that packets are not queued after this point in time.
+ * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock,
+ * this ensures no packets when sock is dead.
+ */
+ spin_lock(&sk->sk_receive_queue.lock);
+ sock_set_flag(sk, SOCK_DEAD);
+ spin_unlock(&sk->sk_receive_queue.lock);
+ sock->sk = NULL;
+
+ dbfs_atomic_inc(&cnt.num_disconnect);
+
+ if (cf_sk->debugfs_socket_dir != NULL)
+ debugfs_remove_recursive(cf_sk->debugfs_socket_dir);
+
+ lock_sock(&(cf_sk->sk));
+ sk->sk_state = CAIF_DISCONNECTED;
+ sk->sk_shutdown = SHUTDOWN_MASK;
+
+ if (cf_sk->sk.sk_socket->state == SS_CONNECTED ||
+ cf_sk->sk.sk_socket->state == SS_CONNECTING)
+ res = caif_disconnect_client(&cf_sk->layer);
+
+ cf_sk->sk.sk_socket->state = SS_DISCONNECTING;
+ wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP);
+
+ sock_orphan(sk);
+ cf_sk->layer.dn = NULL;
+ sk_stream_kill_queues(&cf_sk->sk);
+ release_sock(sk);
+ sock_put(sk);
+ return res;
+}
+
+/* Copied from af_unix.c:unix_poll(), added CAIF tx_flow handling */
+static unsigned int caif_poll(struct file *file,
+ struct socket *sock, poll_table *wait)
+{
+ struct sock *sk = sock->sk;
+ unsigned int mask;
+ struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
+
+ sock_poll_wait(file, sk_sleep(sk), wait);
+ mask = 0;
+
+ /* exceptional events? */
+ if (sk->sk_err)
+ mask |= POLLERR;
+ if (sk->sk_shutdown == SHUTDOWN_MASK)
+ mask |= POLLHUP;
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ mask |= POLLRDHUP;
+
+ /* readable? */
+ if (!skb_queue_empty(&sk->sk_receive_queue) ||
+ (sk->sk_shutdown & RCV_SHUTDOWN))
+ mask |= POLLIN | POLLRDNORM;
+
+ /* Connection-based need to check for termination and startup */
+ if (sk->sk_state == CAIF_DISCONNECTED)
+ mask |= POLLHUP;
+
+ /*
+ * we set writable also when the other side has shut down the
+ * connection. This prevents stuck sockets.
+ */
+ if (sock_writeable(sk) && tx_flow_is_on(cf_sk))
+ mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+
+ return mask;
+}
+
+static const struct proto_ops caif_seqpacket_ops = {
+ .family = PF_CAIF,
+ .owner = THIS_MODULE,
+ .release = caif_release,
+ .bind = sock_no_bind,
+ .connect = caif_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = sock_no_accept,
+ .getname = sock_no_getname,
+ .poll = caif_poll,
+ .ioctl = sock_no_ioctl,
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .setsockopt = setsockopt,
+ .getsockopt = sock_no_getsockopt,
+ .sendmsg = caif_seqpkt_sendmsg,
+ .recvmsg = caif_seqpkt_recvmsg,
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage,
+};
+
+static const struct proto_ops caif_stream_ops = {
+ .family = PF_CAIF,
+ .owner = THIS_MODULE,
+ .release = caif_release,
+ .bind = sock_no_bind,
+ .connect = caif_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = sock_no_accept,
+ .getname = sock_no_getname,
+ .poll = caif_poll,
+ .ioctl = sock_no_ioctl,
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .setsockopt = setsockopt,
+ .getsockopt = sock_no_getsockopt,
+ .sendmsg = caif_stream_sendmsg,
+ .recvmsg = caif_stream_recvmsg,
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage,
+};
+
+/* This function is called when a socket is finally destroyed. */
+static void caif_sock_destructor(struct sock *sk)
+{
+ struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
+ caif_assert(!atomic_read(&sk->sk_wmem_alloc));
+ caif_assert(sk_unhashed(sk));
+ caif_assert(!sk->sk_socket);
+ if (!sock_flag(sk, SOCK_DEAD)) {
+ pr_info("Attempt to release alive CAIF socket: %p\n", sk);
+ return;
+ }
+ sk_stream_kill_queues(&cf_sk->sk);
+ dbfs_atomic_dec(&cnt.caif_nr_socks);
+}
+
+static int caif_create(struct net *net, struct socket *sock, int protocol,
+ int kern)
+{
+ struct sock *sk = NULL;
+ struct caifsock *cf_sk = NULL;
+ static struct proto prot = {.name = "PF_CAIF",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct caifsock),
+ };
+
+ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN))
+ return -EPERM;
+ /*
+ * The sock->type specifies the socket type to use.
+ * The CAIF socket is a packet stream in the sense
+ * that it is packet based. CAIF trusts the reliability
+ * of the link, no resending is implemented.
+ */
+ if (sock->type == SOCK_SEQPACKET)
+ sock->ops = &caif_seqpacket_ops;
+ else if (sock->type == SOCK_STREAM)
+ sock->ops = &caif_stream_ops;
+ else
+ return -ESOCKTNOSUPPORT;
+
+ if (protocol < 0 || protocol >= CAIFPROTO_MAX)
+ return -EPROTONOSUPPORT;
+ /*
+ * Set the socket state to unconnected. The socket state
+ * is really not used at all in the net/core or socket.c but the
+ * initialization makes sure that sock->state is not uninitialized.
+ */
+ sk = sk_alloc(net, PF_CAIF, GFP_KERNEL, &prot);
+ if (!sk)
+ return -ENOMEM;
+
+ cf_sk = container_of(sk, struct caifsock, sk);
+
+ /* Store the protocol */
+ sk->sk_protocol = (unsigned char) protocol;
+
+ /* Sendbuf dictates the amount of outbound packets not yet sent */
+ sk->sk_sndbuf = CAIF_DEF_SNDBUF;
+ sk->sk_rcvbuf = CAIF_DEF_RCVBUF;
+
+ /*
+ * Lock in order to try to stop someone from opening the socket
+ * too early.
+ */
+ lock_sock(&(cf_sk->sk));
+
+ /* Initialize the nozero default sock structure data. */
+ sock_init_data(sock, sk);
+ sk->sk_destruct = caif_sock_destructor;
+
+ mutex_init(&cf_sk->readlock); /* single task reading lock */
+ cf_sk->layer.ctrlcmd = caif_ctrl_cb;
+ cf_sk->sk.sk_socket->state = SS_UNCONNECTED;
+ cf_sk->sk.sk_state = CAIF_DISCONNECTED;
+
+ set_tx_flow_off(cf_sk);
+ set_rx_flow_on(cf_sk);
+
+ /* Set default options on configuration */
+ cf_sk->conn_req.priority = CAIF_PRIO_NORMAL;
+ cf_sk->conn_req.link_selector = CAIF_LINK_LOW_LATENCY;
+ cf_sk->conn_req.protocol = protocol;
+ /* Increase the number of sockets created. */
+ dbfs_atomic_inc(&cnt.caif_nr_socks);
+#ifdef CONFIG_DEBUG_FS
+ if (!IS_ERR(debugfsdir)) {
+ /* Fill in some information concerning the misc socket. */
+ snprintf(cf_sk->name, sizeof(cf_sk->name), "cfsk%d",
+ atomic_read(&cnt.caif_nr_socks));
+
+ cf_sk->debugfs_socket_dir =
+ debugfs_create_dir(cf_sk->name, debugfsdir);
+ debugfs_create_u32("sk_state", S_IRUSR | S_IWUSR,
+ cf_sk->debugfs_socket_dir,
+ (u32 *) &cf_sk->sk.sk_state);
+ debugfs_create_u32("flow_state", S_IRUSR | S_IWUSR,
+ cf_sk->debugfs_socket_dir, &cf_sk->flow_state);
+ debugfs_create_u32("sk_rmem_alloc", S_IRUSR | S_IWUSR,
+ cf_sk->debugfs_socket_dir,
+ (u32 *) &cf_sk->sk.sk_rmem_alloc);
+ debugfs_create_u32("sk_wmem_alloc", S_IRUSR | S_IWUSR,
+ cf_sk->debugfs_socket_dir,
+ (u32 *) &cf_sk->sk.sk_wmem_alloc);
+ debugfs_create_u32("identity", S_IRUSR | S_IWUSR,
+ cf_sk->debugfs_socket_dir,
+ (u32 *) &cf_sk->layer.id);
+ }
+#endif
+ release_sock(&cf_sk->sk);
+ return 0;
+}
+
+
+static struct net_proto_family caif_family_ops = {
+ .family = PF_CAIF,
+ .create = caif_create,
+ .owner = THIS_MODULE,
+};
+
+int af_caif_init(void)
+{
+ int err = sock_register(&caif_family_ops);
+ if (!err)
+ return err;
+ return 0;
+}
+
+static int __init caif_sktinit_module(void)
+{
+#ifdef CONFIG_DEBUG_FS
+ debugfsdir = debugfs_create_dir("caif_sk", NULL);
+ if (!IS_ERR(debugfsdir)) {
+ debugfs_create_u32("num_sockets", S_IRUSR | S_IWUSR,
+ debugfsdir,
+ (u32 *) &cnt.caif_nr_socks);
+ debugfs_create_u32("num_connect_req", S_IRUSR | S_IWUSR,
+ debugfsdir,
+ (u32 *) &cnt.num_connect_req);
+ debugfs_create_u32("num_connect_resp", S_IRUSR | S_IWUSR,
+ debugfsdir,
+ (u32 *) &cnt.num_connect_resp);
+ debugfs_create_u32("num_connect_fail_resp", S_IRUSR | S_IWUSR,
+ debugfsdir,
+ (u32 *) &cnt.num_connect_fail_resp);
+ debugfs_create_u32("num_disconnect", S_IRUSR | S_IWUSR,
+ debugfsdir,
+ (u32 *) &cnt.num_disconnect);
+ debugfs_create_u32("num_remote_shutdown_ind",
+ S_IRUSR | S_IWUSR, debugfsdir,
+ (u32 *) &cnt.num_remote_shutdown_ind);
+ debugfs_create_u32("num_tx_flow_off_ind", S_IRUSR | S_IWUSR,
+ debugfsdir,
+ (u32 *) &cnt.num_tx_flow_off_ind);
+ debugfs_create_u32("num_tx_flow_on_ind", S_IRUSR | S_IWUSR,
+ debugfsdir,
+ (u32 *) &cnt.num_tx_flow_on_ind);
+ debugfs_create_u32("num_rx_flow_off", S_IRUSR | S_IWUSR,
+ debugfsdir,
+ (u32 *) &cnt.num_rx_flow_off);
+ debugfs_create_u32("num_rx_flow_on", S_IRUSR | S_IWUSR,
+ debugfsdir,
+ (u32 *) &cnt.num_rx_flow_on);
+ }
+#endif
+ return af_caif_init();
+}
+
+static void __exit caif_sktexit_module(void)
+{
+ sock_unregister(PF_CAIF);
+ if (debugfsdir != NULL)
+ debugfs_remove_recursive(debugfsdir);
+}
+module_init(caif_sktinit_module);
+module_exit(caif_sktexit_module);
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 4/7] caif: Disconnect without waiting for response
From: sjur.brandeland @ 2010-04-28 18:54 UTC (permalink / raw)
To: netdev, davem
Cc: marcel, daniel.martensson, sjurbr, linus.walleij,
Sjur Braendeland
In-Reply-To: <1272480880-30672-3-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Changes:
o Function cfcnfg_disconn_adapt_layer is changed to do asynchronous
disconnect, not waiting for any response from the modem. Due to this
the function cfcnfg_linkdestroy_rsp does nothing anymore.
o Because disconnect may take down a connection before a connect response
is received the function cfcnfg_linkup_rsp is checking if the client is
still waiting for the response, if not a disconnect request is sent to
the modem.
o cfctrl is no longer keeping track of pending disconnect requests.
o Added function cfctrl_cancel_req, which is used for deleting a pending
connect request if disconnect is done before connect response is received.
o Removed unused function cfctrl_insert_req2
o Added better handling of connect reject from modem.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
include/net/caif/cfctrl.h | 7 +-
net/caif/cfcnfg.c | 155 +++++++++++++--------------------------------
net/caif/cfctrl.c | 95 ++++++++++++++++++----------
3 files changed, 111 insertions(+), 146 deletions(-)
diff --git a/include/net/caif/cfctrl.h b/include/net/caif/cfctrl.h
index dee25b8..997603f 100644
--- a/include/net/caif/cfctrl.h
+++ b/include/net/caif/cfctrl.h
@@ -43,8 +43,7 @@ struct cfctrl_rsp {
void (*linksetup_rsp)(struct cflayer *layer, u8 linkid,
enum cfctrl_srv serv, u8 phyid,
struct cflayer *adapt_layer);
- void (*linkdestroy_rsp)(struct cflayer *layer, u8 linkid,
- struct cflayer *client_layer);
+ void (*linkdestroy_rsp)(struct cflayer *layer, u8 linkid);
void (*linkerror_ind)(void);
void (*enum_rsp)(void);
void (*sleep_rsp)(void);
@@ -117,7 +116,7 @@ struct cfctrl {
};
void cfctrl_enum_req(struct cflayer *cfctrl, u8 physlinkid);
-void cfctrl_linkup_request(struct cflayer *cfctrl,
+int cfctrl_linkup_request(struct cflayer *cfctrl,
struct cfctrl_link_param *param,
struct cflayer *user_layer);
int cfctrl_linkdown_req(struct cflayer *cfctrl, u8 linkid,
@@ -135,4 +134,6 @@ void cfctrl_insert_req(struct cfctrl *ctrl,
struct cfctrl_request_info *req);
struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl,
struct cfctrl_request_info *req);
+void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer);
+
#endif /* CFCTRL_H_ */
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index f94f3df..471c629 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -54,8 +54,7 @@ struct cfcnfg {
static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id,
enum cfctrl_srv serv, u8 phyid,
struct cflayer *adapt_layer);
-static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id,
- struct cflayer *client_layer);
+static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id);
static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
struct cflayer *adapt_layer);
static void cfctrl_resp_func(void);
@@ -175,73 +174,65 @@ int cfcnfg_get_named(struct cfcnfg *cnfg, char *name)
return 0;
}
-/*
- * NOTE: What happens on destroy failure:
- * 1a) No response - Too early
- * This will not happen because enumerate has already
- * completed.
- * 1b) No response - FATAL
- * Not handled, but this should be a CAIF PROTOCOL ERROR
- * Modem error, response is really expected - this
- * case is not really handled.
- * 2) O/E-bit indicate error
- * Ignored - this link is destroyed anyway.
- * 3) Not able to match on request
- * Not handled, but this should be a CAIF PROTOCOL ERROR
- * 4) Link-Error - (no response)
- * Not handled, but this should be a CAIF PROTOCOL ERROR
- */
int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer)
{
u8 channel_id = 0;
int ret = 0;
+ struct cflayer *servl = NULL;
struct cfcnfg_phyinfo *phyinfo = NULL;
u8 phyid = 0;
-
caif_assert(adap_layer != NULL);
channel_id = adap_layer->id;
- if (channel_id == 0) {
+ if (adap_layer->dn == NULL || channel_id == 0) {
pr_err("CAIF: %s():adap_layer->id is 0\n", __func__);
ret = -ENOTCONN;
goto end;
}
-
- if (adap_layer->dn == NULL) {
- pr_err("CAIF: %s():adap_layer->dn is NULL\n", __func__);
- ret = -ENODEV;
- goto end;
- }
-
- if (adap_layer->dn != NULL)
- phyid = cfsrvl_getphyid(adap_layer->dn);
-
- phyinfo = cfcnfg_get_phyinfo(cnfg, phyid);
- if (phyinfo == NULL) {
- pr_warning("CAIF: %s(): No interface to send disconnect to\n",
- __func__);
- ret = -ENODEV;
+ servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id);
+ if (servl == NULL)
goto end;
- }
-
- if (phyinfo->id != phyid
- || phyinfo->phy_layer->id != phyid
- || phyinfo->frm_layer->id != phyid) {
-
- pr_err("CAIF: %s(): Inconsistency in phy registration\n",
- __func__);
+ layer_set_up(servl, NULL);
+ ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer);
+ if (servl == NULL) {
+ pr_err("CAIF: %s(): PROTOCOL ERROR "
+ "- Error removing service_layer Channel_Id(%d)",
+ __func__, channel_id);
ret = -EINVAL;
goto end;
}
+ caif_assert(channel_id == servl->id);
+ if (adap_layer->dn != NULL) {
+ phyid = cfsrvl_getphyid(adap_layer->dn);
- ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer);
-
-end:
+ phyinfo = cfcnfg_get_phyinfo(cnfg, phyid);
+ if (phyinfo == NULL) {
+ pr_warning("CAIF: %s(): "
+ "No interface to send disconnect to\n",
+ __func__);
+ ret = -ENODEV;
+ goto end;
+ }
+ if (phyinfo->id != phyid ||
+ phyinfo->phy_layer->id != phyid ||
+ phyinfo->frm_layer->id != phyid) {
+ pr_err("CAIF: %s(): "
+ "Inconsistency in phy registration\n",
+ __func__);
+ ret = -EINVAL;
+ goto end;
+ }
+ }
if (phyinfo != NULL && --phyinfo->phy_ref_count == 0 &&
phyinfo->phy_layer != NULL &&
phyinfo->phy_layer->modemcmd != NULL) {
phyinfo->phy_layer->modemcmd(phyinfo->phy_layer,
_CAIF_MODEMCMD_PHYIF_USELESS);
}
+end:
+ cfsrvl_put(servl);
+ cfctrl_cancel_req(cnfg->ctrl, adap_layer);
+ if (adap_layer->ctrlcmd != NULL)
+ adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0);
return ret;
}
@@ -254,69 +245,11 @@ void cfcnfg_release_adap_layer(struct cflayer *adap_layer)
}
EXPORT_SYMBOL(cfcnfg_release_adap_layer);
-static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id,
- struct cflayer *client_layer)
+static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id)
{
- struct cfcnfg *cnfg = container_obj(layer);
- struct cflayer *servl;
-
- /*
- * 1) Remove service from the MUX layer. The MUX must
- * guarante that no more payload sent "upwards" (receive)
- */
- servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id);
-
- if (servl == NULL) {
- pr_err("CAIF: %s(): PROTOCOL ERROR "
- "- Error removing service_layer Channel_Id(%d)",
- __func__, channel_id);
- return;
- }
- caif_assert(channel_id == servl->id);
-
- if (servl != client_layer && servl->up != client_layer) {
- pr_err("CAIF: %s(): Error removing service_layer "
- "Channel_Id(%d) %p %p",
- __func__, channel_id, (void *) servl,
- (void *) client_layer);
- return;
- }
-
- /*
- * 2) DEINIT_RSP must guarantee that no more packets are transmitted
- * from client (adap_layer) when it returns.
- */
-
- if (servl->ctrlcmd == NULL) {
- pr_err("CAIF: %s(): Error servl->ctrlcmd == NULL", __func__);
- return;
- }
-
- servl->ctrlcmd(servl, CAIF_CTRLCMD_DEINIT_RSP, 0);
-
- /* 3) It is now safe to destroy the service layer. */
- cfservl_destroy(servl);
}
-/*
- * NOTE: What happens on linksetup failure:
- * 1a) No response - Too early
- * This will not happen because enumerate is secured
- * before using interface.
- * 1b) No response - FATAL
- * Not handled, but this should be a CAIF PROTOCOL ERROR
- * Modem error, response is really expected - this case is
- * not really handled.
- * 2) O/E-bit indicate error
- * Handled in cnfg_reject_rsp
- * 3) Not able to match on request
- * Not handled, but this should be a CAIF PROTOCOL ERROR
- * 4) Link-Error - (no response)
- * Not handled, but this should be a CAIF PROTOCOL ERROR
- */
-
-int
-cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
+int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
struct cfctrl_link_param *param,
struct cflayer *adap_layer)
{
@@ -346,8 +279,7 @@ cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
param->phyid);
/* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
cfctrl_enum_req(cnfg->ctrl, param->phyid);
- cfctrl_linkup_request(cnfg->ctrl, param, adap_layer);
- return 0;
+ return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer);
}
EXPORT_SYMBOL(cfcnfg_add_adaptation_layer);
@@ -367,8 +299,10 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
struct cflayer *servicel = NULL;
struct cfcnfg_phyinfo *phyinfo;
if (adapt_layer == NULL) {
- pr_err("CAIF: %s(): PROTOCOL ERROR "
- "- LinkUp Request/Response did not match\n", __func__);
+ pr_debug("CAIF: %s(): link setup response "
+ "but no client exist, send linkdown back\n",
+ __func__);
+ cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL);
return;
}
@@ -424,6 +358,7 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id);
layer_set_up(servicel, adapt_layer);
layer_set_dn(adapt_layer, servicel);
+ cfsrvl_get(servicel);
servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0);
}
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c
index 11f8014..a521d32 100644
--- a/net/caif/cfctrl.c
+++ b/net/caif/cfctrl.c
@@ -32,6 +32,7 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
struct cflayer *cfctrl_create(void)
{
+ struct dev_info dev_info;
struct cfctrl *this =
kmalloc(sizeof(struct cfctrl), GFP_ATOMIC);
if (!this) {
@@ -39,12 +40,13 @@ struct cflayer *cfctrl_create(void)
return NULL;
}
caif_assert(offsetof(struct cfctrl, serv.layer) == 0);
+ memset(&dev_info, 0, sizeof(dev_info));
+ dev_info.id = 0xff;
memset(this, 0, sizeof(*this));
+ cfsrvl_init(&this->serv, 0, &dev_info);
spin_lock_init(&this->info_list_lock);
atomic_set(&this->req_seq_no, 1);
atomic_set(&this->rsp_seq_no, 1);
- this->serv.dev_info.id = 0xff;
- this->serv.layer.id = 0;
this->serv.layer.receive = cfctrl_recv;
sprintf(this->serv.layer.name, "ctrl");
this->serv.layer.ctrlcmd = cfctrl_ctrlcmd;
@@ -127,20 +129,6 @@ void cfctrl_insert_req(struct cfctrl *ctrl,
spin_unlock(&ctrl->info_list_lock);
}
-static void cfctrl_insert_req2(struct cfctrl *ctrl, enum cfctrl_cmd cmd,
- u8 linkid, struct cflayer *user_layer)
-{
- struct cfctrl_request_info *req = kmalloc(sizeof(*req), GFP_KERNEL);
- if (!req) {
- pr_warning("CAIF: %s(): Out of memory\n", __func__);
- return;
- }
- req->client_layer = user_layer;
- req->cmd = cmd;
- req->channel_id = linkid;
- cfctrl_insert_req(ctrl, req);
-}
-
/* Compare and remove request */
struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl,
struct cfctrl_request_info *req)
@@ -234,7 +222,7 @@ void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid)
}
}
-void cfctrl_linkup_request(struct cflayer *layer,
+int cfctrl_linkup_request(struct cflayer *layer,
struct cfctrl_link_param *param,
struct cflayer *user_layer)
{
@@ -248,7 +236,7 @@ void cfctrl_linkup_request(struct cflayer *layer,
struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN);
if (!pkt) {
pr_warning("CAIF: %s(): Out of memory\n", __func__);
- return;
+ return -ENOMEM;
}
cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP);
cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype);
@@ -294,11 +282,12 @@ void cfctrl_linkup_request(struct cflayer *layer,
default:
pr_warning("CAIF: %s():Request setup of bad link type = %d\n",
__func__, param->linktype);
+ return -EINVAL;
}
req = kmalloc(sizeof(*req), GFP_KERNEL);
if (!req) {
pr_warning("CAIF: %s(): Out of memory\n", __func__);
- return;
+ return -ENOMEM;
}
memset(req, 0, sizeof(*req));
req->client_layer = user_layer;
@@ -306,6 +295,11 @@ void cfctrl_linkup_request(struct cflayer *layer,
req->param = *param;
cfctrl_insert_req(cfctrl, req);
init_info(cfpkt_info(pkt), cfctrl);
+ /*
+ * NOTE:Always send linkup and linkdown request on the same
+ * device as the payload. Otherwise old queued up payload
+ * might arrive with the newly allocated channel ID.
+ */
cfpkt_info(pkt)->dev_info->id = param->phyid;
ret =
cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt);
@@ -313,7 +307,9 @@ void cfctrl_linkup_request(struct cflayer *layer,
pr_err("CAIF: %s(): Could not transmit linksetup request\n",
__func__);
cfpkt_destroy(pkt);
+ return -ENODEV;
}
+ return 0;
}
int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid,
@@ -326,7 +322,6 @@ int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid,
pr_warning("CAIF: %s(): Out of memory\n", __func__);
return -ENOMEM;
}
- cfctrl_insert_req2(cfctrl, CFCTRL_CMD_LINK_DESTROY, channelid, client);
cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY);
cfpkt_addbdy(pkt, channelid);
init_info(cfpkt_info(pkt), cfctrl);
@@ -392,6 +387,38 @@ void cfctrl_getstartreason_req(struct cflayer *layer)
}
+void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer)
+{
+ struct cfctrl_request_info *p, *req;
+ struct cfctrl *ctrl = container_obj(layr);
+ spin_lock(&ctrl->info_list_lock);
+
+ if (ctrl->first_req == NULL) {
+ spin_unlock(&ctrl->info_list_lock);
+ return;
+ }
+
+ if (ctrl->first_req->client_layer == adap_layer) {
+
+ req = ctrl->first_req;
+ ctrl->first_req = ctrl->first_req->next;
+ kfree(req);
+ }
+
+ p = ctrl->first_req;
+ while (p != NULL && p->next != NULL) {
+ if (p->next->client_layer == adap_layer) {
+
+ req = p->next;
+ p->next = p->next->next;
+ kfree(p->next);
+ }
+ p = p->next;
+ }
+
+ spin_unlock(&ctrl->info_list_lock);
+}
+
static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
{
u8 cmdrsp;
@@ -409,11 +436,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
cmd = cmdrsp & CFCTRL_CMD_MASK;
if (cmd != CFCTRL_CMD_LINK_ERR
&& CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) {
- if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE) {
- pr_info("CAIF: %s() CAIF Protocol error:"
- "Response bit not set\n", __func__);
- goto error;
- }
+ if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE)
+ cmdrsp |= CFCTRL_ERR_BIT;
}
switch (cmd) {
@@ -451,12 +475,16 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
switch (serv) {
case CFCTRL_SRV_VEI:
case CFCTRL_SRV_DBG:
+ if (CFCTRL_ERR_BIT & cmdrsp)
+ break;
/* Link ID */
cfpkt_extr_head(pkt, &linkid, 1);
break;
case CFCTRL_SRV_VIDEO:
cfpkt_extr_head(pkt, &tmp, 1);
linkparam.u.video.connid = tmp;
+ if (CFCTRL_ERR_BIT & cmdrsp)
+ break;
/* Link ID */
cfpkt_extr_head(pkt, &linkid, 1);
break;
@@ -465,6 +493,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
cfpkt_extr_head(pkt, &tmp32, 4);
linkparam.u.datagram.connid =
le32_to_cpu(tmp32);
+ if (CFCTRL_ERR_BIT & cmdrsp)
+ break;
/* Link ID */
cfpkt_extr_head(pkt, &linkid, 1);
break;
@@ -483,6 +513,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
*cp++ = tmp;
*cp = '\0';
+ if (CFCTRL_ERR_BIT & cmdrsp)
+ break;
/* Link ID */
cfpkt_extr_head(pkt, &linkid, 1);
@@ -519,6 +551,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
cfpkt_extr_head(pkt, &tmp, 1);
*cp++ = tmp;
}
+ if (CFCTRL_ERR_BIT & cmdrsp)
+ break;
/* Link ID */
cfpkt_extr_head(pkt, &linkid, 1);
/* Length */
@@ -560,13 +594,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
break;
case CFCTRL_CMD_LINK_DESTROY:
cfpkt_extr_head(pkt, &linkid, 1);
- rsp.cmd = cmd;
- rsp.channel_id = linkid;
- req = cfctrl_remove_req(cfctrl, &rsp);
- cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid,
- req ? req->client_layer : NULL);
- if (req != NULL)
- kfree(req);
+ cfctrl->res.linkdestroy_rsp(cfctrl->serv.layer.up, linkid);
break;
case CFCTRL_CMD_LINK_ERR:
pr_err("CAIF: %s(): Frame Error Indication received\n",
@@ -608,7 +636,7 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
case CAIF_CTRLCMD_FLOW_OFF_IND:
spin_lock(&this->info_list_lock);
if (this->first_req != NULL) {
- pr_warning("CAIF: %s(): Received flow off in "
+ pr_debug("CAIF: %s(): Received flow off in "
"control layer", __func__);
}
spin_unlock(&this->info_list_lock);
@@ -633,6 +661,7 @@ static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt)
if (!ctrl->loop_linkused[linkid])
goto found;
spin_unlock(&ctrl->loop_linkid_lock);
+ pr_err("CAIF: %s(): Out of link-ids\n", __func__);
return -EINVAL;
found:
if (!ctrl->loop_linkused[linkid])
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 3/7] caif: Add reference counting to service layer
From: sjur.brandeland @ 2010-04-28 18:54 UTC (permalink / raw)
To: netdev, davem
Cc: marcel, daniel.martensson, sjurbr, linus.walleij,
Sjur Braendeland
In-Reply-To: <1272480880-30672-2-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Changes:
o Added functions cfsrvl_get and cfsrvl_put.
o Added support release_client to use by socket and net device.
o Increase reference counting for in-flight packets from cfmuxl
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
include/net/caif/caif_dev.h | 11 +++++++++++
include/net/caif/cfcnfg.h | 7 +++++++
include/net/caif/cfsrvl.h | 22 ++++++++++++++++++++++
net/caif/caif_dev.c | 6 ++++++
net/caif/cfcnfg.c | 7 +++++++
net/caif/cfmuxl.c | 7 ++++++-
net/caif/cfsrvl.c | 7 +++++++
7 files changed, 66 insertions(+), 1 deletions(-)
diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h
index 3aa1ff6..318ab94 100644
--- a/include/net/caif/caif_dev.h
+++ b/include/net/caif/caif_dev.h
@@ -70,6 +70,17 @@ int caif_connect_client(struct caif_connect_request *config,
int caif_disconnect_client(struct cflayer *client_layer);
/**
+ * caif_release_client - Release adaptation layer reference to client.
+ *
+ * @client_layer: Client layer.
+ *
+ * Releases a client/adaptation layer use of the caif stack.
+ * This function must be used after caif_disconnect_client to
+ * decrease the reference count of the service layer.
+ */
+void caif_release_client(struct cflayer *client_layer);
+
+/**
* connect_req_to_link_param - Translate configuration parameters
* from socket format to internal format.
* @cnfg: Pointer to configuration handler
diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h
index f16b875..9fc2fc2 100644
--- a/include/net/caif/cfcnfg.h
+++ b/include/net/caif/cfcnfg.h
@@ -97,6 +97,13 @@ int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg,
struct cflayer *adap_layer);
/**
+ * cfcnfg_release_adap_layer - Used by client to release the adaptation layer.
+ *
+ * @adap_layer: Adaptation layer.
+ */
+void cfcnfg_release_adap_layer(struct cflayer *adap_layer);
+
+/**
* cfcnfg_add_adaptation_layer - Add an adaptation layer to the CAIF stack.
*
* The adaptation Layer is where the interface to application or higher-level
diff --git a/include/net/caif/cfsrvl.h b/include/net/caif/cfsrvl.h
index b2a12db..2dc9eb1 100644
--- a/include/net/caif/cfsrvl.h
+++ b/include/net/caif/cfsrvl.h
@@ -9,14 +9,18 @@
#include <linux/list.h>
#include <linux/stddef.h>
#include <linux/types.h>
+#include <linux/kref.h>
+
struct cfsrvl {
struct cflayer layer;
bool open;
bool phy_flow_on;
bool modem_flow_on;
struct dev_info dev_info;
+ struct kref ref;
};
+void cfsrvl_release(struct kref *kref);
struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info);
struct cflayer *cfdgml_create(u8 linkid, struct dev_info *dev_info);
struct cflayer *cfutill_create(u8 linkid, struct dev_info *dev_info);
@@ -31,4 +35,22 @@ void cfsrvl_init(struct cfsrvl *service,
bool cfsrvl_ready(struct cfsrvl *service, int *err);
u8 cfsrvl_getphyid(struct cflayer *layer);
+static inline void cfsrvl_get(struct cflayer *layr)
+{
+ struct cfsrvl *s;
+ if (layr == NULL)
+ return;
+ s = container_of(layr, struct cfsrvl, layer);
+ kref_get(&s->ref);
+}
+
+static inline void cfsrvl_put(struct cflayer *layr)
+{
+ struct cfsrvl *s;
+ if (layr == NULL)
+ return;
+ s = container_of(layr, struct cfsrvl, layer);
+ kref_put(&s->ref, cfsrvl_release);
+}
+
#endif /* CFSRVL_H_ */
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index be1f674..0145bae 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -346,6 +346,12 @@ int caif_disconnect_client(struct cflayer *adap_layer)
}
EXPORT_SYMBOL(caif_disconnect_client);
+void caif_release_client(struct cflayer *adap_layer)
+{
+ cfcnfg_release_adap_layer(adap_layer);
+}
+EXPORT_SYMBOL(caif_release_client);
+
/* Per-namespace Caif devices handling */
static int caif_init_net(struct net *net)
{
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index d52f256..f94f3df 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -247,6 +247,13 @@ end:
}
EXPORT_SYMBOL(cfcnfg_disconn_adapt_layer);
+void cfcnfg_release_adap_layer(struct cflayer *adap_layer)
+{
+ if (adap_layer->dn)
+ cfsrvl_put(adap_layer->dn);
+}
+EXPORT_SYMBOL(cfcnfg_release_adap_layer);
+
static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id,
struct cflayer *client_layer)
{
diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c
index 6fb9f9e..7372f27 100644
--- a/net/caif/cfmuxl.c
+++ b/net/caif/cfmuxl.c
@@ -62,6 +62,7 @@ int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid)
{
struct cfmuxl *muxl = container_obj(layr);
spin_lock(&muxl->receive_lock);
+ cfsrvl_get(up);
list_add(&up->node, &muxl->srvl_list);
spin_unlock(&muxl->receive_lock);
return 0;
@@ -172,8 +173,11 @@ struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 id)
struct cfmuxl *muxl = container_obj(layr);
spin_lock(&muxl->receive_lock);
up = get_up(muxl, id);
+ if (up == NULL)
+ return NULL;
memset(muxl->up_cache, 0, sizeof(muxl->up_cache));
list_del(&up->node);
+ cfsrvl_put(up);
spin_unlock(&muxl->receive_lock);
return up;
}
@@ -203,8 +207,9 @@ static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt)
*/
return /* CFGLU_EPROT; */ 0;
}
-
+ cfsrvl_get(up);
ret = up->receive(up, pkt);
+ cfsrvl_put(up);
return ret;
}
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c
index d470c51..aff31f3 100644
--- a/net/caif/cfsrvl.c
+++ b/net/caif/cfsrvl.c
@@ -158,6 +158,13 @@ void cfsrvl_init(struct cfsrvl *service,
service->layer.ctrlcmd = cfservl_ctrlcmd;
service->layer.modemcmd = cfservl_modemcmd;
service->dev_info = *dev_info;
+ kref_init(&service->ref);
+}
+
+void cfsrvl_release(struct kref *kref)
+{
+ struct cfsrvl *service = container_of(kref, struct cfsrvl, ref);
+ kfree(service);
}
bool cfsrvl_ready(struct cfsrvl *service, int *err)
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 2/7] caif: Rename functions in cfcnfg and caif_dev
From: sjur.brandeland @ 2010-04-28 18:54 UTC (permalink / raw)
To: netdev, davem
Cc: marcel, daniel.martensson, sjurbr, linus.walleij,
Sjur Braendeland
In-Reply-To: <1272480880-30672-1-git-send-email-sjur.brandeland@stericsson.com>
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Changes:
o Renamed cfcnfg_del_adapt_layer to cfcnfg_disconn_adapt_layer
o Fixed typo cfcfg to cfcnfg
o Renamed linkid to channel_id
o Updated documentation in caif_dev.h
o Minor formatting changes
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
include/net/caif/caif_dev.h | 6 +++-
include/net/caif/cfcnfg.h | 10 ++++----
net/caif/caif_dev.c | 15 ++++++------
net/caif/cfcnfg.c | 51 +++++++++++++++++++++----------------------
4 files changed, 41 insertions(+), 41 deletions(-)
diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h
index 42a7c78..3aa1ff6 100644
--- a/include/net/caif/caif_dev.h
+++ b/include/net/caif/caif_dev.h
@@ -23,17 +23,19 @@ struct caif_param {
};
/**
- * caif_connect_request - Request data for CAIF channel setup.
+ * struct caif_connect_request - Request data for CAIF channel setup.
+ * @protocol: Type of CAIF protocol to use (at, datagram etc)
* @sockaddr: Socket address to connect.
* @priority: Priority of the connection.
* @link_selector: Link selector (high bandwidth or low latency)
* @link_name: Name of the CAIF Link Layer to use.
+ * @param: Connect Request parameters (CAIF_SO_REQ_PARAM).
*
* This struct is used when connecting a CAIF channel.
* It contains all CAIF channel configuration options.
*/
struct caif_connect_request {
- int protocol;
+ enum caif_protocol_type protocol;
struct sockaddr_caif sockaddr;
enum caif_channel_priority priority;
enum caif_link_selector link_selector;
diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h
index 366082c..f16b875 100644
--- a/include/net/caif/cfcnfg.h
+++ b/include/net/caif/cfcnfg.h
@@ -87,13 +87,14 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer);
/**
- * cfcnfg_del_adapt_layer - Deletes an adaptation layer from the CAIF stack.
+ * cfcnfg_disconn_adapt_layer - Disconnects an adaptation layer.
*
* @cnfg: Pointer to a CAIF configuration object, created by
* cfcnfg_create().
* @adap_layer: Adaptation layer to be removed.
*/
-int cfcnfg_del_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer);
+int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg,
+ struct cflayer *adap_layer);
/**
* cfcnfg_add_adaptation_layer - Add an adaptation layer to the CAIF stack.
@@ -102,14 +103,13 @@ int cfcnfg_del_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer);
* driver functionality is implemented.
*
* @cnfg: Pointer to a CAIF configuration object, created by
- * cfcnfg_create().
+ * cfcnfg_create().
* @param: Link setup parameters.
* @adap_layer: Specify the adaptation layer; the receive and
* flow-control functions MUST be set in the structure.
*
*/
-int
-cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
+int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
struct cfctrl_link_param *param,
struct cflayer *adap_layer);
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index e84837e..be1f674 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -330,20 +330,19 @@ int caif_connect_client(struct caif_connect_request *conn_req,
struct cflayer *client_layer)
{
struct cfctrl_link_param param;
- if (connect_req_to_link_param(get_caif_conf(), conn_req, ¶m) == 0)
- /* Hook up the adaptation layer. */
- return cfcnfg_add_adaptation_layer(get_caif_conf(),
+ int ret;
+ ret = connect_req_to_link_param(get_caif_conf(), conn_req, ¶m);
+ if (ret)
+ return ret;
+ /* Hook up the adaptation layer. */
+ return cfcnfg_add_adaptation_layer(get_caif_conf(),
¶m, client_layer);
-
- return -EINVAL;
-
- caif_assert(0);
}
EXPORT_SYMBOL(caif_connect_client);
int caif_disconnect_client(struct cflayer *adap_layer)
{
- return cfcnfg_del_adapt_layer(get_caif_conf(), adap_layer);
+ return cfcnfg_disconn_adapt_layer(get_caif_conf(), adap_layer);
}
EXPORT_SYMBOL(caif_disconnect_client);
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index c873e3d..d52f256 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -51,12 +51,12 @@ struct cfcnfg {
struct cfcnfg_phyinfo phy_layers[MAX_PHY_LAYERS];
};
-static void cncfg_linkup_rsp(struct cflayer *layer, u8 linkid,
+static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id,
enum cfctrl_srv serv, u8 phyid,
struct cflayer *adapt_layer);
-static void cncfg_linkdestroy_rsp(struct cflayer *layer, u8 linkid,
+static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id,
struct cflayer *client_layer);
-static void cncfg_reject_rsp(struct cflayer *layer, u8 linkid,
+static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
struct cflayer *adapt_layer);
static void cfctrl_resp_func(void);
static void cfctrl_enum_resp(void);
@@ -82,13 +82,13 @@ struct cfcnfg *cfcnfg_create(void)
resp = cfctrl_get_respfuncs(this->ctrl);
resp->enum_rsp = cfctrl_enum_resp;
resp->linkerror_ind = cfctrl_resp_func;
- resp->linkdestroy_rsp = cncfg_linkdestroy_rsp;
+ resp->linkdestroy_rsp = cfcnfg_linkdestroy_rsp;
resp->sleep_rsp = cfctrl_resp_func;
resp->wake_rsp = cfctrl_resp_func;
resp->restart_rsp = cfctrl_resp_func;
resp->radioset_rsp = cfctrl_resp_func;
- resp->linksetup_rsp = cncfg_linkup_rsp;
- resp->reject_rsp = cncfg_reject_rsp;
+ resp->linksetup_rsp = cfcnfg_linkup_rsp;
+ resp->reject_rsp = cfcnfg_reject_rsp;
this->last_phyid = 1;
@@ -191,8 +191,7 @@ int cfcnfg_get_named(struct cfcnfg *cnfg, char *name)
* 4) Link-Error - (no response)
* Not handled, but this should be a CAIF PROTOCOL ERROR
*/
-
-int cfcnfg_del_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer)
+int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer)
{
u8 channel_id = 0;
int ret = 0;
@@ -246,9 +245,9 @@ end:
return ret;
}
-EXPORT_SYMBOL(cfcnfg_del_adapt_layer);
+EXPORT_SYMBOL(cfcnfg_disconn_adapt_layer);
-static void cncfg_linkdestroy_rsp(struct cflayer *layer, u8 linkid,
+static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id,
struct cflayer *client_layer)
{
struct cfcnfg *cnfg = container_obj(layer);
@@ -258,20 +257,20 @@ static void cncfg_linkdestroy_rsp(struct cflayer *layer, u8 linkid,
* 1) Remove service from the MUX layer. The MUX must
* guarante that no more payload sent "upwards" (receive)
*/
- servl = cfmuxl_remove_uplayer(cnfg->mux, linkid);
+ servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id);
if (servl == NULL) {
pr_err("CAIF: %s(): PROTOCOL ERROR "
- "- Error removing service_layer Linkid(%d)",
- __func__, linkid);
+ "- Error removing service_layer Channel_Id(%d)",
+ __func__, channel_id);
return;
}
- caif_assert(linkid == servl->id);
+ caif_assert(channel_id == servl->id);
if (servl != client_layer && servl->up != client_layer) {
pr_err("CAIF: %s(): Error removing service_layer "
- "Linkid(%d) %p %p",
- __func__, linkid, (void *) servl,
+ "Channel_Id(%d) %p %p",
+ __func__, channel_id, (void *) servl,
(void *) client_layer);
return;
}
@@ -345,7 +344,7 @@ cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
}
EXPORT_SYMBOL(cfcnfg_add_adaptation_layer);
-static void cncfg_reject_rsp(struct cflayer *layer, u8 linkid,
+static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
struct cflayer *adapt_layer)
{
if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL)
@@ -354,7 +353,7 @@ static void cncfg_reject_rsp(struct cflayer *layer, u8 linkid,
}
static void
-cncfg_linkup_rsp(struct cflayer *layer, u8 linkid, enum cfctrl_srv serv,
+cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
u8 phyid, struct cflayer *adapt_layer)
{
struct cfcnfg *cnfg = container_obj(layer);
@@ -383,26 +382,26 @@ cncfg_linkup_rsp(struct cflayer *layer, u8 linkid, enum cfctrl_srv serv,
_CAIF_MODEMCMD_PHYIF_USEFULL);
}
- adapt_layer->id = linkid;
+ adapt_layer->id = channel_id;
switch (serv) {
case CFCTRL_SRV_VEI:
- servicel = cfvei_create(linkid, &phyinfo->dev_info);
+ servicel = cfvei_create(channel_id, &phyinfo->dev_info);
break;
case CFCTRL_SRV_DATAGRAM:
- servicel = cfdgml_create(linkid, &phyinfo->dev_info);
+ servicel = cfdgml_create(channel_id, &phyinfo->dev_info);
break;
case CFCTRL_SRV_RFM:
- servicel = cfrfml_create(linkid, &phyinfo->dev_info);
+ servicel = cfrfml_create(channel_id, &phyinfo->dev_info);
break;
case CFCTRL_SRV_UTIL:
- servicel = cfutill_create(linkid, &phyinfo->dev_info);
+ servicel = cfutill_create(channel_id, &phyinfo->dev_info);
break;
case CFCTRL_SRV_VIDEO:
- servicel = cfvidl_create(linkid, &phyinfo->dev_info);
+ servicel = cfvidl_create(channel_id, &phyinfo->dev_info);
break;
case CFCTRL_SRV_DBG:
- servicel = cfdbgl_create(linkid, &phyinfo->dev_info);
+ servicel = cfdbgl_create(channel_id, &phyinfo->dev_info);
break;
default:
pr_err("CAIF: %s(): Protocol error. "
@@ -415,7 +414,7 @@ cncfg_linkup_rsp(struct cflayer *layer, u8 linkid, enum cfctrl_srv serv,
return;
}
layer_set_dn(servicel, cnfg->mux);
- cfmuxl_set_uplayer(cnfg->mux, servicel, linkid);
+ cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id);
layer_set_up(servicel, adapt_layer);
layer_set_dn(adapt_layer, servicel);
servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0);
--
1.6.3.3
^ permalink raw reply related
* [PATCH net-next-2.6 1/7] caif: Ldisc add permission check and mem-alloc error check
From: sjur.brandeland @ 2010-04-28 18:54 UTC (permalink / raw)
To: netdev, davem
Cc: marcel, daniel.martensson, sjurbr, linus.walleij,
Sjur Braendeland
From: Sjur Braendeland <sjur.brandeland@stericsson.com>
Changes:
o Added permission checks for installing. CAP_SYS_ADMIN and
CAP_SYS_TTY_CONFIG can install the ldisc.
o Check if allocation of skb was successful.
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com>
---
drivers/net/caif/caif_serial.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 38c0186..09257ca 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -197,7 +197,8 @@ static void ldisc_receive(struct tty_struct *tty, const u8 *data,
/* Get a suitable caif packet and copy in data. */
skb = netdev_alloc_skb(ser->dev, count+1);
- BUG_ON(skb == NULL);
+ if (skb == NULL)
+ return;
p = skb_put(skb, count);
memcpy(p, data, count);
@@ -315,6 +316,8 @@ static int ldisc_open(struct tty_struct *tty)
/* No write no play */
if (tty->ops->write == NULL)
return -EOPNOTSUPP;
+ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_TTY_CONFIG))
+ return -EPERM;
sprintf(name, "cf%s", tty->name);
dev = alloc_netdev(sizeof(*ser), name, caifdev_setup);
--
1.6.3.3
^ permalink raw reply related
* Re: [net-next-2.6 PATCH 1/2] Add netdev port-profile support (take III, was iovnl)
From: Scott Feldman @ 2010-04-28 18:54 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: davem, netdev, chrisw
In-Reply-To: <201004281513.58879.arnd@arndb.de>
On 4/28/10 6:13 AM, "Arnd Bergmann" <arnd@arndb.de> wrote:
> What I could imagine to unify this is something like
>
> ip port_profile set DEVICE [ { pre_associate | pre_associate_rr } ]
> { name PORT-PROFILE | vsi MGR:VTID:VER }
> mac LLADDR
> [ vlan VID ]
> [ host_uuid HOST_UUID ]
> [ client_uuid CLIENT_UUID ]
> [ client_name CLIENT_NAME ]
> ip port_profile del DEVICE [ mac LLADDR [ vlan VID ] ]
> ip port_profile show DEVICE
Arnd, can someone test this with VDP today? I don't have access to that
equipment so it's difficult for me to fully test the unified patch. I can
test the previous patch with enic easily because I have access to production
systems. I'd like to make sure someone can test this with VDP before I
respin the patch one more time.
-scott
^ permalink raw reply
* Re: [PATCH]: sctp: Fix skb_over_panic resulting from multiple invalid parameter errors (CVE-2010-1173)
From: Neil Horman @ 2010-04-28 18:52 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: sri, linux-sctp, eteo, netdev, davem, security
In-Reply-To: <4BD87DFF.6080502@hp.com>
On Wed, Apr 28, 2010 at 02:27:11PM -0400, Vlad Yasevich wrote:
>
>
> Neil Horman wrote:
> > On Wed, Apr 28, 2010 at 01:52:05PM -0400, Vlad Yasevich wrote:
> >>
> >> Vlad Yasevich wrote:
> >>> Neil Horman wrote:
> >>>> On Wed, Apr 28, 2010 at 10:00:37AM -0400, Vlad Yasevich wrote:
> >>>>> I have this patch and a few others already queued.
> >>>>>
> >>>>> I was planning on sending these today for stable.
> >>>>>
> >>>>> Here is the full list of stable patches I have:
> >>>>>
> >>>>> sctp: Fix oops when sending queued ASCONF chunks
> >>>>> sctp: fix to calc the INIT/INIT-ACK chunk length correctly is set
> >>>>> sctp: per_cpu variables should be in bh_disabled section
> >>>>> sctp: fix potential reference of a freed pointer
> >>>>> sctp: avoid irq lock inversion while call sk->sk_data_ready()
> >>>>>
> >>>>> -vlad
> >>>>>
> >>>> Are you sure? this oops looks _very_ simmilar to the INIT/INIT-ACK length
> >>>> calculation oops described above, but is in fact different, and requires this
> >>>> patch, from what I can see. The right fix might be in the ASCONF chunk patch
> >>>> you list above, but I don't see that in your tree at the moment, so I can't be
> >>>> sure.
> >>> As I said, I totally goofed when reading the description and I apologize.
> >>> However, I do one comment regarding the patch.
> >>>
> >>> If the bad packet is REALLY long (I mean close to 65K IP limit), then
> >>> we'll end up allocating a supper huge skb in this case and potentially exceed
> >>> the IP length limitation. Section 11.4 of rfc 4960 allows us to omit some
> >>> errors and limit the size of the packet.
> >>>
> >>> I would recommend limiting this to MTU worth of potentiall errors. This is
> >>> on top of what the INIT-ACK is going to carry, so at most we'll sent 2 MTUs
> >>> worth. That's still a potential by amplification attack, but it's somewhat
> >>> mitigated.
> >>>
> >>> Of course now we have to handle the case of checking for space before adding
> >>> an error cause. :)
> >>>
> >> Hi Neil
> >>
> >> I am also not crazy about the pre-allocation scheme. In the case where you have
> >> say 100 parameters that are all 'skip' parameters, you'd end up pre-allocating a
> >> huge buffer for absolutely nothing.
> >>
> > Would have been nice if you'd made your opinion known 4 hours ago when I was
> > testing version 2 of this. :)
> >
>
> sorry, fighting a head cold and need drugs to think clearly... ;)
>
Its ok, I'm apparently just feeling a bit short tempered today. Apologies, hope
your feeling better soon :)
>
> >> This is another point toward a fixed error chunk size and let parameter
> >> processing allocate it when it reaches a parameter that needs an error.
> >>
> > Hmm, ok, what would you say to a pathmtu sized chunk allocation in parameter
> > processing that drops errors beyond its capacity
> > Neil
>
> Here is my quick take on this. Haven't tested it at all.
>
I think somthing like this will work, I've got a variant that uses some helper
functions to create and manipulate fixed length op error chunks going right now.
It does basically the same thing that your doing, but consolidates the checking
of remaining space to a central place. I think that might be better, as during
my looking at this version, I found two other points that might be vulnerable to
this error (haven't tested to confirm yet though). I'll post shortly.
Thanks!
Neil
^ permalink raw reply
* [PATCH 5/5] sctp: Fix oops when sending queued ASCONF chunks
From: Vlad Yasevich @ 2010-04-28 18:47 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-sctp, Vlad Yasevich, Yuansong Qiao, Shuaijun Zhang
In-Reply-To: <1272480442-32673-1-git-send-email-vladislav.yasevich@hp.com>
When we finish processing ASCONF_ACK chunk, we try to send
the next queued ASCONF. This action runs the sctp state
machine recursively and it's not prepared to do so.
kernel BUG at kernel/timer.c:790!
invalid opcode: 0000 [#1] SMP
last sysfs file: /sys/module/ipv6/initstate
Modules linked in: sha256_generic sctp libcrc32c ipv6 dm_multipath
uinput 8139too i2c_piix4 8139cp mii i2c_core pcspkr virtio_net joydev
floppy virtio_blk virtio_pci [last unloaded: scsi_wait_scan]
Pid: 0, comm: swapper Not tainted 2.6.34-rc4 #15 /Bochs
EIP: 0060:[<c044a2ef>] EFLAGS: 00010286 CPU: 0
EIP is at add_timer+0xd/0x1b
EAX: cecbab14 EBX: 000000f0 ECX: c0957b1c EDX: 03595cf4
ESI: cecba800 EDI: cf276f00 EBP: c0957aa0 ESP: c0957aa0
DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
Process swapper (pid: 0, ti=c0956000 task=c0988ba0 task.ti=c0956000)
Stack:
c0957ae0 d1851214 c0ab62e4 c0ab5f26 0500ffff 00000004 00000005 00000004
<0> 00000000 d18694fd 00000004 1666b892 cecba800 cecba800 c0957b14
00000004
<0> c0957b94 d1851b11 ceda8b00 cecba800 cf276f00 00000001 c0957b14
000000d0
Call Trace:
[<d1851214>] ? sctp_side_effects+0x607/0xdfc [sctp]
[<d1851b11>] ? sctp_do_sm+0x108/0x159 [sctp]
[<d1863386>] ? sctp_pname+0x0/0x1d [sctp]
[<d1861a56>] ? sctp_primitive_ASCONF+0x36/0x3b [sctp]
[<d185657c>] ? sctp_process_asconf_ack+0x2a4/0x2d3 [sctp]
[<d184e35c>] ? sctp_sf_do_asconf_ack+0x1dd/0x2b4 [sctp]
[<d1851ac1>] ? sctp_do_sm+0xb8/0x159 [sctp]
[<d1863334>] ? sctp_cname+0x0/0x52 [sctp]
[<d1854377>] ? sctp_assoc_bh_rcv+0xac/0xe1 [sctp]
[<d1858f0f>] ? sctp_inq_push+0x2d/0x30 [sctp]
[<d186329d>] ? sctp_rcv+0x797/0x82e [sctp]
Tested-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: Yuansong Qiao <ysqiao@research.ait.ie>
Signed-off-by: Shuaijun Zhang <szhang@research.ait.ie>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
---
include/net/sctp/command.h | 1 +
net/sctp/sm_make_chunk.c | 15 ---------------
net/sctp/sm_sideeffect.c | 26 ++++++++++++++++++++++++++
net/sctp/sm_statefuns.c | 8 +++++++-
4 files changed, 34 insertions(+), 16 deletions(-)
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 8be5135..2c55a7e 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -107,6 +107,7 @@ typedef enum {
SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */
SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */
SCTP_CMD_SEND_MSG, /* Send the whole use message */
+ SCTP_CMD_SEND_NEXT_ASCONF, /* Send the next ASCONF after ACK */
SCTP_CMD_LAST
} sctp_verb_t;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index f6fc5c1..0fd5b4c 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3318,21 +3318,6 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
sctp_chunk_free(asconf);
asoc->addip_last_asconf = NULL;
- /* Send the next asconf chunk from the addip chunk queue. */
- if (!list_empty(&asoc->addip_chunk_list)) {
- struct list_head *entry = asoc->addip_chunk_list.next;
- asconf = list_entry(entry, struct sctp_chunk, list);
-
- list_del_init(entry);
-
- /* Hold the chunk until an ASCONF_ACK is received. */
- sctp_chunk_hold(asconf);
- if (sctp_primitive_ASCONF(asoc, asconf))
- sctp_chunk_free(asconf);
- else
- asoc->addip_last_asconf = asconf;
- }
-
return retval;
}
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 4c5bed9..d5ae450 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -962,6 +962,29 @@ static int sctp_cmd_send_msg(struct sctp_association *asoc,
}
+/* Sent the next ASCONF packet currently stored in the association.
+ * This happens after the ASCONF_ACK was succeffully processed.
+ */
+static void sctp_cmd_send_asconf(struct sctp_association *asoc)
+{
+ /* Send the next asconf chunk from the addip chunk
+ * queue.
+ */
+ if (!list_empty(&asoc->addip_chunk_list)) {
+ struct list_head *entry = asoc->addip_chunk_list.next;
+ struct sctp_chunk *asconf = list_entry(entry,
+ struct sctp_chunk, list);
+ list_del_init(entry);
+
+ /* Hold the chunk until an ASCONF_ACK is received. */
+ sctp_chunk_hold(asconf);
+ if (sctp_primitive_ASCONF(asoc, asconf))
+ sctp_chunk_free(asconf);
+ else
+ asoc->addip_last_asconf = asconf;
+ }
+}
+
/* These three macros allow us to pull the debugging code out of the
* main flow of sctp_do_sm() to keep attention focused on the real
@@ -1617,6 +1640,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
}
error = sctp_cmd_send_msg(asoc, cmd->obj.msg);
break;
+ case SCTP_CMD_SEND_NEXT_ASCONF:
+ sctp_cmd_send_asconf(asoc);
+ break;
default:
printk(KERN_WARNING "Impossible command: %u, %p\n",
cmd->verb, cmd->obj.ptr);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index abf601a..24b2cd5 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3676,8 +3676,14 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
if (!sctp_process_asconf_ack((struct sctp_association *)asoc,
- asconf_ack))
+ asconf_ack)) {
+ /* Successfully processed ASCONF_ACK. We can
+ * release the next asconf if we have one.
+ */
+ sctp_add_cmd_sf(commands, SCTP_CMD_SEND_NEXT_ASCONF,
+ SCTP_NULL());
return SCTP_DISPOSITION_CONSUME;
+ }
abort = sctp_make_abort(asoc, asconf_ack,
sizeof(sctp_errhdr_t));
--
1.6.0.4
^ permalink raw reply related
* [PATCH 4/5] sctp: fix to calc the INIT/INIT-ACK chunk length correctly is set
From: Vlad Yasevich @ 2010-04-28 18:47 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-sctp, Wei Yongjun, Vlad Yasevich
In-Reply-To: <1272480442-32673-1-git-send-email-vladislav.yasevich@hp.com>
From: Wei Yongjun <yjwei@cn.fujitsu.com>
When calculating the INIT/INIT-ACK chunk length, we should not
only account the length of parameters, but also the parameters
zero padding length, such as AUTH HMACS parameter and CHUNKS
parameter. Without the parameters zero padding length we may get
following oops.
skb_over_panic: text:ce2068d2 len:130 put:6 head:cac3fe00 data:cac3fe00 tail:0xcac3fe82 end:0xcac3fe80 dev:<NULL>
------------[ cut here ]------------
kernel BUG at net/core/skbuff.c:127!
invalid opcode: 0000 [#2] SMP
last sysfs file: /sys/module/aes_generic/initstate
Modules linked in: authenc ......
Pid: 4102, comm: sctp_darn Tainted: G D 2.6.34-rc2 #6
EIP: 0060:[<c0607630>] EFLAGS: 00010282 CPU: 0
EIP is at skb_over_panic+0x37/0x3e
EAX: 00000078 EBX: c07c024b ECX: c07c02b9 EDX: cb607b78
ESI: 00000000 EDI: cac3fe7a EBP: 00000002 ESP: cb607b74
DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
Process sctp_darn (pid: 4102, ti=cb607000 task=cabdc990 task.ti=cb607000)
Stack:
c07c02b9 ce2068d2 00000082 00000006 cac3fe00 cac3fe00 cac3fe82 cac3fe80
<0> c07c024b cac3fe7c cac3fe7a c0608dec ca986e80 ce2068d2 00000006 0000007a
<0> cb8120ca ca986e80 cb812000 00000003 cb8120c4 ce208a25 cb8120ca cadd9400
Call Trace:
[<ce2068d2>] ? sctp_addto_chunk+0x45/0x85 [sctp]
[<c0608dec>] ? skb_put+0x2e/0x32
[<ce2068d2>] ? sctp_addto_chunk+0x45/0x85 [sctp]
[<ce208a25>] ? sctp_make_init+0x279/0x28c [sctp]
[<c0686a92>] ? apic_timer_interrupt+0x2a/0x30
[<ce1fdc0b>] ? sctp_sf_do_prm_asoc+0x2b/0x7b [sctp]
[<ce202823>] ? sctp_do_sm+0xa0/0x14a [sctp]
[<ce2133b9>] ? sctp_pname+0x0/0x14 [sctp]
[<ce211d72>] ? sctp_primitive_ASSOCIATE+0x2b/0x31 [sctp]
[<ce20f3cf>] ? sctp_sendmsg+0x7a0/0x9eb [sctp]
[<c064eb1e>] ? inet_sendmsg+0x3b/0x43
[<c04244b7>] ? task_tick_fair+0x2d/0xd9
[<c06031e1>] ? sock_sendmsg+0xa7/0xc1
[<c0416afe>] ? smp_apic_timer_interrupt+0x6b/0x75
[<c0425123>] ? dequeue_task_fair+0x34/0x19b
[<c0446abb>] ? sched_clock_local+0x17/0x11e
[<c052ea87>] ? _copy_from_user+0x2b/0x10c
[<c060ab3a>] ? verify_iovec+0x3c/0x6a
[<c06035ca>] ? sys_sendmsg+0x186/0x1e2
[<c042176b>] ? __wake_up_common+0x34/0x5b
[<c04240c2>] ? __wake_up+0x2c/0x3b
[<c057e35c>] ? tty_wakeup+0x43/0x47
[<c04430f2>] ? remove_wait_queue+0x16/0x24
[<c0580c94>] ? n_tty_read+0x5b8/0x65e
[<c042be02>] ? default_wake_function+0x0/0x8
[<c0604e0e>] ? sys_socketcall+0x17f/0x1cd
[<c040264c>] ? sysenter_do_call+0x12/0x22
Code: 0f 45 de 53 ff b0 98 00 00 00 ff b0 94 ......
EIP: [<c0607630>] skb_over_panic+0x37/0x3e SS:ESP 0068:cb607b74
To reproduce:
# modprobe sctp
# echo 1 > /proc/sys/net/sctp/addip_enable
# echo 1 > /proc/sys/net/sctp/auth_enable
# sctp_test -H 3ffe:501:ffff:100:20c:29ff:fe4d:f37e -P 800 -l
# sctp_darn -H 3ffe:501:ffff:100:20c:29ff:fe4d:f37e -P 900 -h 192.168.0.21 -p 800 -I -s -t
sctp_darn ready to send...
3ffe:501:ffff:100:20c:29ff:fe4d:f37e:900-192.168.0.21:800 Interactive mode> bindx-add=192.168.0.21
3ffe:501:ffff:100:20c:29ff:fe4d:f37e:900-192.168.0.21:800 Interactive mode> bindx-add=192.168.1.21
3ffe:501:ffff:100:20c:29ff:fe4d:f37e:900-192.168.0.21:800 Interactive mode> snd=10
------------------------------------------------------------------
eth0 has addresses: 3ffe:501:ffff:100:20c:29ff:fe4d:f37e and 192.168.0.21
eth1 has addresses: 192.168.1.21
------------------------------------------------------------------
Reported-by: George Cheimonidis <gchimon@gmail.com>
Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
---
net/sctp/sm_make_chunk.c | 17 ++++++++++-------
1 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 17cb400..f6fc5c1 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -208,7 +208,8 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
sp = sctp_sk(asoc->base.sk);
num_types = sp->pf->supported_addrs(sp, types);
- chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN(num_types);
+ chunksize = sizeof(init) + addrs_len;
+ chunksize += WORD_ROUND(SCTP_SAT_LEN(num_types));
chunksize += sizeof(ecap_param);
if (sctp_prsctp_enable)
@@ -238,14 +239,14 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
/* Add HMACS parameter length if any were defined */
auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs;
if (auth_hmacs->length)
- chunksize += ntohs(auth_hmacs->length);
+ chunksize += WORD_ROUND(ntohs(auth_hmacs->length));
else
auth_hmacs = NULL;
/* Add CHUNKS parameter length */
auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks;
if (auth_chunks->length)
- chunksize += ntohs(auth_chunks->length);
+ chunksize += WORD_ROUND(ntohs(auth_chunks->length));
else
auth_chunks = NULL;
@@ -255,7 +256,8 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
/* If we have any extensions to report, account for that */
if (num_ext)
- chunksize += sizeof(sctp_supported_ext_param_t) + num_ext;
+ chunksize += WORD_ROUND(sizeof(sctp_supported_ext_param_t) +
+ num_ext);
/* RFC 2960 3.3.2 Initiation (INIT) (1)
*
@@ -397,13 +399,13 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs;
if (auth_hmacs->length)
- chunksize += ntohs(auth_hmacs->length);
+ chunksize += WORD_ROUND(ntohs(auth_hmacs->length));
else
auth_hmacs = NULL;
auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks;
if (auth_chunks->length)
- chunksize += ntohs(auth_chunks->length);
+ chunksize += WORD_ROUND(ntohs(auth_chunks->length));
else
auth_chunks = NULL;
@@ -412,7 +414,8 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
}
if (num_ext)
- chunksize += sizeof(sctp_supported_ext_param_t) + num_ext;
+ chunksize += WORD_ROUND(sizeof(sctp_supported_ext_param_t) +
+ num_ext);
/* Now allocate and fill out the chunk. */
retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize);
--
1.6.0.4
^ permalink raw reply related
* [PATCH 3/5] sctp: per_cpu variables should be in bh_disabled section
From: Vlad Yasevich @ 2010-04-28 18:47 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-sctp, Vlad Yasevich
In-Reply-To: <1272480442-32673-1-git-send-email-vladislav.yasevich@hp.com>
Since the change of the atomics to percpu variables, we now
have to disable BH in process context when touching percpu variables.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
---
net/sctp/socket.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index efa2bc3..44a1ab0 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3719,12 +3719,12 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
sp->hmac = NULL;
SCTP_DBG_OBJCNT_INC(sock);
- percpu_counter_inc(&sctp_sockets_allocated);
/* Set socket backlog limit. */
sk->sk_backlog.limit = sysctl_sctp_rmem[1];
local_bh_disable();
+ percpu_counter_inc(&sctp_sockets_allocated);
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
local_bh_enable();
@@ -3741,8 +3741,8 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk)
/* Release our hold on the endpoint. */
ep = sctp_sk(sk)->ep;
sctp_endpoint_free(ep);
- percpu_counter_dec(&sctp_sockets_allocated);
local_bh_disable();
+ percpu_counter_dec(&sctp_sockets_allocated);
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
local_bh_enable();
}
--
1.6.0.4
^ permalink raw reply related
* [PATCH 1/5] sctp: avoid irq lock inversion while call sk->sk_data_ready()
From: Vlad Yasevich @ 2010-04-28 18:47 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-sctp, Wei Yongjun, Vlad Yasevich
In-Reply-To: <1272480442-32673-1-git-send-email-vladislav.yasevich@hp.com>
From: Wei Yongjun <yjwei@cn.fujitsu.com>
sk->sk_data_ready() of sctp socket can be called from both BH and non-BH
contexts, but the default sk->sk_data_ready(), sock_def_readable(), can
not be used in this case. Therefore, we have to make a new function
sctp_data_ready() to grab sk->sk_data_ready() with BH disabling.
=========================================================
[ INFO: possible irq lock inversion dependency detected ]
2.6.33-rc6 #129
---------------------------------------------------------
sctp_darn/1517 just changed the state of lock:
(clock-AF_INET){++.?..}, at: [<c06aab60>] sock_def_readable+0x20/0x80
but this lock took another, SOFTIRQ-unsafe lock in the past:
(slock-AF_INET){+.-...}
and interrupts could create inverse lock ordering between them.
other info that might help us debug this:
1 lock held by sctp_darn/1517:
#0: (sk_lock-AF_INET){+.+.+.}, at: [<cdfe363d>] sctp_sendmsg+0x23d/0xc00 [sctp]
Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
---
include/net/sctp/sctp.h | 1 +
net/sctp/endpointola.c | 1 +
net/sctp/socket.c | 10 ++++++++++
3 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 78740ec..fa6cde5 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -128,6 +128,7 @@ extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
int sctp_inet_listen(struct socket *sock, int backlog);
void sctp_write_space(struct sock *sk);
+void sctp_data_ready(struct sock *sk, int len);
unsigned int sctp_poll(struct file *file, struct socket *sock,
poll_table *wait);
void sctp_sock_rfree(struct sk_buff *skb);
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 905fda5..7ec09ba 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -144,6 +144,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
/* Use SCTP specific send buffer space queues. */
ep->sndbuf_policy = sctp_sndbuf_policy;
+ sk->sk_data_ready = sctp_data_ready;
sk->sk_write_space = sctp_write_space;
sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 007e8ba..efa2bc3 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6189,6 +6189,16 @@ do_nonblock:
goto out;
}
+void sctp_data_ready(struct sock *sk, int len)
+{
+ read_lock_bh(&sk->sk_callback_lock);
+ if (sk_has_sleeper(sk))
+ wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN |
+ POLLRDNORM | POLLRDBAND);
+ sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
+ read_unlock_bh(&sk->sk_callback_lock);
+}
+
/* If socket sndbuf has changed, wake up all per association waiters. */
void sctp_write_space(struct sock *sk)
{
--
1.6.0.4
^ permalink raw reply related
* [PATCH 2/5] sctp: fix potential reference of a freed pointer
From: Vlad Yasevich @ 2010-04-28 18:47 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-sctp, Vlad Yasevich
In-Reply-To: <1272480442-32673-1-git-send-email-vladislav.yasevich@hp.com>
When sctp attempts to update an assocition, it removes any
addresses that were not in the updated INITs. However, the loop
may attempt to refrence a transport with address after removing it.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
---
net/sctp/associola.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index df5abbf..99c93ee 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1194,8 +1194,10 @@ void sctp_assoc_update(struct sctp_association *asoc,
/* Remove any peer addresses not present in the new association. */
list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
trans = list_entry(pos, struct sctp_transport, transports);
- if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr))
- sctp_assoc_del_peer(asoc, &trans->ipaddr);
+ if (!sctp_assoc_lookup_paddr(new, &trans->ipaddr)) {
+ sctp_assoc_rm_peer(asoc, trans);
+ continue;
+ }
if (asoc->state >= SCTP_STATE_ESTABLISHED)
sctp_transport_reset(trans);
--
1.6.0.4
^ permalink raw reply related
* sctp patches for net-2.6
From: Vlad Yasevich @ 2010-04-28 18:47 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-sctp
Hi David
The following are the patches for the current net-2.6 tree that
solve some critical issues. Please consider pushing them to
stable as well.
Thanks
-vlad
^ permalink raw reply
* Re: [net-next-2.6 PATCH 2/2] add ndo_set_port_profile op support for enic dynamic vnics
From: Scott Feldman @ 2010-04-28 18:39 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: davem, netdev, chrisw
In-Reply-To: <201004281532.47875.arnd@arndb.de>
On 4/28/10 6:32 AM, "Arnd Bergmann" <arnd@arndb.de> wrote:
> On Wednesday 28 April 2010, Scott Feldman wrote:
>> +static int enic_set_port_profile(struct net_device *netdev,
>> + struct ifla_port_profile *ipp)
>> +{
>> + struct enic *enic = netdev_priv(netdev);
>> + struct vic_provinfo *vp;
>> + u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
>> + u8 *mac = ipp->mac;
>> + int err;
>> +
>> + memset(&enic->port_profile, 0, sizeof(enic->port_profile));
>> +
>> + if (!enic_is_dynamic(enic))
>> + return -EOPNOTSUPP;
>
> Not sure I understand how this fits together. You said in an earlier mail:
>
>>> Anything that ties port profiles to VFs seems fundamentally flawed AFAICT,
>>> at least when we want to extend this to adapters that don't do it in
>>> firmware.
>>
>> Ya, I tend I agree. Let's just make port-profile a setting of any netdev,
>> an eth, macvtap, eth.x, bond, etc. That's probably what I should have done
>> in the first place. Something like:
>
> I thought you had meant that we can do the association of attached interfaces
> through any interface, rather than tying it to the slave interface. While I'm
> not sure I read your code correctly, it seems like you now only talk to the
> slave interface, not to the master at all!
>
> At least the check above should be 'if (enic_is_dynamic(enic)) return
> -EOPNOTSUPP', not the other way round.
> Moreover, if the netdev is the master here, you only allow a single slave,
> which is not enough for larger setups (n > 1), though that could be a
> limitation of your first version.
The code is correct. I probably confused you with earlier patches trying to
accommodate master/slave devices and you might have assumed enic was such a
device. But it's not. For enic, there are two device IDs, let's call one
"static" and the other "dynamic". The only difference between the two is
static enics load up fully ready to go just like a normal nic, whereas
dynamic enics load up but can't yet pass traffic because they're not
"plugged in" to the network. To plug them in, you need to associate a
port-profile. The physical analogy is this: server admin tells network
admin: plug my nic into a switch port with these characteristics. Here, the
port-profile describes those switch port characteristics. Now, there is no
master/slave relationship between static and dynamic enics. There could be
with a simple firmware update, but it's not there today. Also, I want to
point out that a single phys Cisco nic can be provisioned to expose many
static and/or many dynamic enics to the host. On the order of 100s. The
code above is to block port-profile association on static enics. Static
enics where already provisioned on the network when created so there is no
need for a port-profile push from the host.
> Passing just the slave device however would not work in the general case, as I
> tried to point out in the mail you replied to. If the slave interface is owned
> by a guest using PCI passthrough, or it sits below a stack of nested
> interfaces
> (vlan, bridge, tap, vhost, ...), it's impossible to know what interface is
> responsible for setting up the slave.
For port-profile, we want to pass the device that is to be "plugged-in" to
the network based on port-profile association. This is the device that
gives basic connectivity to the guest interface, regardless of how the guest
interface is wired to the device. It could be direct PCI pass-thru, macvtap
stack, some yet-to-be-invented kernel-bypass stack, etc.
> Note that you cannot perform the association
> through the slave interface itself because the remote switch would discard any
> traffic originating from an unassociated interface.
That's not a limitation of our device/switch.
-scott
^ permalink raw reply
* Re: [PATCH]: sctp: Fix skb_over_panic resulting from multiple invalid parameter errors (CVE-2010-1173)
From: Vlad Yasevich @ 2010-04-28 18:27 UTC (permalink / raw)
To: Neil Horman; +Cc: sri, linux-sctp, eteo, netdev, davem, security
In-Reply-To: <20100428181645.GD4818@hmsreliant.think-freely.org>
[-- Attachment #1: Type: text/plain, Size: 2614 bytes --]
Neil Horman wrote:
> On Wed, Apr 28, 2010 at 01:52:05PM -0400, Vlad Yasevich wrote:
>>
>> Vlad Yasevich wrote:
>>> Neil Horman wrote:
>>>> On Wed, Apr 28, 2010 at 10:00:37AM -0400, Vlad Yasevich wrote:
>>>>> I have this patch and a few others already queued.
>>>>>
>>>>> I was planning on sending these today for stable.
>>>>>
>>>>> Here is the full list of stable patches I have:
>>>>>
>>>>> sctp: Fix oops when sending queued ASCONF chunks
>>>>> sctp: fix to calc the INIT/INIT-ACK chunk length correctly is set
>>>>> sctp: per_cpu variables should be in bh_disabled section
>>>>> sctp: fix potential reference of a freed pointer
>>>>> sctp: avoid irq lock inversion while call sk->sk_data_ready()
>>>>>
>>>>> -vlad
>>>>>
>>>> Are you sure? this oops looks _very_ simmilar to the INIT/INIT-ACK length
>>>> calculation oops described above, but is in fact different, and requires this
>>>> patch, from what I can see. The right fix might be in the ASCONF chunk patch
>>>> you list above, but I don't see that in your tree at the moment, so I can't be
>>>> sure.
>>> As I said, I totally goofed when reading the description and I apologize.
>>> However, I do one comment regarding the patch.
>>>
>>> If the bad packet is REALLY long (I mean close to 65K IP limit), then
>>> we'll end up allocating a supper huge skb in this case and potentially exceed
>>> the IP length limitation. Section 11.4 of rfc 4960 allows us to omit some
>>> errors and limit the size of the packet.
>>>
>>> I would recommend limiting this to MTU worth of potentiall errors. This is
>>> on top of what the INIT-ACK is going to carry, so at most we'll sent 2 MTUs
>>> worth. That's still a potential by amplification attack, but it's somewhat
>>> mitigated.
>>>
>>> Of course now we have to handle the case of checking for space before adding
>>> an error cause. :)
>>>
>> Hi Neil
>>
>> I am also not crazy about the pre-allocation scheme. In the case where you have
>> say 100 parameters that are all 'skip' parameters, you'd end up pre-allocating a
>> huge buffer for absolutely nothing.
>>
> Would have been nice if you'd made your opinion known 4 hours ago when I was
> testing version 2 of this. :)
>
sorry, fighting a head cold and need drugs to think clearly... ;)
>> This is another point toward a fixed error chunk size and let parameter
>> processing allocate it when it reaches a parameter that needs an error.
>>
> Hmm, ok, what would you say to a pathmtu sized chunk allocation in parameter
> processing that drops errors beyond its capacity
> Neil
Here is my quick take on this. Haven't tested it at all.
-vlad
[-- Attachment #2: neil --]
[-- Type: text/plain, Size: 3987 bytes --]
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 0fd5b4c..74d8d21 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1959,8 +1959,10 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,
union sctp_params param,
struct sctp_chunk *chunk,
- struct sctp_chunk **errp)
+ struct sctp_chunk **errp,
+ unsigned int param_cnt)
{
+ unsigned int needed_bytes;
int retval = SCTP_IERROR_NO_ERROR;
switch (param.p->type & SCTP_PARAM_ACTION_MASK) {
@@ -1976,11 +1978,41 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,
/* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters.
*/
- if (NULL == *errp)
- *errp = sctp_make_op_error_space(asoc, chunk,
- ntohs(chunk->chunk_hdr->length));
+ if (NULL == *errp) {
+ unsigned int len;
+
+ /* Reserver space for the worst possible case
+ * at this time. We count incomming chunk length
+ * since error parameters carry the bad parameter
+ * inself, plus have space for error headers for
+ * the remaining number of parameters.
+ */
+ len = ntohs(chunk->chunk_hdr->length);
+ len += sizeof(sctp_errhdr_t) * param_cnt;
+
+ /* We need to prevent amplification attacks that
+ * result from sending 65K init chunks with all bad
+ * params maliciously, so lets limit our error response
+ * to 1 MTU worth of errors, but at least 1500 bytes
+ * in case our pathmtu hasn't been updated yet.
+ */
+ len = min(len, asoc ? asoc->pathmtu :
+ SCTP_DEFAULT_MAXSEGMENT);
+ *errp = sctp_make_op_error_space(asoc, chunk, len);
+ }
if (*errp) {
+ needed_bytes = sizeof(sctp_errhdr_t) +
+ WORD_ROUND(ntohs(param.p->length));
+
+ if (skb_tailroom((*errp)->skb) < needed_bytes)
+ /*
+ * If we're over our packet size here, don't add
+ * the error, this is allowed by section 11.4 of
+ * RFC 4960
+ */
+ break;
+
sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
WORD_ROUND(ntohs(param.p->length)));
sctp_addto_chunk(*errp,
@@ -2013,7 +2045,8 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc,
union sctp_params param,
sctp_cid_t cid,
struct sctp_chunk *chunk,
- struct sctp_chunk **err_chunk)
+ struct sctp_chunk **err_chunk,
+ unsigned int param_cnt)
{
struct sctp_hmac_algo_param *hmacs;
int retval = SCTP_IERROR_NO_ERROR;
@@ -2119,7 +2152,8 @@ fallthrough:
default:
SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",
ntohs(param.p->type), cid);
- retval = sctp_process_unk_param(asoc, param, chunk, err_chunk);
+ retval = sctp_process_unk_param(asoc, param, chunk, err_chunk,
+ param_cnt);
break;
}
return retval;
@@ -2135,6 +2169,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
union sctp_params param;
int has_cookie = 0;
int result;
+ unsigned int param_cnt = 0;
/* Verify stream values are non-zero. */
if ((0 == peer_init->init_hdr.num_outbound_streams) ||
@@ -2150,6 +2185,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
if (SCTP_PARAM_STATE_COOKIE == param.p->type)
has_cookie = 1;
+ param_cnt++;
} /* for (loop through all parameters) */
@@ -2173,7 +2209,8 @@ int sctp_verify_init(const struct sctp_association *asoc,
/* Verify all the variable length parameters */
sctp_walk_params(param, peer_init, init_hdr.params) {
- result = sctp_verify_param(asoc, param, cid, chunk, errp);
+ result = sctp_verify_param(asoc, param, cid, chunk, errp,
+ param_cnt);
switch (result) {
case SCTP_IERROR_ABORT:
case SCTP_IERROR_NOMEM:
@@ -2184,6 +2221,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
default:
break;
}
+ param_cnt--;
} /* for (loop through all parameters) */
^ permalink raw reply related
* Re: [PATCH] forcedeth: Stay in NAPI as long as there's work
From: Stephen Hemminger @ 2010-04-28 18:25 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Joe Perches, Tom Herbert, netdev, aabdulla, davem
In-Reply-To: <20100428111354.49a6ec1a@nehalam>
The following does the same thing without the extra overhead
of testing all the registers. It also handles the out of memory
case.
Compile tested only...
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/drivers/net/forcedeth.c 2010-04-28 11:14:29.784799317 -0700
+++ b/drivers/net/forcedeth.c 2010-04-28 11:23:53.254354744 -0700
@@ -3743,23 +3743,26 @@ static int nv_napi_poll(struct napi_stru
u8 __iomem *base = get_hwbase(dev);
unsigned long flags;
int retcode;
- int tx_work, rx_work;
+ int rx_count, tx_work=0, rx_work=0;
- if (!nv_optimized(np)) {
- spin_lock_irqsave(&np->lock, flags);
- tx_work = nv_tx_done(dev, np->tx_ring_size);
- spin_unlock_irqrestore(&np->lock, flags);
+ do {
+ if (!nv_optimized(np)) {
+ spin_lock_irqsave(&np->lock, flags);
+ tx_work += nv_tx_done(dev, np->tx_ring_size);
+ spin_unlock_irqrestore(&np->lock, flags);
- rx_work = nv_rx_process(dev, budget);
- retcode = nv_alloc_rx(dev);
- } else {
- spin_lock_irqsave(&np->lock, flags);
- tx_work = nv_tx_done_optimized(dev, np->tx_ring_size);
- spin_unlock_irqrestore(&np->lock, flags);
+ rx_count = nv_rx_process(dev, budget);
+ retcode = nv_alloc_rx(dev);
+ } else {
+ spin_lock_irqsave(&np->lock, flags);
+ tx_work += nv_tx_done_optimized(dev, np->tx_ring_size);
+ spin_unlock_irqrestore(&np->lock, flags);
- rx_work = nv_rx_process_optimized(dev, budget);
- retcode = nv_alloc_rx_optimized(dev);
- }
+ rx_count = nv_rx_process_optimized(dev, budget);
+ retcode = nv_alloc_rx_optimized(dev);
+ }
+ } while (retcode == 0 &&
+ rx_count > 0 && (rx_work += rx_count) < budget);
if (retcode) {
spin_lock_irqsave(&np->lock, flags);
^ permalink raw reply
* Re: [PATCH] forcedeth: Stay in NAPI as long as there's work
From: Tom Herbert @ 2010-04-28 18:18 UTC (permalink / raw)
To: Joe Perches; +Cc: netdev, aabdulla, davem
In-Reply-To: <g2t65634d661004281107j676369c9ge379434723478c1@mail.gmail.com>
On Wed, Apr 28, 2010 at 11:07 AM, Tom Herbert <therbert@google.com> wrote:
>>
>> It might be better to test the comparisons using
>> a cpu_to_le32 of the constants.
>>
> Yes. Probably should also be changed in nv_tx_done{_optimized} and
> nv_rx_process{_optimized}
>
Scratch that. flags are checked all over the place in those other functions.
>> static inline int nv_has_work(struct fe_priv *np)
>> {
>> if (nv_optimized(np))
>> return ((np->get_rx.ex != np->put_rx.ex) &&
>> !(np->get_rx.ex->flaglen & cpu_to_le32(NV_RX2_AVAIL))) ||
>> ((np->get_tx.ex != np->put_tx.ex) &&
>> !(np->get_tx.ex->flaglen & cpu_to_le32(NV_TX_VALID)));
>>
>> return ((np->get_rx.orig != np->put_rx.orig) &&
>> !(np->get_rx.orig->flaglen & cpu_to_le32(NV_RX_AVAIL))) ||
>> ((np->get_tx.orig != np->put_tx.orig) &&
>> !(np->get_tx.orig->flaglen & cpu_to_le32(NV_TX_VALID)));
>> }
>>
>>
>>
>
^ permalink raw reply
* Re: [PATCH]: sctp: Fix skb_over_panic resulting from multiple invalid parameter errors (CVE-2010-1173)
From: Neil Horman @ 2010-04-28 18:16 UTC (permalink / raw)
To: Vlad Yasevich; +Cc: sri, linux-sctp, eteo, netdev, davem, security
In-Reply-To: <4BD875C5.9000907@hp.com>
On Wed, Apr 28, 2010 at 01:52:05PM -0400, Vlad Yasevich wrote:
>
>
> Vlad Yasevich wrote:
> >
> > Neil Horman wrote:
> >> On Wed, Apr 28, 2010 at 10:00:37AM -0400, Vlad Yasevich wrote:
> >>> I have this patch and a few others already queued.
> >>>
> >>> I was planning on sending these today for stable.
> >>>
> >>> Here is the full list of stable patches I have:
> >>>
> >>> sctp: Fix oops when sending queued ASCONF chunks
> >>> sctp: fix to calc the INIT/INIT-ACK chunk length correctly is set
> >>> sctp: per_cpu variables should be in bh_disabled section
> >>> sctp: fix potential reference of a freed pointer
> >>> sctp: avoid irq lock inversion while call sk->sk_data_ready()
> >>>
> >>> -vlad
> >>>
> >> Are you sure? this oops looks _very_ simmilar to the INIT/INIT-ACK length
> >> calculation oops described above, but is in fact different, and requires this
> >> patch, from what I can see. The right fix might be in the ASCONF chunk patch
> >> you list above, but I don't see that in your tree at the moment, so I can't be
> >> sure.
> >
> > As I said, I totally goofed when reading the description and I apologize.
> > However, I do one comment regarding the patch.
> >
> > If the bad packet is REALLY long (I mean close to 65K IP limit), then
> > we'll end up allocating a supper huge skb in this case and potentially exceed
> > the IP length limitation. Section 11.4 of rfc 4960 allows us to omit some
> > errors and limit the size of the packet.
> >
> > I would recommend limiting this to MTU worth of potentiall errors. This is
> > on top of what the INIT-ACK is going to carry, so at most we'll sent 2 MTUs
> > worth. That's still a potential by amplification attack, but it's somewhat
> > mitigated.
> >
> > Of course now we have to handle the case of checking for space before adding
> > an error cause. :)
> >
>
> Hi Neil
>
> I am also not crazy about the pre-allocation scheme. In the case where you have
> say 100 parameters that are all 'skip' parameters, you'd end up pre-allocating a
> huge buffer for absolutely nothing.
>
Would have been nice if you'd made your opinion known 4 hours ago when I was
testing version 2 of this. :)
> This is another point toward a fixed error chunk size and let parameter
> processing allocate it when it reaches a parameter that needs an error.
>
Hmm, ok, what would you say to a pathmtu sized chunk allocation in parameter
processing that drops errors beyond its capacity
Neil
>
^ permalink raw reply
* Re: [PATCH] forcedeth: Stay in NAPI as long as there's work
From: Stephen Hemminger @ 2010-04-28 18:13 UTC (permalink / raw)
To: Joe Perches; +Cc: Tom Herbert, netdev, aabdulla, davem
In-Reply-To: <1272477251.18228.36.camel@Joe-Laptop.home>
On Wed, 28 Apr 2010 10:54:11 -0700
Joe Perches <joe@perches.com> wrote:
> On Tue, 2010-04-27 at 23:36 -0700, Tom Herbert wrote:
> > Add loop in NAPI poll routine to keep processing RX and TX as long as
> > there is more work to do. This is similar to what tg3 and some other
> > drivers do.
> > Signed-off-by: Tom Herbert <therbert@google.com>
> > ---
> > diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
> > index a1c0e7b..1e4de7b 100644
> > --- a/drivers/net/forcedeth.c
> > +++ b/drivers/net/forcedeth.c
> > @@ -3736,6 +3736,23 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data)
> > }
> >
> > #ifdef CONFIG_FORCEDETH_NAPI
> > +static inline int nv_has_work(struct fe_priv *np)
> > +{
> > + if (nv_optimized(np)) {
> > + return (
> > + ((np->get_rx.ex != np->put_rx.ex) &&
> > + !(le32_to_cpu(np->get_rx.ex->flaglen) & NV_RX2_AVAIL)) ||
> > + ((np->get_tx.ex != np->put_tx.ex) &&
> > + !(le32_to_cpu(np->get_tx.ex->flaglen) & NV_TX_VALID)));
> > + } else {
> > + return (
> > + ((np->get_rx.orig != np->put_rx.orig) &&
> > + !(le32_to_cpu(np->get_rx.orig->flaglen) & NV_RX_AVAIL)) ||
> > + ((np->get_tx.orig != np->put_tx.orig) &&
> > + !(le32_to_cpu(np->get_tx.orig->flaglen) & NV_TX_VALID)));
> > + }
> > +}
Why than adding another check step, why not just keep going until
rx_done returns 0?
^ permalink raw reply
* Re: [PATCH] forcedeth: Stay in NAPI as long as there's work
From: Tom Herbert @ 2010-04-28 18:07 UTC (permalink / raw)
To: Joe Perches; +Cc: netdev, aabdulla, davem
In-Reply-To: <1272477251.18228.36.camel@Joe-Laptop.home>
>
> It might be better to test the comparisons using
> a cpu_to_le32 of the constants.
>
Yes. Probably should also be changed in nv_tx_done{_optimized} and
nv_rx_process{_optimized}
> static inline int nv_has_work(struct fe_priv *np)
> {
> if (nv_optimized(np))
> return ((np->get_rx.ex != np->put_rx.ex) &&
> !(np->get_rx.ex->flaglen & cpu_to_le32(NV_RX2_AVAIL))) ||
> ((np->get_tx.ex != np->put_tx.ex) &&
> !(np->get_tx.ex->flaglen & cpu_to_le32(NV_TX_VALID)));
>
> return ((np->get_rx.orig != np->put_rx.orig) &&
> !(np->get_rx.orig->flaglen & cpu_to_le32(NV_RX_AVAIL))) ||
> ((np->get_tx.orig != np->put_tx.orig) &&
> !(np->get_tx.orig->flaglen & cpu_to_le32(NV_TX_VALID)));
> }
>
>
>
^ permalink raw reply
* Re: Problem with "tcp: bind() fix when many ports are bound" commit
From: Grzegorz Chwesewicz @ 2010-04-28 17:59 UTC (permalink / raw)
To: David Miller; +Cc: linux-kernel, netdev, eric.dumazet
In-Reply-To: <20100428.095032.32709294.davem@davemloft.net>
David Miller pisze:
> From: Grzegorz Chwesewicz <grzegorz.chwesewicz@retis.net.pl>
> Date: Wed, 28 Apr 2010 14:33:45 +0200
>
>> Hi, I have a problem with binding to port with the latest git kernel
>> (my HEAD is at 1600f9def09de07c5dbeb539e978fa73880690dd). Please CC to
>> me as I'm not subscribed to the list.
>
> Please send networking bug reports CC:'d to netdev and the people
> who wrote and signed off on the commit you've narrowed down the
> problem to.
>
> Otherwise the appropriate people will take longer to find out about
> your bug, and therefore the bug will take longer to fix than
> necessary.
>
> Thanks.
OK, thanks, next time I'll do like you said.
--
Pozdrawiam
Grzegorz Chwesewicz
mailto:grzegorz.chwesewicz@retis.net.pl
^ permalink raw reply
* Re: 2.6.34-rc5-git7 (plus all patches) -- another suspicious rcu_dereference_check() usage.
From: Paul E. McKenney @ 2010-04-28 17:54 UTC (permalink / raw)
To: Miles Lane
Cc: Vivek Goyal, Eric Paris, Lai Jiangshan, Ingo Molnar,
Peter Zijlstra, LKML, nauman, eric.dumazet, netdev, Jens Axboe,
Gui Jianfeng, Li Zefan, Johannes Berg, shemminger
In-Reply-To: <h2ya44ae5cd1004261751waa5cb65ei3d139cbcfa2cc5cf@mail.gmail.com>
On Mon, Apr 26, 2010 at 08:51:06PM -0400, Miles Lane wrote:
> This one occurred during the wakeup from suspend to RAM.
>
> [ 984.724697] [ INFO: suspicious rcu_dereference_check() usage. ]
> [ 984.724700] ---------------------------------------------------
> [ 984.724703] include/linux/fdtable.h:88 invoked
> rcu_dereference_check() without protection!
> [ 984.724706]
> [ 984.724707] other info that might help us debug this:
> [ 984.724708]
> [ 984.724711]
> [ 984.724711] rcu_scheduler_active = 1, debug_locks = 1
> [ 984.724714] no locks held by dbus-daemon/4680.
> [ 984.724717]
> [ 984.724717] stack backtrace:
> [ 984.724721] Pid: 4680, comm: dbus-daemon Not tainted 2.6.34-rc5-git7 #33
> [ 984.724724] Call Trace:
> [ 984.724734] [<ffffffff81074556>] lockdep_rcu_dereference+0x9d/0xa6
> [ 984.724740] [<ffffffff810fc785>] fcheck_files+0xb1/0xc9
> [ 984.724745] [<ffffffff810fc7f5>] fget_light+0x35/0xab
> [ 984.724751] [<ffffffff81433e1b>] ? sock_poll_wait+0x13/0x18
> [ 984.724755] [<ffffffff81433e39>] ? unix_poll+0x19/0x95
> [ 984.724762] [<ffffffff8110aa95>] do_sys_poll+0x1ff/0x3e5
> [ 984.724766] [<ffffffff8110a19e>] ? __pollwait+0x0/0xc7
> [ 984.724771] [<ffffffff8110a265>] ? pollwake+0x0/0x4f
> [ 984.724776] [<ffffffff8110a265>] ? pollwake+0x0/0x4f
> [ 984.724780] [<ffffffff8110a265>] ? pollwake+0x0/0x4f
> [ 984.724784] [<ffffffff8110a265>] ? pollwake+0x0/0x4f
> [ 984.724788] [<ffffffff8110a265>] ? pollwake+0x0/0x4f
> [ 984.724793] [<ffffffff8110a265>] ? pollwake+0x0/0x4f
> [ 984.724797] [<ffffffff8110a265>] ? pollwake+0x0/0x4f
> [ 984.724802] [<ffffffff8110a265>] ? pollwake+0x0/0x4f
> [ 984.724806] [<ffffffff8110a265>] ? pollwake+0x0/0x4f
> [ 984.724812] [<ffffffff8110ae0f>] sys_poll+0x50/0xbb
> [ 984.724818] [<ffffffff81009d82>] system_call_fastpath+0x16/0x1b
Hmmm... I am not convinced that this is a false positive. Couldn't
there be a multi-threaded process where one thread is invoking poll()
on a UNIX socket just as another thread is calling close() on it?
The current fcheck_files() logic requires that the caller either (1) be in
an RCU read-side critical section, (2) hold ->files_lock, or (3) passing
in a files_struct with ->count equal to 1 (initialization or cleanup).
So I don't feel comfortable just slapping an RCU read-side critical
section around this one, at least not unless someone who understands
the locking says that doing so is OK.
Thanx, Paul
> #
> # Automatically generated make config: don't edit
> # Linux kernel version: 2.6.34-rc5-git7
> # Mon Apr 26 19:18:59 2010
> #
> CONFIG_64BIT=y
> # CONFIG_X86_32 is not set
> CONFIG_X86_64=y
> CONFIG_X86=y
> CONFIG_OUTPUT_FORMAT="elf64-x86-64"
> CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
> CONFIG_GENERIC_TIME=y
> CONFIG_GENERIC_CMOS_UPDATE=y
> CONFIG_CLOCKSOURCE_WATCHDOG=y
> CONFIG_GENERIC_CLOCKEVENTS=y
> CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
> CONFIG_LOCKDEP_SUPPORT=y
> CONFIG_STACKTRACE_SUPPORT=y
> CONFIG_HAVE_LATENCYTOP_SUPPORT=y
> CONFIG_MMU=y
> CONFIG_ZONE_DMA=y
> CONFIG_NEED_DMA_MAP_STATE=y
> CONFIG_GENERIC_ISA_DMA=y
> CONFIG_GENERIC_IOMAP=y
> CONFIG_GENERIC_BUG=y
> CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
> CONFIG_GENERIC_HWEIGHT=y
> CONFIG_GENERIC_GPIO=y
> CONFIG_ARCH_MAY_HAVE_PC_FDC=y
> # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
> CONFIG_RWSEM_XCHGADD_ALGORITHM=y
> CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
> CONFIG_GENERIC_CALIBRATE_DELAY=y
> CONFIG_GENERIC_TIME_VSYSCALL=y
> CONFIG_ARCH_HAS_CPU_RELAX=y
> CONFIG_ARCH_HAS_DEFAULT_IDLE=y
> CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
> CONFIG_HAVE_SETUP_PER_CPU_AREA=y
> CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
> CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
> CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y
> CONFIG_ARCH_HIBERNATION_POSSIBLE=y
> CONFIG_ARCH_SUSPEND_POSSIBLE=y
> CONFIG_ZONE_DMA32=y
> CONFIG_ARCH_POPULATES_NODE_MAP=y
> CONFIG_AUDIT_ARCH=y
> CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
> CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
> CONFIG_HAVE_EARLY_RES=y
> CONFIG_HAVE_INTEL_TXT=y
> CONFIG_GENERIC_HARDIRQS=y
> CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
> CONFIG_GENERIC_IRQ_PROBE=y
> CONFIG_GENERIC_PENDING_IRQ=y
> CONFIG_USE_GENERIC_SMP_HELPERS=y
> CONFIG_X86_64_SMP=y
> CONFIG_X86_HT=y
> CONFIG_X86_TRAMPOLINE=y
> # CONFIG_KTIME_SCALAR is not set
> CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
> CONFIG_CONSTRUCTORS=y
>
> #
> # General setup
> #
> CONFIG_EXPERIMENTAL=y
> CONFIG_LOCK_KERNEL=y
> CONFIG_INIT_ENV_ARG_LIMIT=32
> CONFIG_LOCALVERSION=""
> # CONFIG_LOCALVERSION_AUTO is not set
> CONFIG_HAVE_KERNEL_GZIP=y
> CONFIG_HAVE_KERNEL_BZIP2=y
> CONFIG_HAVE_KERNEL_LZMA=y
> CONFIG_HAVE_KERNEL_LZO=y
> # CONFIG_KERNEL_GZIP is not set
> # CONFIG_KERNEL_BZIP2 is not set
> CONFIG_KERNEL_LZMA=y
> # CONFIG_KERNEL_LZO is not set
> CONFIG_SWAP=y
> CONFIG_SYSVIPC=y
> CONFIG_SYSVIPC_SYSCTL=y
> CONFIG_POSIX_MQUEUE=y
> CONFIG_POSIX_MQUEUE_SYSCTL=y
> CONFIG_BSD_PROCESS_ACCT=y
> CONFIG_BSD_PROCESS_ACCT_V3=y
> CONFIG_TASKSTATS=y
> CONFIG_TASK_DELAY_ACCT=y
> CONFIG_TASK_XACCT=y
> CONFIG_TASK_IO_ACCOUNTING=y
> CONFIG_AUDIT=y
> CONFIG_AUDITSYSCALL=y
> CONFIG_AUDIT_TREE=y
>
> #
> # RCU Subsystem
> #
> # CONFIG_TREE_RCU is not set
> CONFIG_TREE_PREEMPT_RCU=y
> # CONFIG_TINY_RCU is not set
> CONFIG_RCU_TRACE=y
> CONFIG_RCU_FANOUT=64
> CONFIG_RCU_FANOUT_EXACT=y
> CONFIG_TREE_RCU_TRACE=y
> # CONFIG_IKCONFIG is not set
> CONFIG_LOG_BUF_SHIFT=18
> CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
> CONFIG_CGROUPS=y
> # CONFIG_CGROUP_DEBUG is not set
> CONFIG_CGROUP_NS=y
> CONFIG_CGROUP_FREEZER=y
> CONFIG_CGROUP_DEVICE=y
> CONFIG_CPUSETS=y
> CONFIG_PROC_PID_CPUSET=y
> CONFIG_CGROUP_CPUACCT=y
> CONFIG_RESOURCE_COUNTERS=y
> # CONFIG_CGROUP_MEM_RES_CTLR is not set
> CONFIG_CGROUP_SCHED=y
> CONFIG_FAIR_GROUP_SCHED=y
> CONFIG_RT_GROUP_SCHED=y
> # CONFIG_SYSFS_DEPRECATED_V2 is not set
> CONFIG_RELAY=y
> CONFIG_NAMESPACES=y
> CONFIG_UTS_NS=y
> CONFIG_IPC_NS=y
> CONFIG_USER_NS=y
> CONFIG_PID_NS=y
> CONFIG_NET_NS=y
> CONFIG_BLK_DEV_INITRD=y
> CONFIG_INITRAMFS_SOURCE=""
> CONFIG_RD_GZIP=y
> CONFIG_RD_BZIP2=y
> CONFIG_RD_LZMA=y
> CONFIG_RD_LZO=y
> CONFIG_CC_OPTIMIZE_FOR_SIZE=y
> CONFIG_SYSCTL=y
> CONFIG_ANON_INODES=y
> # CONFIG_EMBEDDED is not set
> CONFIG_UID16=y
> CONFIG_SYSCTL_SYSCALL=y
> CONFIG_KALLSYMS=y
> CONFIG_KALLSYMS_ALL=y
> CONFIG_KALLSYMS_EXTRA_PASS=y
> CONFIG_HOTPLUG=y
> CONFIG_PRINTK=y
> CONFIG_BUG=y
> CONFIG_ELF_CORE=y
> CONFIG_PCSPKR_PLATFORM=y
> CONFIG_BASE_FULL=y
> CONFIG_FUTEX=y
> CONFIG_EPOLL=y
> CONFIG_SIGNALFD=y
> CONFIG_TIMERFD=y
> CONFIG_EVENTFD=y
> CONFIG_SHMEM=y
> CONFIG_AIO=y
> CONFIG_HAVE_PERF_EVENTS=y
>
> #
> # Kernel Performance Events And Counters
> #
> CONFIG_PERF_EVENTS=y
> # CONFIG_PERF_COUNTERS is not set
> # CONFIG_DEBUG_PERF_USE_VMALLOC is not set
> CONFIG_VM_EVENT_COUNTERS=y
> CONFIG_PCI_QUIRKS=y
> CONFIG_SLUB_DEBUG=y
> # CONFIG_COMPAT_BRK is not set
> # CONFIG_SLAB is not set
> CONFIG_SLUB=y
> # CONFIG_SLOB is not set
> CONFIG_PROFILING=y
> CONFIG_TRACEPOINTS=y
> CONFIG_OPROFILE=m
> CONFIG_OPROFILE_EVENT_MULTIPLEX=y
> CONFIG_HAVE_OPROFILE=y
> CONFIG_KPROBES=y
> CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
> CONFIG_KRETPROBES=y
> CONFIG_HAVE_IOREMAP_PROT=y
> CONFIG_HAVE_KPROBES=y
> CONFIG_HAVE_KRETPROBES=y
> CONFIG_HAVE_OPTPROBES=y
> CONFIG_HAVE_ARCH_TRACEHOOK=y
> CONFIG_HAVE_DMA_ATTRS=y
> CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
> CONFIG_HAVE_DMA_API_DEBUG=y
> CONFIG_HAVE_HW_BREAKPOINT=y
> CONFIG_HAVE_USER_RETURN_NOTIFIER=y
>
> #
> # GCOV-based kernel profiling
> #
> # CONFIG_GCOV_KERNEL is not set
> CONFIG_SLOW_WORK=y
> # CONFIG_SLOW_WORK_DEBUG is not set
> # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
> CONFIG_SLABINFO=y
> CONFIG_RT_MUTEXES=y
> CONFIG_BASE_SMALL=0
> CONFIG_MODULES=y
> CONFIG_MODULE_FORCE_LOAD=y
> CONFIG_MODULE_UNLOAD=y
> CONFIG_MODULE_FORCE_UNLOAD=y
> CONFIG_MODVERSIONS=y
> # CONFIG_MODULE_SRCVERSION_ALL is not set
> CONFIG_STOP_MACHINE=y
> CONFIG_BLOCK=y
> CONFIG_BLK_DEV_BSG=y
> # CONFIG_BLK_DEV_INTEGRITY is not set
> CONFIG_BLK_CGROUP=y
> CONFIG_DEBUG_BLK_CGROUP=y
> CONFIG_BLOCK_COMPAT=y
>
> #
> # IO Schedulers
> #
> CONFIG_IOSCHED_NOOP=y
> CONFIG_IOSCHED_DEADLINE=m
> CONFIG_IOSCHED_CFQ=y
> CONFIG_CFQ_GROUP_IOSCHED=y
> CONFIG_DEBUG_CFQ_IOSCHED=y
> # CONFIG_DEFAULT_DEADLINE is not set
> CONFIG_DEFAULT_CFQ=y
> # CONFIG_DEFAULT_NOOP is not set
> CONFIG_DEFAULT_IOSCHED="cfq"
> # CONFIG_INLINE_SPIN_TRYLOCK is not set
> # CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
> # CONFIG_INLINE_SPIN_LOCK is not set
> # CONFIG_INLINE_SPIN_LOCK_BH is not set
> # CONFIG_INLINE_SPIN_LOCK_IRQ is not set
> # CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
> # CONFIG_INLINE_SPIN_UNLOCK is not set
> # CONFIG_INLINE_SPIN_UNLOCK_BH is not set
> # CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
> # CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
> # CONFIG_INLINE_READ_TRYLOCK is not set
> # CONFIG_INLINE_READ_LOCK is not set
> # CONFIG_INLINE_READ_LOCK_BH is not set
> # CONFIG_INLINE_READ_LOCK_IRQ is not set
> # CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
> # CONFIG_INLINE_READ_UNLOCK is not set
> # CONFIG_INLINE_READ_UNLOCK_BH is not set
> # CONFIG_INLINE_READ_UNLOCK_IRQ is not set
> # CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
> # CONFIG_INLINE_WRITE_TRYLOCK is not set
> # CONFIG_INLINE_WRITE_LOCK is not set
> # CONFIG_INLINE_WRITE_LOCK_BH is not set
> # CONFIG_INLINE_WRITE_LOCK_IRQ is not set
> # CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
> # CONFIG_INLINE_WRITE_UNLOCK is not set
> # CONFIG_INLINE_WRITE_UNLOCK_BH is not set
> # CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
> # CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
> # CONFIG_MUTEX_SPIN_ON_OWNER is not set
> CONFIG_FREEZER=y
>
> #
> # Processor type and features
> #
> CONFIG_TICK_ONESHOT=y
> CONFIG_NO_HZ=y
> CONFIG_HIGH_RES_TIMERS=y
> CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
> CONFIG_SMP=y
> CONFIG_X86_X2APIC=y
> CONFIG_SPARSE_IRQ=y
> CONFIG_X86_MPPARSE=y
> CONFIG_X86_EXTENDED_PLATFORM=y
> CONFIG_X86_VSMP=y
> CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
> CONFIG_SCHED_OMIT_FRAME_POINTER=y
> CONFIG_PARAVIRT_GUEST=y
> CONFIG_XEN=y
> CONFIG_XEN_MAX_DOMAIN_MEMORY=32
> CONFIG_XEN_SAVE_RESTORE=y
> # CONFIG_XEN_DEBUG_FS is not set
> CONFIG_KVM_CLOCK=y
> CONFIG_KVM_GUEST=y
> CONFIG_PARAVIRT=y
> CONFIG_PARAVIRT_SPINLOCKS=y
> CONFIG_PARAVIRT_CLOCK=y
> CONFIG_PARAVIRT_DEBUG=y
> CONFIG_NO_BOOTMEM=y
> # CONFIG_MEMTEST is not set
> # CONFIG_M386 is not set
> # CONFIG_M486 is not set
> # CONFIG_M586 is not set
> # CONFIG_M586TSC is not set
> # CONFIG_M586MMX is not set
> # CONFIG_M686 is not set
> # CONFIG_MPENTIUMII is not set
> # CONFIG_MPENTIUMIII is not set
> # CONFIG_MPENTIUMM is not set
> # CONFIG_MPENTIUM4 is not set
> # CONFIG_MK6 is not set
> # CONFIG_MK7 is not set
> # CONFIG_MK8 is not set
> # CONFIG_MCRUSOE is not set
> # CONFIG_MEFFICEON is not set
> # CONFIG_MWINCHIPC6 is not set
> # CONFIG_MWINCHIP3D is not set
> # CONFIG_MGEODEGX1 is not set
> # CONFIG_MGEODE_LX is not set
> # CONFIG_MCYRIXIII is not set
> # CONFIG_MVIAC3_2 is not set
> # CONFIG_MVIAC7 is not set
> # CONFIG_MPSC is not set
> # CONFIG_MCORE2 is not set
> # CONFIG_MATOM is not set
> CONFIG_GENERIC_CPU=y
> CONFIG_X86_CPU=y
> CONFIG_X86_INTERNODE_CACHE_SHIFT=12
> CONFIG_X86_CMPXCHG=y
> CONFIG_X86_L1_CACHE_SHIFT=6
> CONFIG_X86_XADD=y
> CONFIG_X86_WP_WORKS_OK=y
> CONFIG_X86_TSC=y
> CONFIG_X86_CMPXCHG64=y
> CONFIG_X86_CMOV=y
> CONFIG_X86_MINIMUM_CPU_FAMILY=64
> CONFIG_X86_DEBUGCTLMSR=y
> CONFIG_CPU_SUP_INTEL=y
> CONFIG_CPU_SUP_AMD=y
> CONFIG_CPU_SUP_CENTAUR=y
> # CONFIG_X86_DS is not set
> CONFIG_HPET_TIMER=y
> CONFIG_HPET_EMULATE_RTC=y
> CONFIG_DMI=y
> CONFIG_GART_IOMMU=y
> # CONFIG_CALGARY_IOMMU is not set
> # CONFIG_AMD_IOMMU is not set
> CONFIG_SWIOTLB=y
> CONFIG_IOMMU_HELPER=y
> CONFIG_IOMMU_API=y
> # CONFIG_MAXSMP is not set
> CONFIG_NR_CPUS=2
> CONFIG_SCHED_SMT=y
> CONFIG_SCHED_MC=y
> # CONFIG_PREEMPT_NONE is not set
> # CONFIG_PREEMPT_VOLUNTARY is not set
> CONFIG_PREEMPT=y
> CONFIG_X86_LOCAL_APIC=y
> CONFIG_X86_IO_APIC=y
> CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
> CONFIG_X86_MCE=y
> CONFIG_X86_MCE_INTEL=y
> # CONFIG_X86_MCE_AMD is not set
> CONFIG_X86_MCE_THRESHOLD=y
> # CONFIG_X86_MCE_INJECT is not set
> CONFIG_X86_THERMAL_VECTOR=y
> # CONFIG_I8K is not set
> CONFIG_MICROCODE=y
> CONFIG_MICROCODE_INTEL=y
> # CONFIG_MICROCODE_AMD is not set
> CONFIG_MICROCODE_OLD_INTERFACE=y
> CONFIG_X86_MSR=y
> CONFIG_X86_CPUID=y
> CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
> CONFIG_DIRECT_GBPAGES=y
> # CONFIG_NUMA is not set
> CONFIG_ARCH_PROC_KCORE_TEXT=y
> CONFIG_ARCH_SPARSEMEM_DEFAULT=y
> CONFIG_ARCH_SPARSEMEM_ENABLE=y
> CONFIG_ARCH_SELECT_MEMORY_MODEL=y
> CONFIG_ARCH_MEMORY_PROBE=y
> CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
> CONFIG_SELECT_MEMORY_MODEL=y
> # CONFIG_FLATMEM_MANUAL is not set
> # CONFIG_DISCONTIGMEM_MANUAL is not set
> CONFIG_SPARSEMEM_MANUAL=y
> CONFIG_SPARSEMEM=y
> CONFIG_HAVE_MEMORY_PRESENT=y
> CONFIG_SPARSEMEM_EXTREME=y
> CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
> CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
> CONFIG_SPARSEMEM_VMEMMAP=y
> CONFIG_MEMORY_HOTPLUG=y
> CONFIG_MEMORY_HOTPLUG_SPARSE=y
> CONFIG_MEMORY_HOTREMOVE=y
> CONFIG_PAGEFLAGS_EXTENDED=y
> CONFIG_SPLIT_PTLOCK_CPUS=999999
> CONFIG_MIGRATION=y
> CONFIG_PHYS_ADDR_T_64BIT=y
> CONFIG_ZONE_DMA_FLAG=1
> CONFIG_BOUNCE=y
> CONFIG_VIRT_TO_BUS=y
> # CONFIG_KSM is not set
> CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
> CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
> CONFIG_MEMORY_FAILURE=y
> # CONFIG_HWPOISON_INJECT is not set
> CONFIG_X86_CHECK_BIOS_CORRUPTION=y
> CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
> CONFIG_X86_RESERVE_LOW_64K=y
> CONFIG_MTRR=y
> CONFIG_MTRR_SANITIZER=y
> CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1
> CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
> CONFIG_X86_PAT=y
> CONFIG_ARCH_USES_PG_UNCACHED=y
> CONFIG_EFI=y
> CONFIG_SECCOMP=y
> CONFIG_CC_STACKPROTECTOR=y
> # CONFIG_HZ_100 is not set
> # CONFIG_HZ_250 is not set
> CONFIG_HZ_300=y
> # CONFIG_HZ_1000 is not set
> CONFIG_HZ=300
> CONFIG_SCHED_HRTICK=y
> CONFIG_KEXEC=y
> CONFIG_CRASH_DUMP=y
> CONFIG_KEXEC_JUMP=y
> CONFIG_PHYSICAL_START=0x1000000
> CONFIG_RELOCATABLE=y
> CONFIG_PHYSICAL_ALIGN=0x1000000
> CONFIG_HOTPLUG_CPU=y
> CONFIG_COMPAT_VDSO=y
> # CONFIG_CMDLINE_BOOL is not set
> CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
> CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
>
> #
> # Power management and ACPI options
> #
> CONFIG_ARCH_HIBERNATION_HEADER=y
> CONFIG_PM=y
> CONFIG_PM_DEBUG=y
> # CONFIG_PM_ADVANCED_DEBUG is not set
> # CONFIG_PM_VERBOSE is not set
> CONFIG_CAN_PM_TRACE=y
> CONFIG_PM_TRACE=y
> CONFIG_PM_TRACE_RTC=y
> CONFIG_PM_SLEEP_SMP=y
> CONFIG_PM_SLEEP=y
> CONFIG_SUSPEND=y
> CONFIG_SUSPEND_FREEZER=y
> CONFIG_HIBERNATION_NVS=y
> CONFIG_HIBERNATION=y
> CONFIG_PM_STD_PARTITION=""
> CONFIG_PM_RUNTIME=y
> CONFIG_PM_OPS=y
> CONFIG_ACPI=y
> CONFIG_ACPI_SLEEP=y
> # CONFIG_ACPI_PROCFS is not set
> # CONFIG_ACPI_PROCFS_POWER is not set
> CONFIG_ACPI_POWER_METER=m
> CONFIG_ACPI_SYSFS_POWER=y
> # CONFIG_ACPI_PROC_EVENT is not set
> CONFIG_ACPI_AC=m
> CONFIG_ACPI_BATTERY=m
> CONFIG_ACPI_BUTTON=y
> CONFIG_ACPI_VIDEO=y
> CONFIG_ACPI_FAN=m
> # CONFIG_ACPI_DOCK is not set
> CONFIG_ACPI_PROCESSOR=y
> CONFIG_ACPI_HOTPLUG_CPU=y
> CONFIG_ACPI_PROCESSOR_AGGREGATOR=y
> CONFIG_ACPI_THERMAL=y
> # CONFIG_ACPI_CUSTOM_DSDT is not set
> CONFIG_ACPI_BLACKLIST_YEAR=0
> # CONFIG_ACPI_DEBUG is not set
> # CONFIG_ACPI_PCI_SLOT is not set
> CONFIG_X86_PM_TIMER=y
> CONFIG_ACPI_CONTAINER=y
> CONFIG_ACPI_HOTPLUG_MEMORY=m
> CONFIG_ACPI_SBS=m
> # CONFIG_SFI is not set
>
> #
> # CPU Frequency scaling
> #
> CONFIG_CPU_FREQ=y
> CONFIG_CPU_FREQ_TABLE=y
> CONFIG_CPU_FREQ_DEBUG=y
> # CONFIG_CPU_FREQ_STAT is not set
> # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
> # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
> CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
> # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
> # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
> CONFIG_CPU_FREQ_GOV_PERFORMANCE=m
> CONFIG_CPU_FREQ_GOV_POWERSAVE=m
> CONFIG_CPU_FREQ_GOV_USERSPACE=y
> CONFIG_CPU_FREQ_GOV_ONDEMAND=m
> CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
>
> #
> # CPUFreq processor drivers
> #
> # CONFIG_X86_PCC_CPUFREQ is not set
> CONFIG_X86_ACPI_CPUFREQ=y
> # CONFIG_X86_POWERNOW_K8 is not set
> # CONFIG_X86_SPEEDSTEP_CENTRINO is not set
> # CONFIG_X86_P4_CLOCKMOD is not set
>
> #
> # shared options
> #
> # CONFIG_X86_SPEEDSTEP_LIB is not set
> CONFIG_CPU_IDLE=y
> CONFIG_CPU_IDLE_GOV_LADDER=y
> CONFIG_CPU_IDLE_GOV_MENU=y
>
> #
> # Memory power savings
> #
> CONFIG_I7300_IDLE_IOAT_CHANNEL=y
> CONFIG_I7300_IDLE=m
>
> #
> # Bus options (PCI etc.)
> #
> CONFIG_PCI=y
> CONFIG_PCI_DIRECT=y
> CONFIG_PCI_MMCONFIG=y
> CONFIG_PCI_DOMAINS=y
> CONFIG_DMAR=y
> CONFIG_DMAR_DEFAULT_ON=y
> CONFIG_DMAR_FLOPPY_WA=y
> CONFIG_INTR_REMAP=y
> CONFIG_PCIEPORTBUS=y
> CONFIG_HOTPLUG_PCI_PCIE=m
> CONFIG_PCIEAER=y
> # CONFIG_PCIE_ECRC is not set
> # CONFIG_PCIEAER_INJECT is not set
> # CONFIG_PCIEASPM is not set
> CONFIG_PCIE_PME=y
> CONFIG_ARCH_SUPPORTS_MSI=y
> CONFIG_PCI_MSI=y
> # CONFIG_PCI_DEBUG is not set
> # CONFIG_PCI_STUB is not set
> CONFIG_HT_IRQ=y
> # CONFIG_PCI_IOV is not set
> CONFIG_PCI_IOAPIC=y
> CONFIG_ISA_DMA_API=y
> CONFIG_K8_NB=y
> # CONFIG_PCCARD is not set
> CONFIG_HOTPLUG_PCI=m
> CONFIG_HOTPLUG_PCI_FAKE=m
> CONFIG_HOTPLUG_PCI_ACPI=m
> CONFIG_HOTPLUG_PCI_ACPI_IBM=m
> CONFIG_HOTPLUG_PCI_CPCI=y
> CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
> CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
> CONFIG_HOTPLUG_PCI_SHPC=m
>
> #
> # Executable file formats / Emulations
> #
> CONFIG_BINFMT_ELF=y
> CONFIG_COMPAT_BINFMT_ELF=y
> CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
> # CONFIG_HAVE_AOUT is not set
> CONFIG_BINFMT_MISC=y
> CONFIG_IA32_EMULATION=y
> # CONFIG_IA32_AOUT is not set
> CONFIG_COMPAT=y
> CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
> CONFIG_SYSVIPC_COMPAT=y
> CONFIG_NET=y
>
> #
> # Networking options
> #
> CONFIG_PACKET=y
> CONFIG_UNIX=y
> CONFIG_XFRM=y
> CONFIG_XFRM_USER=m
> # CONFIG_XFRM_SUB_POLICY is not set
> CONFIG_XFRM_MIGRATE=y
> # CONFIG_XFRM_STATISTICS is not set
> CONFIG_XFRM_IPCOMP=m
> CONFIG_NET_KEY=m
> CONFIG_NET_KEY_MIGRATE=y
> CONFIG_INET=y
> CONFIG_IP_MULTICAST=y
> CONFIG_IP_ADVANCED_ROUTER=y
> CONFIG_ASK_IP_FIB_HASH=y
> # CONFIG_IP_FIB_TRIE is not set
> CONFIG_IP_FIB_HASH=y
> CONFIG_IP_MULTIPLE_TABLES=y
> CONFIG_IP_ROUTE_MULTIPATH=y
> CONFIG_IP_ROUTE_VERBOSE=y
> CONFIG_IP_PNP=y
> CONFIG_IP_PNP_DHCP=y
> CONFIG_IP_PNP_BOOTP=y
> CONFIG_IP_PNP_RARP=y
> CONFIG_NET_IPIP=m
> CONFIG_NET_IPGRE=m
> CONFIG_NET_IPGRE_BROADCAST=y
> CONFIG_IP_MROUTE=y
> CONFIG_IP_PIMSM_V1=y
> CONFIG_IP_PIMSM_V2=y
> # CONFIG_ARPD is not set
> CONFIG_SYN_COOKIES=y
> CONFIG_INET_AH=m
> CONFIG_INET_ESP=m
> CONFIG_INET_IPCOMP=m
> CONFIG_INET_XFRM_TUNNEL=m
> CONFIG_INET_TUNNEL=m
> CONFIG_INET_XFRM_MODE_TRANSPORT=m
> CONFIG_INET_XFRM_MODE_TUNNEL=m
> CONFIG_INET_XFRM_MODE_BEET=m
> CONFIG_INET_LRO=y
> # CONFIG_INET_DIAG is not set
> CONFIG_TCP_CONG_ADVANCED=y
> # CONFIG_TCP_CONG_BIC is not set
> CONFIG_TCP_CONG_CUBIC=y
> # CONFIG_TCP_CONG_WESTWOOD is not set
> # CONFIG_TCP_CONG_HTCP is not set
> # CONFIG_TCP_CONG_HSTCP is not set
> # CONFIG_TCP_CONG_HYBLA is not set
> # CONFIG_TCP_CONG_VEGAS is not set
> # CONFIG_TCP_CONG_SCALABLE is not set
> # CONFIG_TCP_CONG_LP is not set
> # CONFIG_TCP_CONG_VENO is not set
> # CONFIG_TCP_CONG_YEAH is not set
> # CONFIG_TCP_CONG_ILLINOIS is not set
> # CONFIG_DEFAULT_BIC is not set
> CONFIG_DEFAULT_CUBIC=y
> # CONFIG_DEFAULT_HTCP is not set
> # CONFIG_DEFAULT_VEGAS is not set
> # CONFIG_DEFAULT_WESTWOOD is not set
> # CONFIG_DEFAULT_RENO is not set
> CONFIG_DEFAULT_TCP_CONG="cubic"
> CONFIG_TCP_MD5SIG=y
> CONFIG_IPV6=m
> # CONFIG_IPV6_PRIVACY is not set
> # CONFIG_IPV6_ROUTER_PREF is not set
> # CONFIG_IPV6_OPTIMISTIC_DAD is not set
> CONFIG_INET6_AH=m
> CONFIG_INET6_ESP=m
> CONFIG_INET6_IPCOMP=m
> # CONFIG_IPV6_MIP6 is not set
> CONFIG_INET6_XFRM_TUNNEL=m
> CONFIG_INET6_TUNNEL=m
> CONFIG_INET6_XFRM_MODE_TRANSPORT=m
> CONFIG_INET6_XFRM_MODE_TUNNEL=m
> CONFIG_INET6_XFRM_MODE_BEET=m
> # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
> CONFIG_IPV6_SIT=m
> # CONFIG_IPV6_SIT_6RD is not set
> CONFIG_IPV6_NDISC_NODETYPE=y
> CONFIG_IPV6_TUNNEL=m
> # CONFIG_IPV6_MULTIPLE_TABLES is not set
> CONFIG_IPV6_MROUTE=y
> CONFIG_IPV6_PIMSM_V2=y
> CONFIG_NETLABEL=y
> CONFIG_NETWORK_SECMARK=y
> CONFIG_NETFILTER=y
> # CONFIG_NETFILTER_DEBUG is not set
> # CONFIG_NETFILTER_ADVANCED is not set
>
> #
> # Core Netfilter Configuration
> #
> CONFIG_NETFILTER_NETLINK=m
> CONFIG_NETFILTER_NETLINK_LOG=m
> CONFIG_NF_CONNTRACK=m
> CONFIG_NF_CONNTRACK_SECMARK=y
> CONFIG_NF_CONNTRACK_FTP=m
> CONFIG_NF_CONNTRACK_IRC=m
> CONFIG_NF_CONNTRACK_SIP=m
> CONFIG_NF_CT_NETLINK=m
> CONFIG_NETFILTER_XTABLES=y
> CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
> CONFIG_NETFILTER_XT_TARGET_MARK=m
> CONFIG_NETFILTER_XT_TARGET_NFLOG=m
> CONFIG_NETFILTER_XT_TARGET_SECMARK=m
> CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
> CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
> CONFIG_NETFILTER_XT_MATCH_MARK=m
> CONFIG_NETFILTER_XT_MATCH_POLICY=m
> CONFIG_NETFILTER_XT_MATCH_STATE=m
> # CONFIG_IP_VS is not set
>
> #
> # IP: Netfilter Configuration
> #
> CONFIG_NF_DEFRAG_IPV4=m
> CONFIG_NF_CONNTRACK_IPV4=m
> CONFIG_NF_CONNTRACK_PROC_COMPAT=y
> CONFIG_IP_NF_IPTABLES=m
> CONFIG_IP_NF_FILTER=m
> CONFIG_IP_NF_TARGET_REJECT=m
> CONFIG_IP_NF_TARGET_LOG=m
> CONFIG_IP_NF_TARGET_ULOG=m
> CONFIG_NF_NAT=m
> CONFIG_NF_NAT_NEEDED=y
> CONFIG_IP_NF_TARGET_MASQUERADE=m
> CONFIG_NF_NAT_FTP=m
> CONFIG_NF_NAT_IRC=m
> # CONFIG_NF_NAT_TFTP is not set
> # CONFIG_NF_NAT_AMANDA is not set
> # CONFIG_NF_NAT_PPTP is not set
> # CONFIG_NF_NAT_H323 is not set
> CONFIG_NF_NAT_SIP=m
> CONFIG_IP_NF_MANGLE=m
>
> #
> # IPv6: Netfilter Configuration
> #
> CONFIG_NF_CONNTRACK_IPV6=m
> CONFIG_IP6_NF_IPTABLES=m
> CONFIG_IP6_NF_MATCH_IPV6HEADER=m
> CONFIG_IP6_NF_TARGET_LOG=m
> CONFIG_IP6_NF_FILTER=m
> CONFIG_IP6_NF_TARGET_REJECT=m
> CONFIG_IP6_NF_MANGLE=m
> # CONFIG_IP_DCCP is not set
> CONFIG_IP_SCTP=m
> # CONFIG_SCTP_DBG_MSG is not set
> # CONFIG_SCTP_DBG_OBJCNT is not set
> # CONFIG_SCTP_HMAC_NONE is not set
> # CONFIG_SCTP_HMAC_SHA1 is not set
> CONFIG_SCTP_HMAC_MD5=y
> # CONFIG_RDS is not set
> # CONFIG_TIPC is not set
> # CONFIG_ATM is not set
> # CONFIG_BRIDGE is not set
> # CONFIG_NET_DSA is not set
> # CONFIG_VLAN_8021Q is not set
> # CONFIG_DECNET is not set
> CONFIG_LLC=m
> CONFIG_LLC2=m
> # CONFIG_IPX is not set
> CONFIG_ATALK=m
> CONFIG_DEV_APPLETALK=m
> CONFIG_IPDDP=m
> CONFIG_IPDDP_ENCAP=y
> CONFIG_IPDDP_DECAP=y
> # CONFIG_X25 is not set
> # CONFIG_LAPB is not set
> # CONFIG_ECONET is not set
> # CONFIG_WAN_ROUTER is not set
> # CONFIG_PHONET is not set
> # CONFIG_IEEE802154 is not set
> # CONFIG_NET_SCHED is not set
> # CONFIG_DCB is not set
>
> #
> # Network testing
> #
> # CONFIG_NET_PKTGEN is not set
> # CONFIG_NET_TCPPROBE is not set
> # CONFIG_NET_DROP_MONITOR is not set
> # CONFIG_HAMRADIO is not set
> CONFIG_CAN=m
> CONFIG_CAN_RAW=m
> CONFIG_CAN_BCM=m
>
> #
> # CAN Device Drivers
> #
> CONFIG_CAN_VCAN=m
> CONFIG_CAN_DEV=m
> CONFIG_CAN_CALC_BITTIMING=y
> CONFIG_CAN_SJA1000=m
> CONFIG_CAN_SJA1000_PLATFORM=m
> CONFIG_CAN_EMS_PCI=m
> CONFIG_CAN_KVASER_PCI=m
> CONFIG_CAN_PLX_PCI=m
>
> #
> # CAN USB interfaces
> #
> CONFIG_CAN_EMS_USB=m
> CONFIG_CAN_DEBUG_DEVICES=y
> CONFIG_IRDA=m
>
> #
> # IrDA protocols
> #
> CONFIG_IRLAN=m
> CONFIG_IRNET=m
> CONFIG_IRCOMM=m
> CONFIG_IRDA_ULTRA=y
>
> #
> # IrDA options
> #
> CONFIG_IRDA_CACHE_LAST_LSAP=y
> CONFIG_IRDA_FAST_RR=y
> CONFIG_IRDA_DEBUG=y
>
> #
> # Infrared-port device drivers
> #
>
> #
> # SIR device drivers
> #
> CONFIG_IRTTY_SIR=m
>
> #
> # Dongle support
> #
> CONFIG_DONGLE=y
> CONFIG_ESI_DONGLE=m
> CONFIG_ACTISYS_DONGLE=m
> CONFIG_TEKRAM_DONGLE=m
> CONFIG_TOIM3232_DONGLE=m
> CONFIG_LITELINK_DONGLE=m
> CONFIG_MA600_DONGLE=m
> CONFIG_GIRBIL_DONGLE=m
> CONFIG_MCP2120_DONGLE=m
> CONFIG_OLD_BELKIN_DONGLE=m
> CONFIG_ACT200L_DONGLE=m
> CONFIG_KINGSUN_DONGLE=m
> CONFIG_KSDAZZLE_DONGLE=m
> CONFIG_KS959_DONGLE=m
>
> #
> # FIR device drivers
> #
> CONFIG_USB_IRDA=m
> CONFIG_SIGMATEL_FIR=m
> CONFIG_NSC_FIR=m
> CONFIG_WINBOND_FIR=m
> CONFIG_SMC_IRCC_FIR=m
> CONFIG_ALI_FIR=m
> CONFIG_VLSI_FIR=m
> CONFIG_VIA_FIR=m
> CONFIG_MCS_FIR=m
> CONFIG_BT=m
> CONFIG_BT_L2CAP=m
> CONFIG_BT_SCO=m
> CONFIG_BT_RFCOMM=m
> CONFIG_BT_RFCOMM_TTY=y
> CONFIG_BT_BNEP=m
> CONFIG_BT_BNEP_MC_FILTER=y
> CONFIG_BT_BNEP_PROTO_FILTER=y
> CONFIG_BT_HIDP=m
>
> #
> # Bluetooth device drivers
> #
> CONFIG_BT_HCIBTUSB=m
> CONFIG_BT_HCIBTSDIO=m
> CONFIG_BT_HCIUART=m
> CONFIG_BT_HCIUART_H4=y
> CONFIG_BT_HCIUART_BCSP=y
> CONFIG_BT_HCIUART_LL=y
> CONFIG_BT_HCIBCM203X=m
> CONFIG_BT_HCIBPA10X=m
> CONFIG_BT_HCIBFUSB=m
> CONFIG_BT_HCIVHCI=m
> CONFIG_BT_MRVL=m
> CONFIG_BT_MRVL_SDIO=m
> CONFIG_BT_ATH3K=m
> CONFIG_AF_RXRPC=m
> CONFIG_AF_RXRPC_DEBUG=y
> CONFIG_RXKAD=m
> CONFIG_FIB_RULES=y
> CONFIG_WIRELESS=y
> CONFIG_WEXT_CORE=y
> CONFIG_WEXT_PROC=y
> CONFIG_CFG80211=m
> # CONFIG_NL80211_TESTMODE is not set
> # CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
> # CONFIG_CFG80211_REG_DEBUG is not set
> # CONFIG_CFG80211_DEFAULT_PS is not set
> # CONFIG_CFG80211_DEBUGFS is not set
> # CONFIG_CFG80211_INTERNAL_REGDB is not set
> CONFIG_CFG80211_WEXT=y
> CONFIG_WIRELESS_EXT_SYSFS=y
> CONFIG_LIB80211=m
> # CONFIG_LIB80211_DEBUG is not set
> CONFIG_MAC80211=m
> CONFIG_MAC80211_RC_MINSTREL=y
> # CONFIG_MAC80211_RC_DEFAULT_PID is not set
> CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
> CONFIG_MAC80211_RC_DEFAULT="minstrel"
> CONFIG_MAC80211_MESH=y
> CONFIG_MAC80211_LEDS=y
> # CONFIG_MAC80211_DEBUGFS is not set
> # CONFIG_MAC80211_DEBUG_MENU is not set
> CONFIG_WIMAX=m
> CONFIG_WIMAX_DEBUG_LEVEL=8
> CONFIG_RFKILL=m
> CONFIG_RFKILL_LEDS=y
> CONFIG_RFKILL_INPUT=y
> CONFIG_NET_9P=m
> CONFIG_NET_9P_DEBUG=y
>
> #
> # Device Drivers
> #
>
> #
> # Generic Driver Options
> #
> CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
> # CONFIG_DEVTMPFS is not set
> CONFIG_STANDALONE=y
> CONFIG_PREVENT_FIRMWARE_BUILD=y
> CONFIG_FW_LOADER=y
> CONFIG_FIRMWARE_IN_KERNEL=y
> CONFIG_EXTRA_FIRMWARE=""
> # CONFIG_DEBUG_DRIVER is not set
> CONFIG_DEBUG_DEVRES=y
> CONFIG_SYS_HYPERVISOR=y
> CONFIG_CONNECTOR=m
> CONFIG_MTD=y
> CONFIG_MTD_DEBUG=y
> CONFIG_MTD_DEBUG_VERBOSE=0
> CONFIG_MTD_TESTS=m
> CONFIG_MTD_CONCAT=m
> CONFIG_MTD_PARTITIONS=y
> CONFIG_MTD_REDBOOT_PARTS=y
> CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
> # CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
> # CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
> # CONFIG_MTD_CMDLINE_PARTS is not set
> CONFIG_MTD_AR7_PARTS=m
>
> #
> # User Modules And Translation Layers
> #
> CONFIG_MTD_CHAR=y
> CONFIG_HAVE_MTD_OTP=y
> CONFIG_MTD_BLKDEVS=y
> CONFIG_MTD_BLOCK=y
> CONFIG_FTL=y
> CONFIG_NFTL=y
> # CONFIG_NFTL_RW is not set
> CONFIG_INFTL=m
> CONFIG_RFD_FTL=y
> CONFIG_SSFDC=m
> CONFIG_MTD_OOPS=y
>
> #
> # RAM/ROM/Flash chip drivers
> #
> CONFIG_MTD_CFI=y
> CONFIG_MTD_JEDECPROBE=y
> CONFIG_MTD_GEN_PROBE=y
> # CONFIG_MTD_CFI_ADV_OPTIONS is not set
> CONFIG_MTD_MAP_BANK_WIDTH_1=y
> CONFIG_MTD_MAP_BANK_WIDTH_2=y
> CONFIG_MTD_MAP_BANK_WIDTH_4=y
> # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
> # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
> # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
> CONFIG_MTD_CFI_I1=y
> CONFIG_MTD_CFI_I2=y
> # CONFIG_MTD_CFI_I4 is not set
> # CONFIG_MTD_CFI_I8 is not set
> CONFIG_MTD_CFI_INTELEXT=y
> CONFIG_MTD_CFI_AMDSTD=y
> CONFIG_MTD_CFI_STAA=y
> CONFIG_MTD_CFI_UTIL=y
> CONFIG_MTD_RAM=y
> CONFIG_MTD_ROM=y
> CONFIG_MTD_ABSENT=y
>
> #
> # Mapping drivers for chip access
> #
> # CONFIG_MTD_COMPLEX_MAPPINGS is not set
> CONFIG_MTD_PHYSMAP=y
> # CONFIG_MTD_PHYSMAP_COMPAT is not set
> CONFIG_MTD_SC520CDP=m
> CONFIG_MTD_NETSC520=m
> CONFIG_MTD_TS5500=m
> CONFIG_MTD_AMD76XROM=m
> CONFIG_MTD_ICHXROM=y
> CONFIG_MTD_ESB2ROM=y
> CONFIG_MTD_CK804XROM=m
> CONFIG_MTD_SCB2_FLASH=y
> CONFIG_MTD_NETtel=m
> CONFIG_MTD_L440GX=y
> CONFIG_MTD_INTEL_VR_NOR=y
> CONFIG_MTD_PLATRAM=y
>
> #
> # Self-contained MTD device drivers
> #
> CONFIG_MTD_PMC551=m
> # CONFIG_MTD_PMC551_BUGFIX is not set
> # CONFIG_MTD_PMC551_DEBUG is not set
> CONFIG_MTD_SLRAM=y
> CONFIG_MTD_PHRAM=y
> CONFIG_MTD_MTDRAM=m
> CONFIG_MTDRAM_TOTAL_SIZE=4096
> CONFIG_MTDRAM_ERASE_SIZE=128
> CONFIG_MTD_BLOCK2MTD=y
>
> #
> # Disk-On-Chip Device Drivers
> #
> CONFIG_MTD_DOC2000=m
> CONFIG_MTD_DOC2001=m
> CONFIG_MTD_DOC2001PLUS=m
> CONFIG_MTD_DOCPROBE=m
> CONFIG_MTD_DOCECC=m
> # CONFIG_MTD_DOCPROBE_ADVANCED is not set
> CONFIG_MTD_DOCPROBE_ADDRESS=0
> CONFIG_MTD_NAND=y
> # CONFIG_MTD_NAND_VERIFY_WRITE is not set
> # CONFIG_MTD_NAND_ECC_SMC is not set
> # CONFIG_MTD_NAND_MUSEUM_IDS is not set
> CONFIG_MTD_NAND_IDS=y
> CONFIG_MTD_NAND_DISKONCHIP=m
> # CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
> CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
> # CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
> CONFIG_MTD_NAND_CAFE=m
> CONFIG_MTD_NAND_NANDSIM=m
> CONFIG_MTD_NAND_PLATFORM=m
> CONFIG_MTD_ALAUDA=m
> CONFIG_MTD_ONENAND=y
> # CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
> CONFIG_MTD_ONENAND_GENERIC=y
> CONFIG_MTD_ONENAND_OTP=y
> CONFIG_MTD_ONENAND_2X_PROGRAM=y
> CONFIG_MTD_ONENAND_SIM=m
>
> #
> # LPDDR flash memory drivers
> #
> CONFIG_MTD_LPDDR=y
> CONFIG_MTD_QINFO_PROBE=y
>
> #
> # UBI - Unsorted block images
> #
> CONFIG_MTD_UBI=y
> CONFIG_MTD_UBI_WL_THRESHOLD=4096
> CONFIG_MTD_UBI_BEB_RESERVE=1
> CONFIG_MTD_UBI_GLUEBI=y
>
> #
> # UBI debugging options
> #
> CONFIG_MTD_UBI_DEBUG=y
> # CONFIG_MTD_UBI_DEBUG_MSG is not set
> # CONFIG_MTD_UBI_DEBUG_PARANOID is not set
> # CONFIG_MTD_UBI_DEBUG_DISABLE_BGT is not set
> # CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS is not set
> # CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES is not set
> # CONFIG_MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES is not set
>
> #
> # Additional UBI debugging messages
> #
> # CONFIG_MTD_UBI_DEBUG_MSG_BLD is not set
> # CONFIG_MTD_UBI_DEBUG_MSG_EBA is not set
> # CONFIG_MTD_UBI_DEBUG_MSG_WL is not set
> # CONFIG_MTD_UBI_DEBUG_MSG_IO is not set
> CONFIG_PARPORT=m
> CONFIG_PARPORT_PC=m
> CONFIG_PARPORT_SERIAL=m
> CONFIG_PARPORT_PC_FIFO=y
> CONFIG_PARPORT_PC_SUPERIO=y
> # CONFIG_PARPORT_GSC is not set
> CONFIG_PARPORT_AX88796=m
> CONFIG_PARPORT_1284=y
> CONFIG_PARPORT_NOT_PC=y
> CONFIG_PNP=y
> CONFIG_PNP_DEBUG_MESSAGES=y
>
> #
> # Protocols
> #
> CONFIG_PNPACPI=y
> CONFIG_BLK_DEV=y
> CONFIG_BLK_DEV_FD=m
> CONFIG_PARIDE=m
>
> #
> # Parallel IDE high-level drivers
> #
> CONFIG_PARIDE_PD=m
> CONFIG_PARIDE_PCD=m
> CONFIG_PARIDE_PF=m
> # CONFIG_PARIDE_PT is not set
> CONFIG_PARIDE_PG=m
>
> #
> # Parallel IDE protocol modules
> #
> # CONFIG_PARIDE_ATEN is not set
> # CONFIG_PARIDE_BPCK is not set
> # CONFIG_PARIDE_COMM is not set
> # CONFIG_PARIDE_DSTR is not set
> # CONFIG_PARIDE_FIT2 is not set
> # CONFIG_PARIDE_FIT3 is not set
> # CONFIG_PARIDE_EPAT is not set
> # CONFIG_PARIDE_EPIA is not set
> # CONFIG_PARIDE_FRIQ is not set
> # CONFIG_PARIDE_FRPW is not set
> # CONFIG_PARIDE_KBIC is not set
> # CONFIG_PARIDE_KTTI is not set
> # CONFIG_PARIDE_ON20 is not set
> # CONFIG_PARIDE_ON26 is not set
> # CONFIG_BLK_CPQ_DA is not set
> # CONFIG_BLK_CPQ_CISS_DA is not set
> # CONFIG_BLK_DEV_DAC960 is not set
> # CONFIG_BLK_DEV_UMEM is not set
> # CONFIG_BLK_DEV_COW_COMMON is not set
> CONFIG_BLK_DEV_LOOP=y
> CONFIG_BLK_DEV_CRYPTOLOOP=y
> # CONFIG_BLK_DEV_DRBD is not set
> # CONFIG_BLK_DEV_NBD is not set
> # CONFIG_BLK_DEV_SX8 is not set
> # CONFIG_BLK_DEV_UB is not set
> # CONFIG_BLK_DEV_RAM is not set
> # CONFIG_CDROM_PKTCDVD is not set
> # CONFIG_ATA_OVER_ETH is not set
> CONFIG_XEN_BLKDEV_FRONTEND=y
> # CONFIG_BLK_DEV_HD is not set
> CONFIG_MISC_DEVICES=y
> # CONFIG_AD525X_DPOT is not set
> # CONFIG_IBM_ASM is not set
> # CONFIG_PHANTOM is not set
> # CONFIG_SGI_IOC4 is not set
> CONFIG_TIFM_CORE=y
> CONFIG_TIFM_7XX1=y
> # CONFIG_ICS932S401 is not set
> # CONFIG_ENCLOSURE_SERVICES is not set
> # CONFIG_CS5535_MFGPT is not set
> # CONFIG_HP_ILO is not set
> # CONFIG_ISL29003 is not set
> # CONFIG_SENSORS_TSL2550 is not set
> # CONFIG_DS1682 is not set
> # CONFIG_VMWARE_BALLOON is not set
> # CONFIG_C2PORT is not set
>
> #
> # EEPROM support
> #
> CONFIG_EEPROM_AT24=m
> CONFIG_EEPROM_LEGACY=m
> CONFIG_EEPROM_MAX6875=m
> CONFIG_EEPROM_93CX6=m
> CONFIG_CB710_CORE=m
> # CONFIG_CB710_DEBUG is not set
> CONFIG_CB710_DEBUG_ASSUMPTIONS=y
> # CONFIG_IWMC3200TOP is not set
> CONFIG_HAVE_IDE=y
> # CONFIG_IDE is not set
>
> #
> # SCSI device support
> #
> CONFIG_SCSI_MOD=y
> CONFIG_RAID_ATTRS=m
> CONFIG_SCSI=y
> CONFIG_SCSI_DMA=y
> CONFIG_SCSI_TGT=m
> # CONFIG_SCSI_NETLINK is not set
> CONFIG_SCSI_PROC_FS=y
>
> #
> # SCSI support type (disk, tape, CD-ROM)
> #
> CONFIG_BLK_DEV_SD=m
> # CONFIG_CHR_DEV_ST is not set
> # CONFIG_CHR_DEV_OSST is not set
> CONFIG_BLK_DEV_SR=m
> CONFIG_BLK_DEV_SR_VENDOR=y
> CONFIG_CHR_DEV_SG=m
> # CONFIG_CHR_DEV_SCH is not set
> # CONFIG_SCSI_MULTI_LUN is not set
> CONFIG_SCSI_CONSTANTS=y
> # CONFIG_SCSI_LOGGING is not set
> # CONFIG_SCSI_SCAN_ASYNC is not set
> CONFIG_SCSI_WAIT_SCAN=m
>
> #
> # SCSI Transports
> #
> CONFIG_SCSI_SPI_ATTRS=m
> # CONFIG_SCSI_FC_ATTRS is not set
> # CONFIG_SCSI_ISCSI_ATTRS is not set
> # CONFIG_SCSI_SAS_ATTRS is not set
> # CONFIG_SCSI_SAS_LIBSAS is not set
> # CONFIG_SCSI_SRP_ATTRS is not set
> # CONFIG_SCSI_LOWLEVEL is not set
> # CONFIG_SCSI_DH is not set
> # CONFIG_SCSI_OSD_INITIATOR is not set
> CONFIG_ATA=y
> # CONFIG_ATA_NONSTANDARD is not set
> CONFIG_ATA_VERBOSE_ERROR=y
> CONFIG_ATA_ACPI=y
> CONFIG_SATA_PMP=y
> CONFIG_SATA_AHCI=y
> # CONFIG_SATA_SIL24 is not set
> CONFIG_ATA_SFF=y
> # CONFIG_SATA_SVW is not set
> CONFIG_ATA_PIIX=y
> # CONFIG_SATA_MV is not set
> # CONFIG_SATA_NV is not set
> # CONFIG_PDC_ADMA is not set
> # CONFIG_SATA_QSTOR is not set
> # CONFIG_SATA_PROMISE is not set
> # CONFIG_SATA_SX4 is not set
> # CONFIG_SATA_SIL is not set
> # CONFIG_SATA_SIS is not set
> # CONFIG_SATA_ULI is not set
> # CONFIG_SATA_VIA is not set
> # CONFIG_SATA_VITESSE is not set
> # CONFIG_SATA_INIC162X is not set
> # CONFIG_PATA_ACPI is not set
> # CONFIG_PATA_ALI is not set
> # CONFIG_PATA_AMD is not set
> # CONFIG_PATA_ARTOP is not set
> # CONFIG_PATA_ATP867X is not set
> # CONFIG_PATA_ATIIXP is not set
> # CONFIG_PATA_CMD640_PCI is not set
> # CONFIG_PATA_CMD64X is not set
> # CONFIG_PATA_CS5520 is not set
> # CONFIG_PATA_CS5530 is not set
> # CONFIG_PATA_CYPRESS is not set
> # CONFIG_PATA_EFAR is not set
> # CONFIG_ATA_GENERIC is not set
> # CONFIG_PATA_HPT366 is not set
> # CONFIG_PATA_HPT37X is not set
> # CONFIG_PATA_HPT3X2N is not set
> # CONFIG_PATA_HPT3X3 is not set
> # CONFIG_PATA_IT821X is not set
> # CONFIG_PATA_IT8213 is not set
> # CONFIG_PATA_JMICRON is not set
> # CONFIG_PATA_LEGACY is not set
> # CONFIG_PATA_TRIFLEX is not set
> # CONFIG_PATA_MARVELL is not set
> # CONFIG_PATA_MPIIX is not set
> # CONFIG_PATA_OLDPIIX is not set
> # CONFIG_PATA_NETCELL is not set
> # CONFIG_PATA_NINJA32 is not set
> # CONFIG_PATA_NS87410 is not set
> # CONFIG_PATA_NS87415 is not set
> # CONFIG_PATA_OPTI is not set
> # CONFIG_PATA_OPTIDMA is not set
> # CONFIG_PATA_PDC2027X is not set
> # CONFIG_PATA_PDC_OLD is not set
> # CONFIG_PATA_RADISYS is not set
> # CONFIG_PATA_RDC is not set
> # CONFIG_PATA_RZ1000 is not set
> # CONFIG_PATA_SC1200 is not set
> # CONFIG_PATA_SERVERWORKS is not set
> # CONFIG_PATA_SIL680 is not set
> # CONFIG_PATA_SIS is not set
> # CONFIG_PATA_TOSHIBA is not set
> # CONFIG_PATA_VIA is not set
> # CONFIG_PATA_WINBOND is not set
> CONFIG_PATA_SCH=y
> CONFIG_MD=y
> CONFIG_BLK_DEV_MD=y
> CONFIG_MD_AUTODETECT=y
> # CONFIG_MD_LINEAR is not set
> CONFIG_MD_RAID0=y
> # CONFIG_MD_RAID1 is not set
> # CONFIG_MD_RAID10 is not set
> # CONFIG_MD_RAID456 is not set
> CONFIG_MD_MULTIPATH=y
> # CONFIG_MD_FAULTY is not set
> CONFIG_BLK_DEV_DM=y
> # CONFIG_DM_DEBUG is not set
> # CONFIG_DM_CRYPT is not set
> # CONFIG_DM_SNAPSHOT is not set
> CONFIG_DM_MIRROR=y
> # CONFIG_DM_LOG_USERSPACE is not set
> CONFIG_DM_ZERO=y
> # CONFIG_DM_MULTIPATH is not set
> # CONFIG_DM_DELAY is not set
> # CONFIG_DM_UEVENT is not set
> # CONFIG_FUSION is not set
>
> #
> # IEEE 1394 (FireWire) support
> #
>
> #
> # You can enable one or both FireWire driver stacks.
> #
>
> #
> # The newer stack is recommended.
> #
> # CONFIG_FIREWIRE is not set
> # CONFIG_IEEE1394 is not set
> CONFIG_I2O=m
> CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
> CONFIG_I2O_EXT_ADAPTEC=y
> CONFIG_I2O_EXT_ADAPTEC_DMA64=y
> CONFIG_I2O_CONFIG=m
> CONFIG_I2O_CONFIG_OLD_IOCTL=y
> CONFIG_I2O_BUS=m
> CONFIG_I2O_BLOCK=m
> CONFIG_I2O_SCSI=m
> CONFIG_I2O_PROC=m
> # CONFIG_MACINTOSH_DRIVERS is not set
> CONFIG_NETDEVICES=y
> # CONFIG_DUMMY is not set
> # CONFIG_BONDING is not set
> # CONFIG_MACVLAN is not set
> # CONFIG_EQUALIZER is not set
> # CONFIG_TUN is not set
> # CONFIG_VETH is not set
> # CONFIG_NET_SB1000 is not set
> # CONFIG_ARCNET is not set
> # CONFIG_NET_ETHERNET is not set
> CONFIG_MII=m
> CONFIG_NETDEV_1000=y
> # CONFIG_ACENIC is not set
> # CONFIG_DL2K is not set
> # CONFIG_E1000 is not set
> # CONFIG_E1000E is not set
> # CONFIG_IP1000 is not set
> # CONFIG_IGB is not set
> # CONFIG_IGBVF is not set
> # CONFIG_NS83820 is not set
> # CONFIG_HAMACHI is not set
> # CONFIG_YELLOWFIN is not set
> # CONFIG_R8169 is not set
> # CONFIG_SIS190 is not set
> # CONFIG_SKGE is not set
> # CONFIG_SKY2 is not set
> # CONFIG_VIA_VELOCITY is not set
> # CONFIG_TIGON3 is not set
> # CONFIG_BNX2 is not set
> # CONFIG_CNIC is not set
> # CONFIG_QLA3XXX is not set
> # CONFIG_ATL1 is not set
> # CONFIG_ATL1E is not set
> CONFIG_ATL1C=m
> # CONFIG_JME is not set
> # CONFIG_NETDEV_10000 is not set
> # CONFIG_TR is not set
> CONFIG_WLAN=y
> # CONFIG_LIBERTAS_THINFIRM is not set
> # CONFIG_AIRO is not set
> # CONFIG_ATMEL is not set
> # CONFIG_AT76C50X_USB is not set
> # CONFIG_PRISM54 is not set
> # CONFIG_USB_ZD1201 is not set
> # CONFIG_USB_NET_RNDIS_WLAN is not set
> # CONFIG_RTL8180 is not set
> # CONFIG_RTL8187 is not set
> # CONFIG_ADM8211 is not set
> # CONFIG_MAC80211_HWSIM is not set
> # CONFIG_MWL8K is not set
> # CONFIG_ATH_COMMON is not set
> # CONFIG_B43 is not set
> # CONFIG_B43LEGACY is not set
> # CONFIG_HOSTAP is not set
> # CONFIG_IPW2100 is not set
> # CONFIG_IPW2200 is not set
> CONFIG_IWLWIFI=m
> # CONFIG_IWLWIFI_DEBUG is not set
> # CONFIG_IWLWIFI_DEVICE_TRACING is not set
> CONFIG_IWLAGN=m
> # CONFIG_IWL4965 is not set
> CONFIG_IWL5000=y
> # CONFIG_IWL3945 is not set
> # CONFIG_IWM is not set
> # CONFIG_LIBERTAS is not set
> # CONFIG_HERMES is not set
> # CONFIG_P54_COMMON is not set
> # CONFIG_RT2X00 is not set
> # CONFIG_WL12XX is not set
> # CONFIG_ZD1211RW is not set
>
> #
> # WiMAX Wireless Broadband devices
> #
> # CONFIG_WIMAX_I2400M_USB is not set
> # CONFIG_WIMAX_I2400M_SDIO is not set
>
> #
> # USB Network Adapters
> #
> CONFIG_USB_CATC=m
> CONFIG_USB_KAWETH=m
> CONFIG_USB_PEGASUS=m
> CONFIG_USB_RTL8150=m
> CONFIG_USB_USBNET=m
> CONFIG_USB_NET_AX8817X=m
> CONFIG_USB_NET_CDCETHER=m
> CONFIG_USB_NET_CDC_EEM=m
> CONFIG_USB_NET_DM9601=m
> CONFIG_USB_NET_SMSC75XX=m
> CONFIG_USB_NET_SMSC95XX=m
> CONFIG_USB_NET_GL620A=m
> CONFIG_USB_NET_NET1080=m
> CONFIG_USB_NET_PLUSB=m
> CONFIG_USB_NET_MCS7830=m
> CONFIG_USB_NET_RNDIS_HOST=m
> CONFIG_USB_NET_CDC_SUBSET=m
> CONFIG_USB_ALI_M5632=y
> CONFIG_USB_AN2720=y
> CONFIG_USB_BELKIN=y
> CONFIG_USB_ARMLINUX=y
> CONFIG_USB_EPSON2888=y
> CONFIG_USB_KC2190=y
> CONFIG_USB_NET_ZAURUS=m
> CONFIG_USB_HSO=m
> CONFIG_USB_NET_INT51X1=m
> CONFIG_USB_IPHETH=m
> # CONFIG_WAN is not set
> CONFIG_XEN_NETDEV_FRONTEND=y
> # CONFIG_FDDI is not set
> # CONFIG_HIPPI is not set
> # CONFIG_PLIP is not set
> CONFIG_PPP=m
> # CONFIG_PPP_MULTILINK is not set
> # CONFIG_PPP_FILTER is not set
> # CONFIG_PPP_ASYNC is not set
> CONFIG_PPP_SYNC_TTY=m
> CONFIG_PPP_DEFLATE=m
> CONFIG_PPP_BSDCOMP=m
> CONFIG_PPP_MPPE=m
> CONFIG_PPPOE=m
> # CONFIG_PPPOL2TP is not set
> # CONFIG_SLIP is not set
> CONFIG_SLHC=m
> # CONFIG_NET_FC is not set
> CONFIG_NETCONSOLE=y
> # CONFIG_NETCONSOLE_DYNAMIC is not set
> CONFIG_NETPOLL=y
> # CONFIG_NETPOLL_TRAP is not set
> CONFIG_NET_POLL_CONTROLLER=y
> # CONFIG_VMXNET3 is not set
> # CONFIG_ISDN is not set
> # CONFIG_PHONE is not set
>
> #
> # Input device support
> #
> CONFIG_INPUT=y
> CONFIG_INPUT_FF_MEMLESS=m
> CONFIG_INPUT_POLLDEV=y
> CONFIG_INPUT_SPARSEKMAP=m
>
> #
> # Userland interfaces
> #
> CONFIG_INPUT_MOUSEDEV=y
> # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
> CONFIG_INPUT_MOUSEDEV_SCREEN_X=1366
> CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
> # CONFIG_INPUT_JOYDEV is not set
> CONFIG_INPUT_EVDEV=y
> # CONFIG_INPUT_EVBUG is not set
> CONFIG_XEN_KBDDEV_FRONTEND=y
>
> #
> # Input Device Drivers
> #
> CONFIG_INPUT_KEYBOARD=y
> # CONFIG_KEYBOARD_ADP5588 is not set
> CONFIG_KEYBOARD_ATKBD=y
> # CONFIG_QT2160 is not set
> # CONFIG_KEYBOARD_LKKBD is not set
> # CONFIG_KEYBOARD_GPIO is not set
> # CONFIG_KEYBOARD_MATRIX is not set
> # CONFIG_KEYBOARD_LM8323 is not set
> # CONFIG_KEYBOARD_MAX7359 is not set
> # CONFIG_KEYBOARD_NEWTON is not set
> # CONFIG_KEYBOARD_OPENCORES is not set
> # CONFIG_KEYBOARD_STOWAWAY is not set
> # CONFIG_KEYBOARD_SUNKBD is not set
> # CONFIG_KEYBOARD_XTKBD is not set
> CONFIG_INPUT_MOUSE=y
> CONFIG_MOUSE_PS2=y
> CONFIG_MOUSE_PS2_ALPS=y
> CONFIG_MOUSE_PS2_LOGIPS2PP=y
> CONFIG_MOUSE_PS2_SYNAPTICS=y
> CONFIG_MOUSE_PS2_LIFEBOOK=y
> CONFIG_MOUSE_PS2_TRACKPOINT=y
> CONFIG_MOUSE_PS2_ELANTECH=y
> # CONFIG_MOUSE_PS2_SENTELIC is not set
> # CONFIG_MOUSE_PS2_TOUCHKIT is not set
> # CONFIG_MOUSE_SERIAL is not set
> # CONFIG_MOUSE_APPLETOUCH is not set
> # CONFIG_MOUSE_BCM5974 is not set
> # CONFIG_MOUSE_VSXXXAA is not set
> CONFIG_MOUSE_GPIO=y
> CONFIG_MOUSE_SYNAPTICS_I2C=y
> # CONFIG_INPUT_JOYSTICK is not set
> CONFIG_INPUT_TABLET=y
> CONFIG_TABLET_USB_ACECAD=m
> CONFIG_TABLET_USB_AIPTEK=m
> CONFIG_TABLET_USB_GTCO=m
> CONFIG_TABLET_USB_KBTAB=m
> CONFIG_TABLET_USB_WACOM=m
> # CONFIG_INPUT_TOUCHSCREEN is not set
> CONFIG_INPUT_MISC=y
> # CONFIG_INPUT_PCSPKR is not set
> # CONFIG_INPUT_APANEL is not set
> # CONFIG_INPUT_ATLAS_BTNS is not set
> # CONFIG_INPUT_ATI_REMOTE is not set
> # CONFIG_INPUT_ATI_REMOTE2 is not set
> # CONFIG_INPUT_KEYSPAN_REMOTE is not set
> # CONFIG_INPUT_POWERMATE is not set
> # CONFIG_INPUT_YEALINK is not set
> # CONFIG_INPUT_CM109 is not set
> # CONFIG_INPUT_UINPUT is not set
> # CONFIG_INPUT_WINBOND_CIR is not set
> # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
>
> #
> # Hardware I/O ports
> #
> CONFIG_SERIO=y
> CONFIG_SERIO_I8042=y
> CONFIG_SERIO_SERPORT=y
> # CONFIG_SERIO_CT82C710 is not set
> # CONFIG_SERIO_PARKBD is not set
> # CONFIG_SERIO_PCIPS2 is not set
> CONFIG_SERIO_LIBPS2=y
> # CONFIG_SERIO_RAW is not set
> # CONFIG_SERIO_ALTERA_PS2 is not set
> # CONFIG_GAMEPORT is not set
>
> #
> # Character devices
> #
> CONFIG_VT=y
> CONFIG_CONSOLE_TRANSLATIONS=y
> CONFIG_VT_CONSOLE=y
> CONFIG_HW_CONSOLE=y
> CONFIG_VT_HW_CONSOLE_BINDING=y
> CONFIG_DEVKMEM=y
> # CONFIG_SERIAL_NONSTANDARD is not set
> # CONFIG_NOZOMI is not set
>
> #
> # Serial drivers
> #
> CONFIG_SERIAL_8250=y
> CONFIG_SERIAL_8250_CONSOLE=y
> CONFIG_FIX_EARLYCON_MEM=y
> CONFIG_SERIAL_8250_PCI=y
> CONFIG_SERIAL_8250_PNP=y
> CONFIG_SERIAL_8250_NR_UARTS=32
> CONFIG_SERIAL_8250_RUNTIME_UARTS=4
> # CONFIG_SERIAL_8250_EXTENDED is not set
>
> #
> # Non-8250 serial port support
> #
> # CONFIG_SERIAL_UARTLITE is not set
> CONFIG_SERIAL_CORE=y
> CONFIG_SERIAL_CORE_CONSOLE=y
> # CONFIG_SERIAL_JSM is not set
> CONFIG_SERIAL_TIMBERDALE=m
> CONFIG_UNIX98_PTYS=y
> # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
> # CONFIG_LEGACY_PTYS is not set
> CONFIG_PRINTER=m
> # CONFIG_LP_CONSOLE is not set
> CONFIG_PPDEV=m
> CONFIG_HVC_DRIVER=y
> CONFIG_HVC_IRQ=y
> CONFIG_HVC_XEN=y
> CONFIG_IPMI_HANDLER=m
> # CONFIG_IPMI_PANIC_EVENT is not set
> CONFIG_IPMI_DEVICE_INTERFACE=m
> CONFIG_IPMI_SI=m
> CONFIG_IPMI_WATCHDOG=m
> CONFIG_IPMI_POWEROFF=m
> CONFIG_HW_RANDOM=m
> CONFIG_HW_RANDOM_TIMERIOMEM=m
> CONFIG_HW_RANDOM_INTEL=m
> # CONFIG_HW_RANDOM_AMD is not set
> CONFIG_HW_RANDOM_VIA=m
> CONFIG_NVRAM=m
> CONFIG_R3964=m
> CONFIG_APPLICOM=m
> CONFIG_MWAVE=m
> CONFIG_PC8736x_GPIO=m
> CONFIG_NSC_GPIO=m
> CONFIG_RAW_DRIVER=m
> CONFIG_MAX_RAW_DEVS=256
> CONFIG_HPET=y
> # CONFIG_HPET_MMAP is not set
> CONFIG_HANGCHECK_TIMER=m
> CONFIG_TCG_TPM=m
> # CONFIG_TCG_TIS is not set
> # CONFIG_TCG_NSC is not set
> # CONFIG_TCG_ATMEL is not set
> # CONFIG_TCG_INFINEON is not set
> CONFIG_TELCLOCK=m
> CONFIG_DEVPORT=y
> CONFIG_I2C=y
> CONFIG_I2C_BOARDINFO=y
> CONFIG_I2C_COMPAT=y
> CONFIG_I2C_CHARDEV=m
> CONFIG_I2C_HELPER_AUTO=y
> CONFIG_I2C_SMBUS=m
> CONFIG_I2C_ALGOBIT=y
>
> #
> # I2C Hardware Bus support
> #
>
> #
> # PC SMBus host controller drivers
> #
> # CONFIG_I2C_ALI1535 is not set
> # CONFIG_I2C_ALI1563 is not set
> # CONFIG_I2C_ALI15X3 is not set
> # CONFIG_I2C_AMD756 is not set
> # CONFIG_I2C_AMD8111 is not set
> CONFIG_I2C_I801=m
> # CONFIG_I2C_ISCH is not set
> CONFIG_I2C_PIIX4=m
> CONFIG_I2C_NFORCE2=m
> # CONFIG_I2C_NFORCE2_S4985 is not set
> # CONFIG_I2C_SIS5595 is not set
> # CONFIG_I2C_SIS630 is not set
> # CONFIG_I2C_SIS96X is not set
> # CONFIG_I2C_VIA is not set
> # CONFIG_I2C_VIAPRO is not set
>
> #
> # ACPI drivers
> #
> # CONFIG_I2C_SCMI is not set
>
> #
> # I2C system bus drivers (mostly embedded / system-on-chip)
> #
> CONFIG_I2C_GPIO=m
> # CONFIG_I2C_OCORES is not set
> # CONFIG_I2C_SIMTEC is not set
> # CONFIG_I2C_XILINX is not set
>
> #
> # External I2C/SMBus adapter drivers
> #
> CONFIG_I2C_PARPORT=m
> # CONFIG_I2C_PARPORT_LIGHT is not set
> # CONFIG_I2C_TAOS_EVM is not set
> # CONFIG_I2C_TINY_USB is not set
>
> #
> # Other I2C/SMBus bus drivers
> #
> # CONFIG_I2C_PCA_PLATFORM is not set
> # CONFIG_I2C_STUB is not set
> # CONFIG_I2C_DEBUG_CORE is not set
> # CONFIG_I2C_DEBUG_ALGO is not set
> # CONFIG_I2C_DEBUG_BUS is not set
> # CONFIG_SPI is not set
>
> #
> # PPS support
> #
> # CONFIG_PPS is not set
> CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
> CONFIG_GPIOLIB=y
> # CONFIG_DEBUG_GPIO is not set
> # CONFIG_GPIO_SYSFS is not set
> CONFIG_GPIO_MAX730X=m
>
> #
> # Memory mapped GPIO expanders:
> #
> CONFIG_GPIO_IT8761E=m
> CONFIG_GPIO_SCH=m
>
> #
> # I2C GPIO expanders:
> #
> CONFIG_GPIO_MAX7300=m
> CONFIG_GPIO_MAX732X=m
> CONFIG_GPIO_PCA953X=m
> CONFIG_GPIO_PCF857X=m
> CONFIG_GPIO_ADP5588=m
>
> #
> # PCI GPIO expanders:
> #
> # CONFIG_GPIO_CS5535 is not set
> # CONFIG_GPIO_LANGWELL is not set
> # CONFIG_GPIO_TIMBERDALE is not set
>
> #
> # SPI GPIO expanders:
> #
>
> #
> # AC97 GPIO expanders:
> #
> CONFIG_W1=m
> CONFIG_W1_CON=y
>
> #
> # 1-wire Bus Masters
> #
> # CONFIG_W1_MASTER_MATROX is not set
> # CONFIG_W1_MASTER_DS2490 is not set
> # CONFIG_W1_MASTER_DS2482 is not set
> # CONFIG_W1_MASTER_GPIO is not set
>
> #
> # 1-wire Slaves
> #
> CONFIG_W1_SLAVE_THERM=m
> CONFIG_W1_SLAVE_SMEM=m
> CONFIG_W1_SLAVE_DS2431=m
> CONFIG_W1_SLAVE_DS2433=m
> # CONFIG_W1_SLAVE_DS2433_CRC is not set
> CONFIG_W1_SLAVE_DS2760=m
> # CONFIG_W1_SLAVE_BQ27000 is not set
> CONFIG_POWER_SUPPLY=y
> # CONFIG_POWER_SUPPLY_DEBUG is not set
> # CONFIG_PDA_POWER is not set
> # CONFIG_BATTERY_DS2760 is not set
> # CONFIG_BATTERY_DS2782 is not set
> # CONFIG_BATTERY_BQ27x00 is not set
> # CONFIG_BATTERY_MAX17040 is not set
> CONFIG_HWMON=m
> CONFIG_HWMON_VID=m
> # CONFIG_HWMON_DEBUG_CHIP is not set
>
> #
> # Native drivers
> #
> # CONFIG_SENSORS_ABITUGURU is not set
> # CONFIG_SENSORS_ABITUGURU3 is not set
> # CONFIG_SENSORS_AD7414 is not set
> # CONFIG_SENSORS_AD7418 is not set
> # CONFIG_SENSORS_ADM1021 is not set
> # CONFIG_SENSORS_ADM1025 is not set
> # CONFIG_SENSORS_ADM1026 is not set
> # CONFIG_SENSORS_ADM1029 is not set
> # CONFIG_SENSORS_ADM1031 is not set
> # CONFIG_SENSORS_ADM9240 is not set
> # CONFIG_SENSORS_ADT7411 is not set
> # CONFIG_SENSORS_ADT7462 is not set
> # CONFIG_SENSORS_ADT7470 is not set
> # CONFIG_SENSORS_ADT7475 is not set
> # CONFIG_SENSORS_ASC7621 is not set
> # CONFIG_SENSORS_K8TEMP is not set
> # CONFIG_SENSORS_K10TEMP is not set
> CONFIG_SENSORS_ASB100=m
> # CONFIG_SENSORS_ATXP1 is not set
> # CONFIG_SENSORS_DS1621 is not set
> # CONFIG_SENSORS_I5K_AMB is not set
> # CONFIG_SENSORS_F71805F is not set
> # CONFIG_SENSORS_F71882FG is not set
> # CONFIG_SENSORS_F75375S is not set
> # CONFIG_SENSORS_FSCHMD is not set
> # CONFIG_SENSORS_G760A is not set
> # CONFIG_SENSORS_GL518SM is not set
> # CONFIG_SENSORS_GL520SM is not set
> CONFIG_SENSORS_CORETEMP=m
> # CONFIG_SENSORS_IBMAEM is not set
> # CONFIG_SENSORS_IBMPEX is not set
> # CONFIG_SENSORS_IT87 is not set
> # CONFIG_SENSORS_LM63 is not set
> # CONFIG_SENSORS_LM73 is not set
> # CONFIG_SENSORS_LM75 is not set
> # CONFIG_SENSORS_LM77 is not set
> # CONFIG_SENSORS_LM78 is not set
> # CONFIG_SENSORS_LM80 is not set
> # CONFIG_SENSORS_LM83 is not set
> # CONFIG_SENSORS_LM85 is not set
> # CONFIG_SENSORS_LM87 is not set
> # CONFIG_SENSORS_LM90 is not set
> # CONFIG_SENSORS_LM92 is not set
> # CONFIG_SENSORS_LM93 is not set
> # CONFIG_SENSORS_LTC4215 is not set
> # CONFIG_SENSORS_LTC4245 is not set
> # CONFIG_SENSORS_LM95241 is not set
> # CONFIG_SENSORS_MAX1619 is not set
> # CONFIG_SENSORS_MAX6650 is not set
> # CONFIG_SENSORS_PC87360 is not set
> # CONFIG_SENSORS_PC87427 is not set
> # CONFIG_SENSORS_PCF8591 is not set
> # CONFIG_SENSORS_SHT15 is not set
> # CONFIG_SENSORS_SIS5595 is not set
> # CONFIG_SENSORS_DME1737 is not set
> # CONFIG_SENSORS_SMSC47M1 is not set
> # CONFIG_SENSORS_SMSC47M192 is not set
> # CONFIG_SENSORS_SMSC47B397 is not set
> # CONFIG_SENSORS_ADS7828 is not set
> # CONFIG_SENSORS_AMC6821 is not set
> # CONFIG_SENSORS_THMC50 is not set
> # CONFIG_SENSORS_TMP401 is not set
> # CONFIG_SENSORS_TMP421 is not set
> # CONFIG_SENSORS_VIA_CPUTEMP is not set
> # CONFIG_SENSORS_VIA686A is not set
> # CONFIG_SENSORS_VT1211 is not set
> # CONFIG_SENSORS_VT8231 is not set
> # CONFIG_SENSORS_W83781D is not set
> # CONFIG_SENSORS_W83791D is not set
> # CONFIG_SENSORS_W83792D is not set
> # CONFIG_SENSORS_W83793 is not set
> # CONFIG_SENSORS_W83L785TS is not set
> # CONFIG_SENSORS_W83L786NG is not set
> # CONFIG_SENSORS_W83627HF is not set
> # CONFIG_SENSORS_W83627EHF is not set
> # CONFIG_SENSORS_HDAPS is not set
> # CONFIG_SENSORS_LIS3_I2C is not set
> # CONFIG_SENSORS_APPLESMC is not set
>
> #
> # ACPI drivers
> #
> # CONFIG_SENSORS_ATK0110 is not set
> # CONFIG_SENSORS_LIS3LV02D is not set
> CONFIG_THERMAL=y
> CONFIG_WATCHDOG=y
> # CONFIG_WATCHDOG_NOWAYOUT is not set
>
> #
> # Watchdog Device Drivers
> #
> CONFIG_SOFT_WATCHDOG=m
> # CONFIG_ACQUIRE_WDT is not set
> # CONFIG_ADVANTECH_WDT is not set
> # CONFIG_ALIM1535_WDT is not set
> # CONFIG_ALIM7101_WDT is not set
> # CONFIG_SC520_WDT is not set
> # CONFIG_SBC_FITPC2_WATCHDOG is not set
> # CONFIG_EUROTECH_WDT is not set
> # CONFIG_IB700_WDT is not set
> # CONFIG_IBMASR is not set
> # CONFIG_WAFER_WDT is not set
> CONFIG_I6300ESB_WDT=m
> CONFIG_ITCO_WDT=m
> CONFIG_ITCO_VENDOR_SUPPORT=y
> # CONFIG_IT8712F_WDT is not set
> # CONFIG_IT87_WDT is not set
> # CONFIG_HP_WATCHDOG is not set
> # CONFIG_SC1200_WDT is not set
> # CONFIG_PC87413_WDT is not set
> # CONFIG_60XX_WDT is not set
> # CONFIG_SBC8360_WDT is not set
> # CONFIG_CPU5_WDT is not set
> # CONFIG_SMSC_SCH311X_WDT is not set
> # CONFIG_SMSC37B787_WDT is not set
> # CONFIG_W83627HF_WDT is not set
> # CONFIG_W83697HF_WDT is not set
> # CONFIG_W83697UG_WDT is not set
> # CONFIG_W83877F_WDT is not set
> # CONFIG_W83977F_WDT is not set
> # CONFIG_MACHZ_WDT is not set
> # CONFIG_SBC_EPX_C3_WATCHDOG is not set
>
> #
> # PCI-based Watchdog Cards
> #
> # CONFIG_PCIPCWATCHDOG is not set
> # CONFIG_WDTPCI is not set
>
> #
> # USB-based Watchdog Cards
> #
> # CONFIG_USBPCWATCHDOG is not set
> CONFIG_SSB_POSSIBLE=y
>
> #
> # Sonics Silicon Backplane
> #
> CONFIG_SSB=m
> CONFIG_SSB_SPROM=y
> CONFIG_SSB_PCIHOST_POSSIBLE=y
> CONFIG_SSB_PCIHOST=y
> # CONFIG_SSB_B43_PCI_BRIDGE is not set
> CONFIG_SSB_SDIOHOST_POSSIBLE=y
> CONFIG_SSB_SDIOHOST=y
> # CONFIG_SSB_DEBUG is not set
> CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
> CONFIG_SSB_DRIVER_PCICORE=y
>
> #
> # Multifunction device drivers
> #
> CONFIG_MFD_CORE=m
> # CONFIG_MFD_88PM860X is not set
> # CONFIG_MFD_SM501 is not set
> # CONFIG_HTC_PASIC3 is not set
> # CONFIG_HTC_I2CPLD is not set
> # CONFIG_UCB1400_CORE is not set
> # CONFIG_TPS65010 is not set
> # CONFIG_TWL4030_CORE is not set
> # CONFIG_MFD_TMIO is not set
> # CONFIG_PMIC_DA903X is not set
> # CONFIG_PMIC_ADP5520 is not set
> # CONFIG_MFD_MAX8925 is not set
> # CONFIG_MFD_WM8400 is not set
> # CONFIG_MFD_WM831X is not set
> # CONFIG_MFD_WM8350_I2C is not set
> # CONFIG_MFD_WM8994 is not set
> # CONFIG_MFD_PCF50633 is not set
> # CONFIG_AB3100_CORE is not set
> CONFIG_MFD_TIMBERDALE=m
> CONFIG_LPC_SCH=m
> CONFIG_REGULATOR=y
> # CONFIG_REGULATOR_DEBUG is not set
> # CONFIG_REGULATOR_DUMMY is not set
> CONFIG_REGULATOR_FIXED_VOLTAGE=m
> CONFIG_REGULATOR_VIRTUAL_CONSUMER=m
> CONFIG_REGULATOR_USERSPACE_CONSUMER=m
> CONFIG_REGULATOR_BQ24022=m
> CONFIG_REGULATOR_MAX1586=m
> CONFIG_REGULATOR_MAX8649=m
> CONFIG_REGULATOR_MAX8660=m
> CONFIG_REGULATOR_LP3971=m
> CONFIG_REGULATOR_TPS65023=m
> CONFIG_REGULATOR_TPS6507X=m
> CONFIG_MEDIA_SUPPORT=m
>
> #
> # Multimedia core support
> #
> CONFIG_VIDEO_DEV=m
> CONFIG_VIDEO_V4L2_COMMON=m
> # CONFIG_VIDEO_ALLOW_V4L1 is not set
> CONFIG_VIDEO_V4L1_COMPAT=y
> # CONFIG_DVB_CORE is not set
> CONFIG_VIDEO_MEDIA=m
>
> #
> # Multimedia drivers
> #
> CONFIG_VIDEO_SAA7146=m
> CONFIG_VIDEO_SAA7146_VV=m
> CONFIG_IR_CORE=m
> CONFIG_VIDEO_IR=m
> # CONFIG_MEDIA_ATTACH is not set
> CONFIG_MEDIA_TUNER=m
> # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
> CONFIG_MEDIA_TUNER_SIMPLE=m
> CONFIG_MEDIA_TUNER_TDA8290=m
> CONFIG_MEDIA_TUNER_TDA9887=m
> CONFIG_MEDIA_TUNER_TEA5761=m
> CONFIG_MEDIA_TUNER_TEA5767=m
> CONFIG_MEDIA_TUNER_MT20XX=m
> CONFIG_MEDIA_TUNER_XC2028=m
> CONFIG_MEDIA_TUNER_XC5000=m
> CONFIG_MEDIA_TUNER_MC44S803=m
> CONFIG_VIDEO_V4L2=m
> CONFIG_VIDEOBUF_GEN=m
> CONFIG_VIDEOBUF_DMA_SG=m
> CONFIG_VIDEOBUF_VMALLOC=m
> CONFIG_VIDEO_BTCX=m
> CONFIG_VIDEO_TVEEPROM=m
> CONFIG_VIDEO_TUNER=m
> CONFIG_VIDEO_CAPTURE_DRIVERS=y
> # CONFIG_VIDEO_ADV_DEBUG is not set
> # CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
> CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
> CONFIG_VIDEO_IR_I2C=m
> CONFIG_VIDEO_TVAUDIO=m
> CONFIG_VIDEO_TDA7432=m
> CONFIG_VIDEO_MSP3400=m
> CONFIG_VIDEO_CS53L32A=m
> CONFIG_VIDEO_M52790=m
> CONFIG_VIDEO_WM8775=m
> CONFIG_VIDEO_WM8739=m
> CONFIG_VIDEO_VP27SMPX=m
> CONFIG_VIDEO_SAA6588=m
> CONFIG_VIDEO_BT819=m
> CONFIG_VIDEO_BT856=m
> CONFIG_VIDEO_BT866=m
> CONFIG_VIDEO_KS0127=m
> CONFIG_VIDEO_OV7670=m
> CONFIG_VIDEO_MT9V011=m
> CONFIG_VIDEO_SAA7110=m
> CONFIG_VIDEO_SAA711X=m
> CONFIG_VIDEO_SAA717X=m
> CONFIG_VIDEO_TVP5150=m
> CONFIG_VIDEO_VPX3220=m
> CONFIG_VIDEO_CX25840=m
> CONFIG_VIDEO_CX2341X=m
> CONFIG_VIDEO_SAA7127=m
> CONFIG_VIDEO_SAA7185=m
> CONFIG_VIDEO_ADV7170=m
> CONFIG_VIDEO_ADV7175=m
> CONFIG_VIDEO_UPD64031A=m
> CONFIG_VIDEO_UPD64083=m
> # CONFIG_VIDEO_VIVI is not set
> CONFIG_VIDEO_BT848=m
> CONFIG_VIDEO_SAA5246A=m
> CONFIG_VIDEO_SAA5249=m
> CONFIG_VIDEO_ZORAN=m
> CONFIG_VIDEO_ZORAN_DC30=m
> CONFIG_VIDEO_ZORAN_ZR36060=m
> CONFIG_VIDEO_ZORAN_BUZ=m
> CONFIG_VIDEO_ZORAN_DC10=m
> CONFIG_VIDEO_ZORAN_LML33=m
> CONFIG_VIDEO_ZORAN_LML33R10=m
> CONFIG_VIDEO_ZORAN_AVS6EYES=m
> CONFIG_VIDEO_SAA7134=m
> # CONFIG_VIDEO_SAA7134_ALSA is not set
> CONFIG_VIDEO_HEXIUM_ORION=m
> CONFIG_VIDEO_HEXIUM_GEMINI=m
> CONFIG_VIDEO_CX88=m
> CONFIG_VIDEO_CX88_ALSA=m
> CONFIG_VIDEO_CX88_BLACKBIRD=m
> CONFIG_VIDEO_CX88_MPEG=m
> CONFIG_VIDEO_IVTV=m
> CONFIG_VIDEO_FB_IVTV=m
> CONFIG_VIDEO_CAFE_CCIC=m
> CONFIG_SOC_CAMERA=m
> CONFIG_SOC_CAMERA_MT9M001=m
> CONFIG_SOC_CAMERA_MT9M111=m
> CONFIG_SOC_CAMERA_MT9T031=m
> CONFIG_SOC_CAMERA_MT9T112=m
> CONFIG_SOC_CAMERA_MT9V022=m
> CONFIG_SOC_CAMERA_RJ54N1=m
> CONFIG_SOC_CAMERA_TW9910=m
> # CONFIG_SOC_CAMERA_PLATFORM is not set
> CONFIG_SOC_CAMERA_OV772X=m
> CONFIG_SOC_CAMERA_OV9640=m
> CONFIG_V4L_USB_DRIVERS=y
> CONFIG_USB_VIDEO_CLASS=m
> CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
> CONFIG_USB_GSPCA=m
> CONFIG_USB_M5602=m
> CONFIG_USB_STV06XX=m
> CONFIG_USB_GL860=m
> CONFIG_USB_GSPCA_BENQ=m
> CONFIG_USB_GSPCA_CONEX=m
> CONFIG_USB_GSPCA_CPIA1=m
> CONFIG_USB_GSPCA_ETOMS=m
> CONFIG_USB_GSPCA_FINEPIX=m
> CONFIG_USB_GSPCA_JEILINJ=m
> CONFIG_USB_GSPCA_MARS=m
> CONFIG_USB_GSPCA_MR97310A=m
> CONFIG_USB_GSPCA_OV519=m
> CONFIG_USB_GSPCA_OV534=m
> CONFIG_USB_GSPCA_OV534_9=m
> CONFIG_USB_GSPCA_PAC207=m
> CONFIG_USB_GSPCA_PAC7302=m
> CONFIG_USB_GSPCA_PAC7311=m
> CONFIG_USB_GSPCA_SN9C2028=m
> CONFIG_USB_GSPCA_SN9C20X=m
> # CONFIG_USB_GSPCA_SN9C20X_EVDEV is not set
> CONFIG_USB_GSPCA_SONIXB=m
> CONFIG_USB_GSPCA_SONIXJ=m
> CONFIG_USB_GSPCA_SPCA500=m
> CONFIG_USB_GSPCA_SPCA501=m
> CONFIG_USB_GSPCA_SPCA505=m
> CONFIG_USB_GSPCA_SPCA506=m
> CONFIG_USB_GSPCA_SPCA508=m
> CONFIG_USB_GSPCA_SPCA561=m
> CONFIG_USB_GSPCA_SQ905=m
> CONFIG_USB_GSPCA_SQ905C=m
> CONFIG_USB_GSPCA_STK014=m
> CONFIG_USB_GSPCA_STV0680=m
> CONFIG_USB_GSPCA_SUNPLUS=m
> CONFIG_USB_GSPCA_T613=m
> CONFIG_USB_GSPCA_TV8532=m
> CONFIG_USB_GSPCA_VC032X=m
> CONFIG_USB_GSPCA_ZC3XX=m
> # CONFIG_VIDEO_PVRUSB2 is not set
> # CONFIG_VIDEO_HDPVR is not set
> CONFIG_VIDEO_EM28XX=m
> CONFIG_VIDEO_EM28XX_ALSA=m
> CONFIG_VIDEO_CX231XX=m
> CONFIG_VIDEO_CX231XX_ALSA=m
> CONFIG_VIDEO_USBVISION=m
> CONFIG_USB_ET61X251=m
> CONFIG_USB_SN9C102=m
> CONFIG_USB_ZC0301=m
> # CONFIG_USB_PWC_INPUT_EVDEV is not set
> CONFIG_USB_ZR364XX=m
> CONFIG_USB_STKWEBCAM=m
> CONFIG_USB_S2255=m
> # CONFIG_RADIO_ADAPTERS is not set
> # CONFIG_DAB is not set
>
> #
> # Graphics support
> #
> CONFIG_AGP=y
> # CONFIG_AGP_AMD64 is not set
> CONFIG_AGP_INTEL=y
> # CONFIG_AGP_SIS is not set
> # CONFIG_AGP_VIA is not set
> CONFIG_VGA_ARB=y
> CONFIG_VGA_ARB_MAX_GPUS=16
> # CONFIG_VGA_SWITCHEROO is not set
> CONFIG_DRM=y
> CONFIG_DRM_KMS_HELPER=y
> CONFIG_DRM_TTM=m
> CONFIG_DRM_TDFX=m
> CONFIG_DRM_R128=m
> CONFIG_DRM_RADEON=m
> # CONFIG_DRM_RADEON_KMS is not set
> CONFIG_DRM_I810=m
> # CONFIG_DRM_I830 is not set
> CONFIG_DRM_I915=y
> CONFIG_DRM_I915_KMS=y
> CONFIG_DRM_MGA=m
> CONFIG_DRM_SIS=m
> CONFIG_DRM_VIA=m
> CONFIG_DRM_SAVAGE=m
> CONFIG_VGASTATE=m
> CONFIG_VIDEO_OUTPUT_CONTROL=y
> CONFIG_FB=y
> CONFIG_FIRMWARE_EDID=y
> CONFIG_FB_DDC=m
> # CONFIG_FB_BOOT_VESA_SUPPORT is not set
> CONFIG_FB_CFB_FILLRECT=y
> CONFIG_FB_CFB_COPYAREA=y
> CONFIG_FB_CFB_IMAGEBLIT=y
> # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
> CONFIG_FB_SYS_FILLRECT=y
> CONFIG_FB_SYS_COPYAREA=y
> CONFIG_FB_SYS_IMAGEBLIT=y
> # CONFIG_FB_FOREIGN_ENDIAN is not set
> CONFIG_FB_SYS_FOPS=y
> CONFIG_FB_DEFERRED_IO=y
> CONFIG_FB_HECUBA=m
> CONFIG_FB_SVGALIB=m
> # CONFIG_FB_MACMODES is not set
> CONFIG_FB_BACKLIGHT=y
> CONFIG_FB_MODE_HELPERS=y
> CONFIG_FB_TILEBLITTING=y
>
> #
> # Frame buffer hardware drivers
> #
> # CONFIG_FB_CIRRUS is not set
> # CONFIG_FB_PM2 is not set
> CONFIG_FB_CYBER2000=m
> CONFIG_FB_ARC=m
> # CONFIG_FB_ASILIANT is not set
> # CONFIG_FB_IMSTT is not set
> CONFIG_FB_VGA16=m
> CONFIG_FB_UVESA=m
> # CONFIG_FB_VESA is not set
> # CONFIG_FB_EFI is not set
> CONFIG_FB_N411=m
> CONFIG_FB_HGA=m
> # CONFIG_FB_HGA_ACCEL is not set
> CONFIG_FB_S1D13XXX=m
> CONFIG_FB_NVIDIA=m
> # CONFIG_FB_NVIDIA_I2C is not set
> # CONFIG_FB_NVIDIA_DEBUG is not set
> CONFIG_FB_NVIDIA_BACKLIGHT=y
> CONFIG_FB_RIVA=m
> # CONFIG_FB_RIVA_I2C is not set
> # CONFIG_FB_RIVA_DEBUG is not set
> CONFIG_FB_RIVA_BACKLIGHT=y
> CONFIG_FB_LE80578=m
> # CONFIG_FB_CARILLO_RANCH is not set
> CONFIG_FB_MATROX=m
> # CONFIG_FB_MATROX_MILLENIUM is not set
> # CONFIG_FB_MATROX_MYSTIQUE is not set
> # CONFIG_FB_MATROX_G is not set
> # CONFIG_FB_MATROX_I2C is not set
> CONFIG_FB_RADEON=m
> CONFIG_FB_RADEON_I2C=y
> CONFIG_FB_RADEON_BACKLIGHT=y
> # CONFIG_FB_RADEON_DEBUG is not set
> CONFIG_FB_ATY128=m
> CONFIG_FB_ATY128_BACKLIGHT=y
> CONFIG_FB_ATY=m
> # CONFIG_FB_ATY_CT is not set
> # CONFIG_FB_ATY_GX is not set
> CONFIG_FB_ATY_BACKLIGHT=y
> CONFIG_FB_S3=m
> CONFIG_FB_SAVAGE=m
> # CONFIG_FB_SAVAGE_I2C is not set
> # CONFIG_FB_SAVAGE_ACCEL is not set
> CONFIG_FB_SIS=m
> # CONFIG_FB_SIS_300 is not set
> # CONFIG_FB_SIS_315 is not set
> CONFIG_FB_VIA=m
> CONFIG_FB_NEOMAGIC=m
> CONFIG_FB_KYRO=m
> CONFIG_FB_3DFX=m
> # CONFIG_FB_3DFX_ACCEL is not set
> CONFIG_FB_3DFX_I2C=y
> CONFIG_FB_VOODOO1=m
> CONFIG_FB_VT8623=m
> CONFIG_FB_TRIDENT=m
> CONFIG_FB_ARK=m
> CONFIG_FB_PM3=m
> CONFIG_FB_CARMINE=m
> CONFIG_FB_CARMINE_DRAM_EVAL=y
> # CONFIG_CARMINE_DRAM_CUSTOM is not set
> CONFIG_FB_GEODE=y
> CONFIG_FB_GEODE_LX=m
> CONFIG_FB_GEODE_GX=m
> CONFIG_FB_GEODE_GX1=m
> CONFIG_FB_TMIO=m
> CONFIG_FB_TMIO_ACCELL=y
> CONFIG_FB_VIRTUAL=m
> CONFIG_XEN_FBDEV_FRONTEND=y
> CONFIG_FB_METRONOME=m
> CONFIG_FB_MB862XX=m
> # CONFIG_FB_MB862XX_PCI_GDC is not set
> CONFIG_FB_BROADSHEET=m
> CONFIG_BACKLIGHT_LCD_SUPPORT=y
> CONFIG_LCD_CLASS_DEVICE=m
> # CONFIG_LCD_ILI9320 is not set
> CONFIG_LCD_PLATFORM=m
> CONFIG_BACKLIGHT_CLASS_DEVICE=y
> # CONFIG_BACKLIGHT_GENERIC is not set
> # CONFIG_BACKLIGHT_PROGEAR is not set
> # CONFIG_BACKLIGHT_CARILLO_RANCH is not set
> # CONFIG_BACKLIGHT_MBP_NVIDIA is not set
> # CONFIG_BACKLIGHT_SAHARA is not set
>
> #
> # Display device support
> #
> CONFIG_DISPLAY_SUPPORT=m
>
> #
> # Display hardware drivers
> #
>
> #
> # Console display driver support
> #
> CONFIG_VGA_CONSOLE=y
> CONFIG_VGACON_SOFT_SCROLLBACK=y
> CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
> CONFIG_DUMMY_CONSOLE=y
> CONFIG_FRAMEBUFFER_CONSOLE=y
> # CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
> # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
> # CONFIG_FONTS is not set
> CONFIG_FONT_8x8=y
> CONFIG_FONT_8x16=y
> # CONFIG_LOGO is not set
> CONFIG_SOUND=y
> CONFIG_SOUND_OSS_CORE=y
> CONFIG_SOUND_OSS_CORE_PRECLAIM=y
> CONFIG_SND=m
> CONFIG_SND_TIMER=m
> CONFIG_SND_PCM=m
> CONFIG_SND_HWDEP=m
> CONFIG_SND_RAWMIDI=m
> CONFIG_SND_SEQUENCER=m
> CONFIG_SND_SEQ_DUMMY=m
> CONFIG_SND_OSSEMUL=y
> CONFIG_SND_MIXER_OSS=m
> CONFIG_SND_PCM_OSS=m
> CONFIG_SND_PCM_OSS_PLUGINS=y
> CONFIG_SND_SEQUENCER_OSS=y
> CONFIG_SND_HRTIMER=m
> CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
> CONFIG_SND_DYNAMIC_MINORS=y
> CONFIG_SND_SUPPORT_OLD_API=y
> CONFIG_SND_VERBOSE_PROCFS=y
> # CONFIG_SND_VERBOSE_PRINTK is not set
> # CONFIG_SND_DEBUG is not set
> CONFIG_SND_VMASTER=y
> CONFIG_SND_DMA_SGBUF=y
> CONFIG_SND_RAWMIDI_SEQ=m
> # CONFIG_SND_OPL3_LIB_SEQ is not set
> # CONFIG_SND_OPL4_LIB_SEQ is not set
> # CONFIG_SND_SBAWE_SEQ is not set
> # CONFIG_SND_EMU10K1_SEQ is not set
> CONFIG_SND_AC97_CODEC=m
> CONFIG_SND_DRIVERS=y
> # CONFIG_SND_PCSP is not set
> # CONFIG_SND_DUMMY is not set
> # CONFIG_SND_VIRMIDI is not set
> # CONFIG_SND_MTPAV is not set
> # CONFIG_SND_MTS64 is not set
> # CONFIG_SND_SERIAL_U16550 is not set
> # CONFIG_SND_MPU401 is not set
> # CONFIG_SND_PORTMAN2X4 is not set
> # CONFIG_SND_AC97_POWER_SAVE is not set
> CONFIG_SND_PCI=y
> # CONFIG_SND_AD1889 is not set
> # CONFIG_SND_ALS300 is not set
> # CONFIG_SND_ALS4000 is not set
> # CONFIG_SND_ALI5451 is not set
> # CONFIG_SND_ATIIXP is not set
> # CONFIG_SND_ATIIXP_MODEM is not set
> # CONFIG_SND_AU8810 is not set
> # CONFIG_SND_AU8820 is not set
> # CONFIG_SND_AU8830 is not set
> # CONFIG_SND_AW2 is not set
> # CONFIG_SND_AZT3328 is not set
> # CONFIG_SND_BT87X is not set
> # CONFIG_SND_CA0106 is not set
> # CONFIG_SND_CMIPCI is not set
> # CONFIG_SND_OXYGEN is not set
> # CONFIG_SND_CS4281 is not set
> # CONFIG_SND_CS46XX is not set
> # CONFIG_SND_CS5530 is not set
> # CONFIG_SND_CS5535AUDIO is not set
> # CONFIG_SND_CTXFI is not set
> # CONFIG_SND_DARLA20 is not set
> # CONFIG_SND_GINA20 is not set
> # CONFIG_SND_LAYLA20 is not set
> # CONFIG_SND_DARLA24 is not set
> # CONFIG_SND_GINA24 is not set
> # CONFIG_SND_LAYLA24 is not set
> # CONFIG_SND_MONA is not set
> # CONFIG_SND_MIA is not set
> # CONFIG_SND_ECHO3G is not set
> # CONFIG_SND_INDIGO is not set
> # CONFIG_SND_INDIGOIO is not set
> # CONFIG_SND_INDIGODJ is not set
> # CONFIG_SND_INDIGOIOX is not set
> # CONFIG_SND_INDIGODJX is not set
> # CONFIG_SND_EMU10K1 is not set
> # CONFIG_SND_EMU10K1X is not set
> # CONFIG_SND_ENS1370 is not set
> # CONFIG_SND_ENS1371 is not set
> # CONFIG_SND_ES1938 is not set
> # CONFIG_SND_ES1968 is not set
> # CONFIG_SND_FM801 is not set
> CONFIG_SND_HDA_INTEL=m
> CONFIG_SND_HDA_HWDEP=y
> # CONFIG_SND_HDA_RECONFIG is not set
> # CONFIG_SND_HDA_INPUT_BEEP is not set
> # CONFIG_SND_HDA_INPUT_JACK is not set
> # CONFIG_SND_HDA_PATCH_LOADER is not set
> CONFIG_SND_HDA_CODEC_REALTEK=y
> CONFIG_SND_HDA_CODEC_ANALOG=y
> CONFIG_SND_HDA_CODEC_SIGMATEL=y
> CONFIG_SND_HDA_CODEC_VIA=y
> CONFIG_SND_HDA_CODEC_ATIHDMI=y
> CONFIG_SND_HDA_CODEC_NVHDMI=y
> CONFIG_SND_HDA_CODEC_INTELHDMI=y
> CONFIG_SND_HDA_ELD=y
> CONFIG_SND_HDA_CODEC_CIRRUS=y
> CONFIG_SND_HDA_CODEC_CONEXANT=y
> CONFIG_SND_HDA_CODEC_CA0110=y
> CONFIG_SND_HDA_CODEC_CMEDIA=y
> CONFIG_SND_HDA_CODEC_SI3054=y
> CONFIG_SND_HDA_GENERIC=y
> # CONFIG_SND_HDA_POWER_SAVE is not set
> # CONFIG_SND_HDSP is not set
> # CONFIG_SND_HDSPM is not set
> # CONFIG_SND_HIFIER is not set
> # CONFIG_SND_ICE1712 is not set
> # CONFIG_SND_ICE1724 is not set
> CONFIG_SND_INTEL8X0=m
> CONFIG_SND_INTEL8X0M=m
> # CONFIG_SND_KORG1212 is not set
> # CONFIG_SND_LX6464ES is not set
> # CONFIG_SND_MAESTRO3 is not set
> # CONFIG_SND_MIXART is not set
> # CONFIG_SND_NM256 is not set
> # CONFIG_SND_PCXHR is not set
> # CONFIG_SND_RIPTIDE is not set
> # CONFIG_SND_RME32 is not set
> # CONFIG_SND_RME96 is not set
> # CONFIG_SND_RME9652 is not set
> # CONFIG_SND_SONICVIBES is not set
> # CONFIG_SND_TRIDENT is not set
> # CONFIG_SND_VIA82XX is not set
> # CONFIG_SND_VIA82XX_MODEM is not set
> # CONFIG_SND_VIRTUOSO is not set
> # CONFIG_SND_VX222 is not set
> # CONFIG_SND_YMFPCI is not set
> CONFIG_SND_USB=y
> CONFIG_SND_USB_AUDIO=m
> # CONFIG_SND_USB_UA101 is not set
> # CONFIG_SND_USB_USX2Y is not set
> # CONFIG_SND_USB_CAIAQ is not set
> # CONFIG_SND_USB_US122L is not set
> # CONFIG_SND_SOC is not set
> # CONFIG_SOUND_PRIME is not set
> CONFIG_AC97_BUS=m
> CONFIG_HID_SUPPORT=y
> CONFIG_HID=m
> CONFIG_HIDRAW=y
>
> #
> # USB Input Devices
> #
> CONFIG_USB_HID=m
> CONFIG_HID_PID=y
> CONFIG_USB_HIDDEV=y
>
> #
> # Special HID drivers
> #
> # CONFIG_HID_3M_PCT is not set
> CONFIG_HID_A4TECH=m
> CONFIG_HID_APPLE=m
> CONFIG_HID_BELKIN=m
> CONFIG_HID_CHERRY=m
> CONFIG_HID_CHICONY=m
> CONFIG_HID_CYPRESS=m
> CONFIG_HID_DRAGONRISE=m
> # CONFIG_DRAGONRISE_FF is not set
> CONFIG_HID_EZKEY=m
> CONFIG_HID_KYE=m
> CONFIG_HID_GYRATION=m
> CONFIG_HID_TWINHAN=m
> CONFIG_HID_KENSINGTON=m
> CONFIG_HID_LOGITECH=m
> CONFIG_LOGITECH_FF=y
> # CONFIG_LOGIRUMBLEPAD2_FF is not set
> # CONFIG_LOGIG940_FF is not set
> # CONFIG_HID_MAGICMOUSE is not set
> CONFIG_HID_MICROSOFT=m
> # CONFIG_HID_MOSART is not set
> CONFIG_HID_MONTEREY=m
> CONFIG_HID_NTRIG=m
> CONFIG_HID_ORTEK=m
> CONFIG_HID_PANTHERLORD=m
> CONFIG_PANTHERLORD_FF=y
> CONFIG_HID_PETALYNX=m
> CONFIG_HID_QUANTA=m
> CONFIG_HID_SAMSUNG=m
> CONFIG_HID_SONY=m
> # CONFIG_HID_STANTUM is not set
> CONFIG_HID_SUNPLUS=m
> CONFIG_HID_GREENASIA=m
> # CONFIG_GREENASIA_FF is not set
> CONFIG_HID_SMARTJOYPLUS=m
> # CONFIG_SMARTJOYPLUS_FF is not set
> CONFIG_HID_TOPSEED=m
> CONFIG_HID_THRUSTMASTER=m
> CONFIG_THRUSTMASTER_FF=y
> # CONFIG_HID_WACOM is not set
> CONFIG_HID_ZEROPLUS=m
> CONFIG_ZEROPLUS_FF=y
> CONFIG_USB_SUPPORT=y
> CONFIG_USB_ARCH_HAS_HCD=y
> CONFIG_USB_ARCH_HAS_OHCI=y
> CONFIG_USB_ARCH_HAS_EHCI=y
> CONFIG_USB=y
> CONFIG_USB_DEBUG=y
> CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
>
> #
> # Miscellaneous USB options
> #
> CONFIG_USB_DEVICEFS=y
> # CONFIG_USB_DEVICE_CLASS is not set
> # CONFIG_USB_DYNAMIC_MINORS is not set
> # CONFIG_USB_SUSPEND is not set
> # CONFIG_USB_OTG is not set
> # CONFIG_USB_MON is not set
> CONFIG_USB_WUSB=m
> # CONFIG_USB_WUSB_CBAF is not set
>
> #
> # USB Host Controller Drivers
> #
> # CONFIG_USB_C67X00_HCD is not set
> # CONFIG_USB_XHCI_HCD is not set
> CONFIG_USB_EHCI_HCD=y
> # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
> # CONFIG_USB_EHCI_TT_NEWSCHED is not set
> # CONFIG_USB_OXU210HP_HCD is not set
> # CONFIG_USB_ISP116X_HCD is not set
> # CONFIG_USB_ISP1760_HCD is not set
> # CONFIG_USB_ISP1362_HCD is not set
> CONFIG_USB_OHCI_HCD=y
> # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
> # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
> CONFIG_USB_OHCI_LITTLE_ENDIAN=y
> CONFIG_USB_UHCI_HCD=y
> # CONFIG_USB_U132_HCD is not set
> # CONFIG_USB_SL811_HCD is not set
> # CONFIG_USB_R8A66597_HCD is not set
> CONFIG_USB_WHCI_HCD=m
> CONFIG_USB_HWA_HCD=m
>
> #
> # USB Device Class drivers
> #
> # CONFIG_USB_ACM is not set
> CONFIG_USB_PRINTER=m
> CONFIG_USB_WDM=m
> # CONFIG_USB_TMC is not set
>
> #
> # NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
> #
>
> #
> # also be needed; see USB_STORAGE Help for more info
> #
> CONFIG_USB_STORAGE=m
> # CONFIG_USB_STORAGE_DEBUG is not set
> CONFIG_USB_STORAGE_DATAFAB=m
> # CONFIG_USB_STORAGE_FREECOM is not set
> # CONFIG_USB_STORAGE_ISD200 is not set
> CONFIG_USB_STORAGE_USBAT=m
> CONFIG_USB_STORAGE_SDDR09=m
> CONFIG_USB_STORAGE_SDDR55=m
> CONFIG_USB_STORAGE_JUMPSHOT=m
> CONFIG_USB_STORAGE_ALAUDA=m
> CONFIG_USB_STORAGE_ONETOUCH=m
> CONFIG_USB_STORAGE_KARMA=m
> CONFIG_USB_STORAGE_CYPRESS_ATACB=m
> CONFIG_USB_LIBUSUAL=y
>
> #
> # USB Imaging devices
> #
> CONFIG_USB_MDC800=m
> CONFIG_USB_MICROTEK=m
>
> #
> # USB port drivers
> #
> # CONFIG_USB_USS720 is not set
> CONFIG_USB_SERIAL=m
> CONFIG_USB_EZUSB=y
> CONFIG_USB_SERIAL_GENERIC=y
> CONFIG_USB_SERIAL_AIRCABLE=m
> CONFIG_USB_SERIAL_ARK3116=m
> CONFIG_USB_SERIAL_BELKIN=m
> CONFIG_USB_SERIAL_CH341=m
> CONFIG_USB_SERIAL_WHITEHEAT=m
> CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
> CONFIG_USB_SERIAL_CP210X=m
> CONFIG_USB_SERIAL_CYPRESS_M8=m
> CONFIG_USB_SERIAL_EMPEG=m
> CONFIG_USB_SERIAL_FTDI_SIO=m
> CONFIG_USB_SERIAL_FUNSOFT=m
> CONFIG_USB_SERIAL_VISOR=m
> CONFIG_USB_SERIAL_IPAQ=m
> CONFIG_USB_SERIAL_IR=m
> CONFIG_USB_SERIAL_EDGEPORT=m
> CONFIG_USB_SERIAL_EDGEPORT_TI=m
> CONFIG_USB_SERIAL_GARMIN=m
> CONFIG_USB_SERIAL_IPW=m
> CONFIG_USB_SERIAL_IUU=m
> CONFIG_USB_SERIAL_KEYSPAN_PDA=m
> CONFIG_USB_SERIAL_KEYSPAN=m
> # CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
> # CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
> # CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
> # CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
> # CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
> # CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
> # CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
> # CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
> # CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
> # CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
> # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
> # CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
> CONFIG_USB_SERIAL_KLSI=m
> CONFIG_USB_SERIAL_KOBIL_SCT=m
> CONFIG_USB_SERIAL_MCT_U232=m
> CONFIG_USB_SERIAL_MOS7720=m
> CONFIG_USB_SERIAL_MOS7840=m
> CONFIG_USB_SERIAL_MOTOROLA=m
> CONFIG_USB_SERIAL_NAVMAN=m
> CONFIG_USB_SERIAL_PL2303=m
> CONFIG_USB_SERIAL_OTI6858=m
> CONFIG_USB_SERIAL_QCAUX=m
> CONFIG_USB_SERIAL_QUALCOMM=m
> CONFIG_USB_SERIAL_SPCP8X5=m
> CONFIG_USB_SERIAL_HP4X=m
> CONFIG_USB_SERIAL_SAFE=m
> # CONFIG_USB_SERIAL_SAFE_PADDED is not set
> CONFIG_USB_SERIAL_SIEMENS_MPI=m
> CONFIG_USB_SERIAL_SIERRAWIRELESS=m
> CONFIG_USB_SERIAL_SYMBOL=m
> CONFIG_USB_SERIAL_TI=m
> CONFIG_USB_SERIAL_CYBERJACK=m
> CONFIG_USB_SERIAL_XIRCOM=m
> CONFIG_USB_SERIAL_OPTION=m
> CONFIG_USB_SERIAL_OMNINET=m
> CONFIG_USB_SERIAL_OPTICON=m
> CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
> # CONFIG_USB_SERIAL_DEBUG is not set
>
> #
> # USB Miscellaneous drivers
> #
> # CONFIG_USB_EMI62 is not set
> # CONFIG_USB_EMI26 is not set
> # CONFIG_USB_ADUTUX is not set
> # CONFIG_USB_SEVSEG is not set
> CONFIG_USB_RIO500=m
> # CONFIG_USB_LEGOTOWER is not set
> # CONFIG_USB_LCD is not set
> CONFIG_USB_LED=m
> # CONFIG_USB_CYPRESS_CY7C63 is not set
> # CONFIG_USB_CYTHERM is not set
> # CONFIG_USB_IDMOUSE is not set
> CONFIG_USB_FTDI_ELAN=m
> # CONFIG_USB_APPLEDISPLAY is not set
> # CONFIG_USB_SISUSBVGA is not set
> # CONFIG_USB_LD is not set
> # CONFIG_USB_TRANCEVIBRATOR is not set
> # CONFIG_USB_IOWARRIOR is not set
> # CONFIG_USB_TEST is not set
> CONFIG_USB_ISIGHTFW=m
> # CONFIG_USB_GADGET is not set
>
> #
> # OTG and related infrastructure
> #
> # CONFIG_USB_GPIO_VBUS is not set
> # CONFIG_NOP_USB_XCEIV is not set
> CONFIG_UWB=m
> CONFIG_UWB_HWA=m
> CONFIG_UWB_WHCI=m
> # CONFIG_UWB_WLP is not set
> # CONFIG_UWB_I1480U is not set
> CONFIG_MMC=y
> # CONFIG_MMC_DEBUG is not set
> # CONFIG_MMC_UNSAFE_RESUME is not set
>
> #
> # MMC/SD/SDIO Card Drivers
> #
> CONFIG_MMC_BLOCK=y
> CONFIG_MMC_BLOCK_BOUNCE=y
> CONFIG_SDIO_UART=y
> # CONFIG_MMC_TEST is not set
>
> #
> # MMC/SD/SDIO Host Controller Drivers
> #
> CONFIG_MMC_SDHCI=y
> CONFIG_MMC_SDHCI_PCI=y
> # CONFIG_MMC_RICOH_MMC is not set
> CONFIG_MMC_SDHCI_PLTFM=y
> CONFIG_MMC_WBSD=m
> CONFIG_MMC_TIFM_SD=y
> CONFIG_MMC_CB710=m
> CONFIG_MMC_VIA_SDMMC=m
> CONFIG_MEMSTICK=y
> # CONFIG_MEMSTICK_DEBUG is not set
>
> #
> # MemoryStick drivers
> #
> # CONFIG_MEMSTICK_UNSAFE_RESUME is not set
> CONFIG_MSPRO_BLOCK=y
>
> #
> # MemoryStick Host Controller Drivers
> #
> CONFIG_MEMSTICK_TIFM_MS=y
> CONFIG_MEMSTICK_JMICRON_38X=y
> CONFIG_NEW_LEDS=y
> CONFIG_LEDS_CLASS=m
>
> #
> # LED drivers
> #
> CONFIG_LEDS_ALIX2=m
> CONFIG_LEDS_PCA9532=m
> CONFIG_LEDS_GPIO=m
> CONFIG_LEDS_GPIO_PLATFORM=y
> CONFIG_LEDS_LP3944=m
> CONFIG_LEDS_CLEVO_MAIL=m
> CONFIG_LEDS_PCA955X=m
> # CONFIG_LEDS_REGULATOR is not set
> CONFIG_LEDS_BD2802=m
> CONFIG_LEDS_INTEL_SS4200=m
> CONFIG_LEDS_LT3593=m
> CONFIG_LEDS_TRIGGERS=y
>
> #
> # LED Triggers
> #
> CONFIG_LEDS_TRIGGER_TIMER=m
> CONFIG_LEDS_TRIGGER_HEARTBEAT=m
> CONFIG_LEDS_TRIGGER_BACKLIGHT=m
> CONFIG_LEDS_TRIGGER_GPIO=m
> CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
>
> #
> # iptables trigger is under Netfilter config (LED target)
> #
> # CONFIG_ACCESSIBILITY is not set
> # CONFIG_INFINIBAND is not set
> CONFIG_EDAC=y
>
> #
> # Reporting subsystems
> #
> # CONFIG_EDAC_DEBUG is not set
> CONFIG_EDAC_DECODE_MCE=m
> # CONFIG_EDAC_MM_EDAC is not set
> CONFIG_RTC_LIB=m
> CONFIG_RTC_CLASS=m
>
> #
> # RTC interfaces
> #
> CONFIG_RTC_INTF_SYSFS=y
> CONFIG_RTC_INTF_PROC=y
> CONFIG_RTC_INTF_DEV=y
> # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
> # CONFIG_RTC_DRV_TEST is not set
>
> #
> # I2C RTC drivers
> #
> # CONFIG_RTC_DRV_DS1307 is not set
> # CONFIG_RTC_DRV_DS1374 is not set
> # CONFIG_RTC_DRV_DS1672 is not set
> # CONFIG_RTC_DRV_MAX6900 is not set
> # CONFIG_RTC_DRV_RS5C372 is not set
> # CONFIG_RTC_DRV_ISL1208 is not set
> # CONFIG_RTC_DRV_X1205 is not set
> # CONFIG_RTC_DRV_PCF8563 is not set
> # CONFIG_RTC_DRV_PCF8583 is not set
> # CONFIG_RTC_DRV_M41T80 is not set
> # CONFIG_RTC_DRV_BQ32K is not set
> # CONFIG_RTC_DRV_S35390A is not set
> # CONFIG_RTC_DRV_FM3130 is not set
> # CONFIG_RTC_DRV_RX8581 is not set
> # CONFIG_RTC_DRV_RX8025 is not set
>
> #
> # SPI RTC drivers
> #
>
> #
> # Platform RTC drivers
> #
> CONFIG_RTC_DRV_CMOS=m
> # CONFIG_RTC_DRV_DS1286 is not set
> # CONFIG_RTC_DRV_DS1511 is not set
> # CONFIG_RTC_DRV_DS1553 is not set
> # CONFIG_RTC_DRV_DS1742 is not set
> # CONFIG_RTC_DRV_STK17TA8 is not set
> # CONFIG_RTC_DRV_M48T86 is not set
> # CONFIG_RTC_DRV_M48T35 is not set
> # CONFIG_RTC_DRV_M48T59 is not set
> # CONFIG_RTC_DRV_MSM6242 is not set
> # CONFIG_RTC_DRV_BQ4802 is not set
> # CONFIG_RTC_DRV_RP5C01 is not set
> # CONFIG_RTC_DRV_V3020 is not set
>
> #
> # on-CPU RTC drivers
> #
> CONFIG_DMADEVICES=y
> # CONFIG_DMADEVICES_DEBUG is not set
>
> #
> # DMA Devices
> #
> CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH=y
> CONFIG_INTEL_IOATDMA=m
> CONFIG_DMA_ENGINE=y
>
> #
> # DMA Clients
> #
> CONFIG_NET_DMA=y
> # CONFIG_ASYNC_TX_DMA is not set
> # CONFIG_DMATEST is not set
> CONFIG_DCA=m
> # CONFIG_AUXDISPLAY is not set
> # CONFIG_UIO is not set
>
> #
> # TI VLYNQ
> #
>
> #
> # Xen driver support
> #
> CONFIG_XEN_BALLOON=y
> CONFIG_XEN_SCRUB_PAGES=y
> CONFIG_XEN_DEV_EVTCHN=y
> CONFIG_XENFS=y
> CONFIG_XEN_COMPAT_XENFS=y
> CONFIG_XEN_SYS_HYPERVISOR=y
> # CONFIG_STAGING is not set
> CONFIG_X86_PLATFORM_DEVICES=y
> # CONFIG_ACER_WMI is not set
> CONFIG_ASUS_LAPTOP=m
> # CONFIG_FUJITSU_LAPTOP is not set
> # CONFIG_MSI_LAPTOP is not set
> # CONFIG_PANASONIC_LAPTOP is not set
> # CONFIG_COMPAL_LAPTOP is not set
> # CONFIG_SONY_LAPTOP is not set
> # CONFIG_THINKPAD_ACPI is not set
> CONFIG_INTEL_MENLOW=m
> CONFIG_EEEPC_LAPTOP=m
> # CONFIG_ACPI_WMI is not set
> # CONFIG_ACPI_ASUS is not set
> # CONFIG_TOPSTAR_LAPTOP is not set
> # CONFIG_ACPI_TOSHIBA is not set
> # CONFIG_TOSHIBA_BT_RFKILL is not set
> # CONFIG_ACPI_CMPC is not set
>
> #
> # Firmware Drivers
> #
> # CONFIG_EDD is not set
> CONFIG_FIRMWARE_MEMMAP=y
> CONFIG_EFI_VARS=y
> # CONFIG_DELL_RBU is not set
> # CONFIG_DCDBAS is not set
> CONFIG_DMIID=y
> # CONFIG_ISCSI_IBFT_FIND is not set
>
> #
> # File systems
> #
> CONFIG_EXT2_FS=m
> # CONFIG_EXT2_FS_XATTR is not set
> # CONFIG_EXT2_FS_XIP is not set
> CONFIG_EXT3_FS=m
> # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
> CONFIG_EXT3_FS_XATTR=y
> CONFIG_EXT3_FS_POSIX_ACL=y
> CONFIG_EXT3_FS_SECURITY=y
> CONFIG_EXT4_FS=y
> CONFIG_EXT4_FS_XATTR=y
> # CONFIG_EXT4_FS_POSIX_ACL is not set
> # CONFIG_EXT4_FS_SECURITY is not set
> # CONFIG_EXT4_DEBUG is not set
> CONFIG_JBD=m
> CONFIG_JBD_DEBUG=y
> CONFIG_JBD2=y
> CONFIG_JBD2_DEBUG=y
> CONFIG_FS_MBCACHE=y
> # CONFIG_REISERFS_FS is not set
> # CONFIG_JFS_FS is not set
> CONFIG_FS_POSIX_ACL=y
> # CONFIG_XFS_FS is not set
> # CONFIG_GFS2_FS is not set
> # CONFIG_OCFS2_FS is not set
> # CONFIG_BTRFS_FS is not set
> # CONFIG_NILFS2_FS is not set
> CONFIG_FILE_LOCKING=y
> CONFIG_FSNOTIFY=y
> CONFIG_DNOTIFY=y
> CONFIG_INOTIFY=y
> CONFIG_INOTIFY_USER=y
> CONFIG_QUOTA=y
> CONFIG_QUOTA_NETLINK_INTERFACE=y
> # CONFIG_PRINT_QUOTA_WARNING is not set
> # CONFIG_QUOTA_DEBUG is not set
> CONFIG_QUOTA_TREE=y
> # CONFIG_QFMT_V1 is not set
> CONFIG_QFMT_V2=y
> CONFIG_QUOTACTL=y
> CONFIG_QUOTACTL_COMPAT=y
> # CONFIG_AUTOFS_FS is not set
> CONFIG_AUTOFS4_FS=y
> CONFIG_FUSE_FS=y
> # CONFIG_CUSE is not set
> CONFIG_GENERIC_ACL=y
>
> #
> # Caches
> #
> # CONFIG_FSCACHE is not set
>
> #
> # CD-ROM/DVD Filesystems
> #
> CONFIG_ISO9660_FS=m
> CONFIG_JOLIET=y
> CONFIG_ZISOFS=y
> # CONFIG_UDF_FS is not set
>
> #
> # DOS/FAT/NT Filesystems
> #
> CONFIG_FAT_FS=m
> CONFIG_MSDOS_FS=m
> CONFIG_VFAT_FS=m
> CONFIG_FAT_DEFAULT_CODEPAGE=437
> CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
> # CONFIG_NTFS_FS is not set
>
> #
> # Pseudo filesystems
> #
> CONFIG_PROC_FS=y
> CONFIG_PROC_KCORE=y
> CONFIG_PROC_VMCORE=y
> CONFIG_PROC_SYSCTL=y
> CONFIG_PROC_PAGE_MONITOR=y
> CONFIG_SYSFS=y
> CONFIG_TMPFS=y
> CONFIG_TMPFS_POSIX_ACL=y
> CONFIG_HUGETLBFS=y
> CONFIG_HUGETLB_PAGE=y
> CONFIG_CONFIGFS_FS=m
> CONFIG_MISC_FILESYSTEMS=y
> # CONFIG_ADFS_FS is not set
> # CONFIG_AFFS_FS is not set
> # CONFIG_ECRYPT_FS is not set
> CONFIG_HFS_FS=m
> CONFIG_HFSPLUS_FS=m
> # CONFIG_BEFS_FS is not set
> # CONFIG_BFS_FS is not set
> # CONFIG_EFS_FS is not set
> CONFIG_JFFS2_FS=m
> CONFIG_JFFS2_FS_DEBUG=0
> CONFIG_JFFS2_FS_WRITEBUFFER=y
> # CONFIG_JFFS2_FS_WBUF_VERIFY is not set
> # CONFIG_JFFS2_SUMMARY is not set
> # CONFIG_JFFS2_FS_XATTR is not set
> # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
> CONFIG_JFFS2_ZLIB=y
> # CONFIG_JFFS2_LZO is not set
> CONFIG_JFFS2_RTIME=y
> # CONFIG_JFFS2_RUBIN is not set
> CONFIG_UBIFS_FS=m
> # CONFIG_UBIFS_FS_XATTR is not set
> # CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
> CONFIG_UBIFS_FS_LZO=y
> CONFIG_UBIFS_FS_ZLIB=y
> # CONFIG_UBIFS_FS_DEBUG is not set
> # CONFIG_LOGFS is not set
> CONFIG_CRAMFS=m
> CONFIG_SQUASHFS=m
> # CONFIG_SQUASHFS_EMBEDDED is not set
> CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
> # CONFIG_VXFS_FS is not set
> # CONFIG_MINIX_FS is not set
> # CONFIG_OMFS_FS is not set
> # CONFIG_HPFS_FS is not set
> # CONFIG_QNX4FS_FS is not set
> # CONFIG_ROMFS_FS is not set
> # CONFIG_SYSV_FS is not set
> # CONFIG_UFS_FS is not set
> CONFIG_NETWORK_FILESYSTEMS=y
> # CONFIG_NFS_FS is not set
> # CONFIG_NFSD is not set
> # CONFIG_SMB_FS is not set
> # CONFIG_CEPH_FS is not set
> CONFIG_CIFS=m
> # CONFIG_CIFS_STATS is not set
> CONFIG_CIFS_WEAK_PW_HASH=y
> # CONFIG_CIFS_UPCALL is not set
> # CONFIG_CIFS_XATTR is not set
> # CONFIG_CIFS_DEBUG2 is not set
> # CONFIG_CIFS_DFS_UPCALL is not set
> # CONFIG_CIFS_EXPERIMENTAL is not set
> # CONFIG_NCP_FS is not set
> # CONFIG_CODA_FS is not set
> # CONFIG_AFS_FS is not set
> # CONFIG_9P_FS is not set
>
> #
> # Partition Types
> #
> CONFIG_PARTITION_ADVANCED=y
> # CONFIG_ACORN_PARTITION is not set
> # CONFIG_OSF_PARTITION is not set
> # CONFIG_AMIGA_PARTITION is not set
> # CONFIG_ATARI_PARTITION is not set
> CONFIG_MAC_PARTITION=y
> CONFIG_MSDOS_PARTITION=y
> # CONFIG_BSD_DISKLABEL is not set
> # CONFIG_MINIX_SUBPARTITION is not set
> # CONFIG_SOLARIS_X86_PARTITION is not set
> # CONFIG_UNIXWARE_DISKLABEL is not set
> CONFIG_LDM_PARTITION=y
> CONFIG_LDM_DEBUG=y
> # CONFIG_SGI_PARTITION is not set
> # CONFIG_ULTRIX_PARTITION is not set
> # CONFIG_SUN_PARTITION is not set
> # CONFIG_KARMA_PARTITION is not set
> CONFIG_EFI_PARTITION=y
> # CONFIG_SYSV68_PARTITION is not set
> CONFIG_NLS=y
> CONFIG_NLS_DEFAULT="utf8"
> CONFIG_NLS_CODEPAGE_437=y
> # CONFIG_NLS_CODEPAGE_737 is not set
> # CONFIG_NLS_CODEPAGE_775 is not set
> # CONFIG_NLS_CODEPAGE_850 is not set
> # CONFIG_NLS_CODEPAGE_852 is not set
> # CONFIG_NLS_CODEPAGE_855 is not set
> # CONFIG_NLS_CODEPAGE_857 is not set
> # CONFIG_NLS_CODEPAGE_860 is not set
> # CONFIG_NLS_CODEPAGE_861 is not set
> # CONFIG_NLS_CODEPAGE_862 is not set
> # CONFIG_NLS_CODEPAGE_863 is not set
> # CONFIG_NLS_CODEPAGE_864 is not set
> # CONFIG_NLS_CODEPAGE_865 is not set
> # CONFIG_NLS_CODEPAGE_866 is not set
> # CONFIG_NLS_CODEPAGE_869 is not set
> # CONFIG_NLS_CODEPAGE_936 is not set
> # CONFIG_NLS_CODEPAGE_950 is not set
> # CONFIG_NLS_CODEPAGE_932 is not set
> # CONFIG_NLS_CODEPAGE_949 is not set
> # CONFIG_NLS_CODEPAGE_874 is not set
> # CONFIG_NLS_ISO8859_8 is not set
> # CONFIG_NLS_CODEPAGE_1250 is not set
> # CONFIG_NLS_CODEPAGE_1251 is not set
> CONFIG_NLS_ASCII=y
> CONFIG_NLS_ISO8859_1=y
> # CONFIG_NLS_ISO8859_2 is not set
> # CONFIG_NLS_ISO8859_3 is not set
> # CONFIG_NLS_ISO8859_4 is not set
> # CONFIG_NLS_ISO8859_5 is not set
> # CONFIG_NLS_ISO8859_6 is not set
> # CONFIG_NLS_ISO8859_7 is not set
> # CONFIG_NLS_ISO8859_9 is not set
> # CONFIG_NLS_ISO8859_13 is not set
> # CONFIG_NLS_ISO8859_14 is not set
> # CONFIG_NLS_ISO8859_15 is not set
> # CONFIG_NLS_KOI8_R is not set
> # CONFIG_NLS_KOI8_U is not set
> CONFIG_NLS_UTF8=y
> CONFIG_DLM=m
> # CONFIG_DLM_DEBUG is not set
>
> #
> # Kernel hacking
> #
> CONFIG_TRACE_IRQFLAGS_SUPPORT=y
> CONFIG_PRINTK_TIME=y
> # CONFIG_ENABLE_WARN_DEPRECATED is not set
> CONFIG_ENABLE_MUST_CHECK=y
> CONFIG_FRAME_WARN=2048
> CONFIG_MAGIC_SYSRQ=y
> # CONFIG_STRIP_ASM_SYMS is not set
> # CONFIG_UNUSED_SYMBOLS is not set
> CONFIG_DEBUG_FS=y
> # CONFIG_HEADERS_CHECK is not set
> CONFIG_DEBUG_KERNEL=y
> CONFIG_DEBUG_SHIRQ=y
> CONFIG_DETECT_SOFTLOCKUP=y
> # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
> CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
> CONFIG_DETECT_HUNG_TASK=y
> # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
> CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
> # CONFIG_SCHED_DEBUG is not set
> CONFIG_SCHEDSTATS=y
> CONFIG_TIMER_STATS=y
> CONFIG_DEBUG_OBJECTS=y
> # CONFIG_DEBUG_OBJECTS_SELFTEST is not set
> CONFIG_DEBUG_OBJECTS_FREE=y
> CONFIG_DEBUG_OBJECTS_TIMERS=y
> CONFIG_DEBUG_OBJECTS_WORK=y
> CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
> CONFIG_SLUB_DEBUG_ON=y
> # CONFIG_SLUB_STATS is not set
> CONFIG_DEBUG_PREEMPT=y
> CONFIG_DEBUG_RT_MUTEXES=y
> CONFIG_DEBUG_PI_LIST=y
> # CONFIG_RT_MUTEX_TESTER is not set
> CONFIG_DEBUG_SPINLOCK=y
> CONFIG_DEBUG_MUTEXES=y
> CONFIG_DEBUG_LOCK_ALLOC=y
> CONFIG_PROVE_LOCKING=y
> CONFIG_PROVE_RCU=y
> CONFIG_LOCKDEP=y
> # CONFIG_LOCK_STAT is not set
> CONFIG_DEBUG_LOCKDEP=y
> CONFIG_TRACE_IRQFLAGS=y
> CONFIG_DEBUG_SPINLOCK_SLEEP=y
> # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
> CONFIG_STACKTRACE=y
> # CONFIG_DEBUG_KOBJECT is not set
> CONFIG_DEBUG_BUGVERBOSE=y
> # CONFIG_DEBUG_INFO is not set
> CONFIG_DEBUG_VM=y
> CONFIG_DEBUG_VIRTUAL=y
> # CONFIG_DEBUG_WRITECOUNT is not set
> CONFIG_DEBUG_MEMORY_INIT=y
> CONFIG_DEBUG_LIST=y
> CONFIG_DEBUG_SG=y
> CONFIG_DEBUG_NOTIFIERS=y
> CONFIG_DEBUG_CREDENTIALS=y
> CONFIG_ARCH_WANT_FRAME_POINTERS=y
> CONFIG_FRAME_POINTER=y
> # CONFIG_BOOT_PRINTK_DELAY is not set
> # CONFIG_RCU_TORTURE_TEST is not set
> CONFIG_RCU_CPU_STALL_DETECTOR=y
> # CONFIG_RCU_CPU_STALL_VERBOSE is not set
> # CONFIG_KPROBES_SANITY_TEST is not set
> # CONFIG_BACKTRACE_SELF_TEST is not set
> # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
> # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
> # CONFIG_LKDTM is not set
> # CONFIG_FAULT_INJECTION is not set
> # CONFIG_LATENCYTOP is not set
> CONFIG_SYSCTL_SYSCALL_CHECK=y
> # CONFIG_DEBUG_PAGEALLOC is not set
> CONFIG_USER_STACKTRACE_SUPPORT=y
> CONFIG_NOP_TRACER=y
> CONFIG_HAVE_FUNCTION_TRACER=y
> CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
> CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
> CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
> CONFIG_HAVE_DYNAMIC_FTRACE=y
> CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
> CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
> CONFIG_RING_BUFFER=y
> CONFIG_EVENT_TRACING=y
> CONFIG_CONTEXT_SWITCH_TRACER=y
> CONFIG_RING_BUFFER_ALLOW_SWAP=y
> CONFIG_TRACING=y
> CONFIG_GENERIC_TRACER=y
> CONFIG_TRACING_SUPPORT=y
> CONFIG_FTRACE=y
> # CONFIG_FUNCTION_TRACER is not set
> # CONFIG_IRQSOFF_TRACER is not set
> # CONFIG_PREEMPT_TRACER is not set
> # CONFIG_SYSPROF_TRACER is not set
> # CONFIG_SCHED_TRACER is not set
> # CONFIG_FTRACE_SYSCALLS is not set
> # CONFIG_BOOT_TRACER is not set
> CONFIG_BRANCH_PROFILE_NONE=y
> # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
> # CONFIG_PROFILE_ALL_BRANCHES is not set
> # CONFIG_KSYM_TRACER is not set
> # CONFIG_STACK_TRACER is not set
> # CONFIG_KMEMTRACE is not set
> # CONFIG_WORKQUEUE_TRACER is not set
> CONFIG_BLK_DEV_IO_TRACE=y
> CONFIG_KPROBE_EVENT=y
> # CONFIG_FTRACE_STARTUP_TEST is not set
> # CONFIG_MMIOTRACE is not set
> # CONFIG_RING_BUFFER_BENCHMARK is not set
> # CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
> # CONFIG_DYNAMIC_DEBUG is not set
> # CONFIG_DMA_API_DEBUG is not set
> # CONFIG_SAMPLES is not set
> CONFIG_HAVE_ARCH_KGDB=y
> # CONFIG_KGDB is not set
> CONFIG_HAVE_ARCH_KMEMCHECK=y
> # CONFIG_STRICT_DEVMEM is not set
> CONFIG_X86_VERBOSE_BOOTUP=y
> CONFIG_EARLY_PRINTK=y
> # CONFIG_EARLY_PRINTK_DBGP is not set
> CONFIG_DEBUG_STACKOVERFLOW=y
> # CONFIG_DEBUG_STACK_USAGE is not set
> # CONFIG_DEBUG_PER_CPU_MAPS is not set
> # CONFIG_X86_PTDUMP is not set
> CONFIG_DEBUG_RODATA=y
> # CONFIG_DEBUG_RODATA_TEST is not set
> CONFIG_DEBUG_NX_TEST=m
> # CONFIG_IOMMU_DEBUG is not set
> # CONFIG_IOMMU_STRESS is not set
> CONFIG_HAVE_MMIOTRACE_SUPPORT=y
> # CONFIG_X86_DECODER_SELFTEST is not set
> CONFIG_IO_DELAY_TYPE_0X80=0
> CONFIG_IO_DELAY_TYPE_0XED=1
> CONFIG_IO_DELAY_TYPE_UDELAY=2
> CONFIG_IO_DELAY_TYPE_NONE=3
> CONFIG_IO_DELAY_0X80=y
> # CONFIG_IO_DELAY_0XED is not set
> # CONFIG_IO_DELAY_UDELAY is not set
> # CONFIG_IO_DELAY_NONE is not set
> CONFIG_DEFAULT_IO_DELAY_TYPE=0
> CONFIG_DEBUG_BOOT_PARAMS=y
> # CONFIG_CPA_DEBUG is not set
> CONFIG_OPTIMIZE_INLINING=y
> CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
>
> #
> # Security options
> #
> CONFIG_KEYS=y
> CONFIG_KEYS_DEBUG_PROC_KEYS=y
> CONFIG_SECURITY=y
> CONFIG_SECURITYFS=y
> CONFIG_SECURITY_NETWORK=y
> # CONFIG_SECURITY_NETWORK_XFRM is not set
> # CONFIG_SECURITY_PATH is not set
> # CONFIG_INTEL_TXT is not set
> CONFIG_LSM_MMAP_MIN_ADDR=65536
> CONFIG_SECURITY_SELINUX=y
> CONFIG_SECURITY_SELINUX_BOOTPARAM=y
> CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
> CONFIG_SECURITY_SELINUX_DISABLE=y
> CONFIG_SECURITY_SELINUX_DEVELOP=y
> CONFIG_SECURITY_SELINUX_AVC_STATS=y
> CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
> # CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
> # CONFIG_SECURITY_SMACK is not set
> # CONFIG_SECURITY_TOMOYO is not set
> # CONFIG_IMA is not set
> CONFIG_DEFAULT_SECURITY_SELINUX=y
> # CONFIG_DEFAULT_SECURITY_SMACK is not set
> # CONFIG_DEFAULT_SECURITY_TOMOYO is not set
> # CONFIG_DEFAULT_SECURITY_DAC is not set
> CONFIG_DEFAULT_SECURITY="selinux"
> CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y
> CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y
> CONFIG_CRYPTO=y
>
> #
> # Crypto core or helper
> #
> CONFIG_CRYPTO_ALGAPI=y
> CONFIG_CRYPTO_ALGAPI2=y
> CONFIG_CRYPTO_AEAD=y
> CONFIG_CRYPTO_AEAD2=y
> CONFIG_CRYPTO_BLKCIPHER=y
> CONFIG_CRYPTO_BLKCIPHER2=y
> CONFIG_CRYPTO_HASH=y
> CONFIG_CRYPTO_HASH2=y
> CONFIG_CRYPTO_RNG2=y
> CONFIG_CRYPTO_PCOMP=y
> CONFIG_CRYPTO_MANAGER=y
> CONFIG_CRYPTO_MANAGER2=y
> # CONFIG_CRYPTO_GF128MUL is not set
> # CONFIG_CRYPTO_NULL is not set
> # CONFIG_CRYPTO_PCRYPT is not set
> CONFIG_CRYPTO_WORKQUEUE=y
> # CONFIG_CRYPTO_CRYPTD is not set
> CONFIG_CRYPTO_AUTHENC=y
> # CONFIG_CRYPTO_TEST is not set
>
> #
> # Authenticated Encryption with Associated Data
> #
> # CONFIG_CRYPTO_CCM is not set
> # CONFIG_CRYPTO_GCM is not set
> # CONFIG_CRYPTO_SEQIV is not set
>
> #
> # Block modes
> #
> CONFIG_CRYPTO_CBC=y
> # CONFIG_CRYPTO_CTR is not set
> # CONFIG_CRYPTO_CTS is not set
> CONFIG_CRYPTO_ECB=y
> # CONFIG_CRYPTO_LRW is not set
> CONFIG_CRYPTO_PCBC=m
> # CONFIG_CRYPTO_XTS is not set
>
> #
> # Hash modes
> #
> CONFIG_CRYPTO_HMAC=y
> # CONFIG_CRYPTO_XCBC is not set
> # CONFIG_CRYPTO_VMAC is not set
>
> #
> # Digest
> #
> CONFIG_CRYPTO_CRC32C=m
> # CONFIG_CRYPTO_CRC32C_INTEL is not set
> # CONFIG_CRYPTO_GHASH is not set
> # CONFIG_CRYPTO_MD4 is not set
> CONFIG_CRYPTO_MD5=y
> # CONFIG_CRYPTO_MICHAEL_MIC is not set
> # CONFIG_CRYPTO_RMD128 is not set
> # CONFIG_CRYPTO_RMD160 is not set
> # CONFIG_CRYPTO_RMD256 is not set
> # CONFIG_CRYPTO_RMD320 is not set
> CONFIG_CRYPTO_SHA1=y
> # CONFIG_CRYPTO_SHA256 is not set
> # CONFIG_CRYPTO_SHA512 is not set
> # CONFIG_CRYPTO_TGR192 is not set
> # CONFIG_CRYPTO_WP512 is not set
> # CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set
>
> #
> # Ciphers
> #
> CONFIG_CRYPTO_AES=y
> # CONFIG_CRYPTO_AES_X86_64 is not set
> # CONFIG_CRYPTO_AES_NI_INTEL is not set
> # CONFIG_CRYPTO_ANUBIS is not set
> CONFIG_CRYPTO_ARC4=y
> # CONFIG_CRYPTO_BLOWFISH is not set
> # CONFIG_CRYPTO_CAMELLIA is not set
> # CONFIG_CRYPTO_CAST5 is not set
> # CONFIG_CRYPTO_CAST6 is not set
> CONFIG_CRYPTO_DES=y
> CONFIG_CRYPTO_FCRYPT=m
> # CONFIG_CRYPTO_KHAZAD is not set
> # CONFIG_CRYPTO_SALSA20 is not set
> # CONFIG_CRYPTO_SALSA20_X86_64 is not set
> # CONFIG_CRYPTO_SEED is not set
> # CONFIG_CRYPTO_SERPENT is not set
> # CONFIG_CRYPTO_TEA is not set
> # CONFIG_CRYPTO_TWOFISH is not set
> # CONFIG_CRYPTO_TWOFISH_X86_64 is not set
>
> #
> # Compression
> #
> CONFIG_CRYPTO_DEFLATE=m
> # CONFIG_CRYPTO_ZLIB is not set
> CONFIG_CRYPTO_LZO=m
>
> #
> # Random Number Generation
> #
> # CONFIG_CRYPTO_ANSI_CPRNG is not set
> CONFIG_CRYPTO_HW=y
> # CONFIG_CRYPTO_DEV_PADLOCK is not set
> # CONFIG_CRYPTO_DEV_HIFN_795X is not set
> CONFIG_HAVE_KVM=y
> CONFIG_VIRTUALIZATION=y
> # CONFIG_KVM is not set
> # CONFIG_VHOST_NET is not set
> # CONFIG_VIRTIO_PCI is not set
> # CONFIG_VIRTIO_BALLOON is not set
> CONFIG_BINARY_PRINTF=y
>
> #
> # Library routines
> #
> CONFIG_BITREVERSE=y
> CONFIG_GENERIC_FIND_FIRST_BIT=y
> CONFIG_GENERIC_FIND_NEXT_BIT=y
> CONFIG_GENERIC_FIND_LAST_BIT=y
> CONFIG_CRC_CCITT=m
> CONFIG_CRC16=y
> CONFIG_CRC_T10DIF=y
> CONFIG_CRC_ITU_T=m
> CONFIG_CRC32=y
> # CONFIG_CRC7 is not set
> CONFIG_LIBCRC32C=m
> CONFIG_ZLIB_INFLATE=y
> CONFIG_ZLIB_DEFLATE=m
> CONFIG_LZO_COMPRESS=m
> CONFIG_LZO_DECOMPRESS=y
> CONFIG_DECOMPRESS_GZIP=y
> CONFIG_DECOMPRESS_BZIP2=y
> CONFIG_DECOMPRESS_LZMA=y
> CONFIG_DECOMPRESS_LZO=y
> CONFIG_REED_SOLOMON=m
> CONFIG_REED_SOLOMON_DEC16=y
> CONFIG_HAS_IOMEM=y
> CONFIG_HAS_IOPORT=y
> CONFIG_HAS_DMA=y
> CONFIG_NLATTR=y
^ permalink raw reply
* Re: [PATCH] forcedeth: Stay in NAPI as long as there's work
From: Joe Perches @ 2010-04-28 17:54 UTC (permalink / raw)
To: Tom Herbert; +Cc: netdev, aabdulla, davem
In-Reply-To: <alpine.DEB.1.00.1004272332350.30235@pokey.mtv.corp.google.com>
On Tue, 2010-04-27 at 23:36 -0700, Tom Herbert wrote:
> Add loop in NAPI poll routine to keep processing RX and TX as long as
> there is more work to do. This is similar to what tg3 and some other
> drivers do.
> Signed-off-by: Tom Herbert <therbert@google.com>
> ---
> diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
> index a1c0e7b..1e4de7b 100644
> --- a/drivers/net/forcedeth.c
> +++ b/drivers/net/forcedeth.c
> @@ -3736,6 +3736,23 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data)
> }
>
> #ifdef CONFIG_FORCEDETH_NAPI
> +static inline int nv_has_work(struct fe_priv *np)
> +{
> + if (nv_optimized(np)) {
> + return (
> + ((np->get_rx.ex != np->put_rx.ex) &&
> + !(le32_to_cpu(np->get_rx.ex->flaglen) & NV_RX2_AVAIL)) ||
> + ((np->get_tx.ex != np->put_tx.ex) &&
> + !(le32_to_cpu(np->get_tx.ex->flaglen) & NV_TX_VALID)));
> + } else {
> + return (
> + ((np->get_rx.orig != np->put_rx.orig) &&
> + !(le32_to_cpu(np->get_rx.orig->flaglen) & NV_RX_AVAIL)) ||
> + ((np->get_tx.orig != np->put_tx.orig) &&
> + !(le32_to_cpu(np->get_tx.orig->flaglen) & NV_TX_VALID)));
> + }
> +}
It might be better to test the comparisons using
a cpu_to_le32 of the constants.
static inline int nv_has_work(struct fe_priv *np)
{
if (nv_optimized(np))
return ((np->get_rx.ex != np->put_rx.ex) &&
!(np->get_rx.ex->flaglen & cpu_to_le32(NV_RX2_AVAIL))) ||
((np->get_tx.ex != np->put_tx.ex) &&
!(np->get_tx.ex->flaglen & cpu_to_le32(NV_TX_VALID)));
return ((np->get_rx.orig != np->put_rx.orig) &&
!(np->get_rx.orig->flaglen & cpu_to_le32(NV_RX_AVAIL))) ||
((np->get_tx.orig != np->put_tx.orig) &&
!(np->get_tx.orig->flaglen & cpu_to_le32(NV_TX_VALID)));
}
^ permalink raw reply
* Re: [PATCH]: sctp: Fix skb_over_panic resulting from multiple invalid parameter errors (CVE-2010-1173)
From: Vlad Yasevich @ 2010-04-28 17:52 UTC (permalink / raw)
To: Neil Horman; +Cc: sri, linux-sctp, eteo, netdev, davem, security
In-Reply-To: <4BD8481E.3010509@hp.com>
Vlad Yasevich wrote:
>
> Neil Horman wrote:
>> On Wed, Apr 28, 2010 at 10:00:37AM -0400, Vlad Yasevich wrote:
>>> I have this patch and a few others already queued.
>>>
>>> I was planning on sending these today for stable.
>>>
>>> Here is the full list of stable patches I have:
>>>
>>> sctp: Fix oops when sending queued ASCONF chunks
>>> sctp: fix to calc the INIT/INIT-ACK chunk length correctly is set
>>> sctp: per_cpu variables should be in bh_disabled section
>>> sctp: fix potential reference of a freed pointer
>>> sctp: avoid irq lock inversion while call sk->sk_data_ready()
>>>
>>> -vlad
>>>
>> Are you sure? this oops looks _very_ simmilar to the INIT/INIT-ACK length
>> calculation oops described above, but is in fact different, and requires this
>> patch, from what I can see. The right fix might be in the ASCONF chunk patch
>> you list above, but I don't see that in your tree at the moment, so I can't be
>> sure.
>
> As I said, I totally goofed when reading the description and I apologize.
> However, I do one comment regarding the patch.
>
> If the bad packet is REALLY long (I mean close to 65K IP limit), then
> we'll end up allocating a supper huge skb in this case and potentially exceed
> the IP length limitation. Section 11.4 of rfc 4960 allows us to omit some
> errors and limit the size of the packet.
>
> I would recommend limiting this to MTU worth of potentiall errors. This is
> on top of what the INIT-ACK is going to carry, so at most we'll sent 2 MTUs
> worth. That's still a potential by amplification attack, but it's somewhat
> mitigated.
>
> Of course now we have to handle the case of checking for space before adding
> an error cause. :)
>
Hi Neil
I am also not crazy about the pre-allocation scheme. In the case where you have
say 100 parameters that are all 'skip' parameters, you'd end up pre-allocating a
huge buffer for absolutely nothing.
This is another point toward a fixed error chunk size and let parameter
processing allocate it when it reaches a parameter that needs an error.
-vlad
> -vlad
>
>> Neil
>>
>>> Neil Horman wrote:
>>>> Hey-
>>>> Recently, it was reported to me that the kernel could oops in the
>>>> following way:
>>>>
>>>> <5> kernel BUG at net/core/skbuff.c:91!
>>>> <5> invalid operand: 0000 [#1]
>>>> <5> Modules linked in: sctp netconsole nls_utf8 autofs4 sunrpc iptable_filter
>>>> ip_tables cpufreq_powersave parport_pc lp parport vmblock(U) vsock(U) vmci(U)
>>>> vmxnet(U) vmmemctl(U) vmhgfs(U) acpiphp dm_mirror dm_mod button battery ac md5
>>>> ipv6 uhci_hcd ehci_hcd snd_ens1371 snd_rawmidi snd_seq_device snd_pcm_oss
>>>> snd_mixer_oss snd_pcm snd_timer snd_page_alloc snd_ac97_codec snd soundcore
>>>> pcnet32 mii floppy ext3 jbd ata_piix libata mptscsih mptsas mptspi mptscsi
>>>> mptbase sd_mod scsi_mod
>>>> <5> CPU: 0
>>>> <5> EIP: 0060:[<c02bff27>] Not tainted VLI
>>>> <5> EFLAGS: 00010216 (2.6.9-89.0.25.EL)
>>>> <5> EIP is at skb_over_panic+0x1f/0x2d
>>>> <5> eax: 0000002c ebx: c033f461 ecx: c0357d96 edx: c040fd44
>>>> <5> esi: c033f461 edi: df653280 ebp: 00000000 esp: c040fd40
>>>> <5> ds: 007b es: 007b ss: 0068
>>>> <5> Process swapper (pid: 0, threadinfo=c040f000 task=c0370be0)
>>>> <5> Stack: c0357d96 e0c29478 00000084 00000004 c033f461 df653280 d7883180
>>>> e0c2947d
>>>> <5> 00000000 00000080 df653490 00000004 de4f1ac0 de4f1ac0 00000004
>>>> df653490
>>>> <5> 00000001 e0c2877a 08000800 de4f1ac0 df653490 00000000 e0c29d2e
>>>> 00000004
>>>> <5> Call Trace:
>>>> <5> [<e0c29478>] sctp_addto_chunk+0xb0/0x128 [sctp]
>>>> <5> [<e0c2947d>] sctp_addto_chunk+0xb5/0x128 [sctp]
>>>> <5> [<e0c2877a>] sctp_init_cause+0x3f/0x47 [sctp]
>>>> <5> [<e0c29d2e>] sctp_process_unk_param+0xac/0xb8 [sctp]
>>>> <5> [<e0c29e90>] sctp_verify_init+0xcc/0x134 [sctp]
>>>> <5> [<e0c20322>] sctp_sf_do_5_1B_init+0x83/0x28e [sctp]
>>>> <5> [<e0c25333>] sctp_do_sm+0x41/0x77 [sctp]
>>>> <5> [<c01555a4>] cache_grow+0x140/0x233
>>>> <5> [<e0c26ba1>] sctp_endpoint_bh_rcv+0xc5/0x108 [sctp]
>>>> <5> [<e0c2b863>] sctp_inq_push+0xe/0x10 [sctp]
>>>> <5> [<e0c34600>] sctp_rcv+0x454/0x509 [sctp]
>>>> <5> [<e084e017>] ipt_hook+0x17/0x1c [iptable_filter]
>>>> <5> [<c02d005e>] nf_iterate+0x40/0x81
>>>> <5> [<c02e0bb9>] ip_local_deliver_finish+0x0/0x151
>>>> <5> [<c02e0c7f>] ip_local_deliver_finish+0xc6/0x151
>>>> <5> [<c02d0362>] nf_hook_slow+0x83/0xb5
>>>> <5> [<c02e0bb2>] ip_local_deliver+0x1a2/0x1a9
>>>> <5> [<c02e0bb9>] ip_local_deliver_finish+0x0/0x151
>>>> <5> [<c02e103e>] ip_rcv+0x334/0x3b4
>>>> <5> [<c02c66fd>] netif_receive_skb+0x320/0x35b
>>>> <5> [<e0a0928b>] init_stall_timer+0x67/0x6a [uhci_hcd]
>>>> <5> [<c02c67a4>] process_backlog+0x6c/0xd9
>>>> <5> [<c02c690f>] net_rx_action+0xfe/0x1f8
>>>> <5> [<c012a7b1>] __do_softirq+0x35/0x79
>>>> <5> [<c0107efb>] handle_IRQ_event+0x0/0x4f
>>>> <5> [<c01094de>] do_softirq+0x46/0x4d
>>>>
>>>> Its an skb_over_panic BUG halt that results from processing an init chunk in
>>>> which too many of its variable length parameters are in some way malformed.
>>>>
>>>> The problem is in sctp_process_unk_param:
>>>> if (NULL == *errp)
>>>> *errp = sctp_make_op_error_space(asoc, chunk,
>>>> ntohs(chunk->chunk_hdr->length));
>>>>
>>>> if (*errp) {
>>>> sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
>>>> WORD_ROUND(ntohs(param.p->length)));
>>>> sctp_addto_chunk(*errp,
>>>> WORD_ROUND(ntohs(param.p->length)),
>>>> param.v);
>>>>
>>>> When we allocate an error chunk, we assume that the worst case scenario requires
>>>> that we have chunk_hdr->length data allocated, which would be correct nominally,
>>>> given that we call sctp_addto_chunk for the violating parameter. Unfortunately,
>>>> we also, in sctp_init_cause insert a sctp_errhdr_t structure into the error
>>>> chunk, so the worst case situation in which all parameters are in violation
>>>> requires chunk_hdr->length+(sizeof(sctp_errhdr_t)*param_count) bytes of data.
>>>>
>>>> The result of this error is that a deliberately malformed packet sent to a
>>>> listening host can cause a remote DOS, described in CVE-2010-1173:
>>>> http://cve.mitre.org/cgi-bin/cvename.cgi?name=2010-1173
>>>>
>>>> I've tested the below fix and confirmed that it fixes the issue. It
>>>> pre-allocates the error chunk in sctp_verify_init, where we are able to count
>>>> the total number of variable length parameters, so we know how many error
>>>> headers we might need. Then we simply use that chunk, if we find an error, or
>>>> discard/free it if all the parameters are valid. Applies on top of the
>>>> lksctp-dev tree
>>>>
>>>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
>>>>
>>>>
>>>> sm_make_chunk.c | 24 ++++++++++++++++++++++--
>>>> 1 file changed, 22 insertions(+), 2 deletions(-)
>>>>
>>>>
>>>> diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
>>>> index f592163..990457b 100644
>>>> --- a/net/sctp/sm_make_chunk.c
>>>> +++ b/net/sctp/sm_make_chunk.c
>>>> @@ -2134,6 +2134,8 @@ int sctp_verify_init(const struct sctp_association *asoc,
>>>> union sctp_params param;
>>>> int has_cookie = 0;
>>>> int result;
>>>> + unsigned int param_cnt;
>>>> + unsigned int len;
>>>>
>>>> /* Verify stream values are non-zero. */
>>>> if ((0 == peer_init->init_hdr.num_outbound_streams) ||
>>>> @@ -2149,6 +2151,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
>>>>
>>>> if (SCTP_PARAM_STATE_COOKIE == param.p->type)
>>>> has_cookie = 1;
>>>> + param_cnt++;
>>>>
>>>> } /* for (loop through all parameters) */
>>>>
>>>> @@ -2169,6 +2172,20 @@ int sctp_verify_init(const struct sctp_association *asoc,
>>>> return sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,
>>>> chunk, errp);
>>>>
>>>> + if (!*errp) {
>>>> + /*
>>>> + * Pre-allocate the error packet here
>>>> + * we do this as we need to reserve space
>>>> + * for the worst case scenario in which
>>>> + * every parameter is in error and needs
>>>> + * an errhdr attached to it
>>>> + */
>>>> + len = ntohs(chunk->chunk_hdr->length);
>>>> + len += sizeof(sctp_errhdr_t)*param_cnt;
>>>> +
>>>> + *errp = sctp_make_op_error_space(asoc, chunk, len);
>>>> + }
>>>> +
>>>> /* Verify all the variable length parameters */
>>>> sctp_walk_params(param, peer_init, init_hdr.params) {
>>>>
>>>> @@ -2176,9 +2193,11 @@ int sctp_verify_init(const struct sctp_association *asoc,
>>>> switch (result) {
>>>> case SCTP_IERROR_ABORT:
>>>> case SCTP_IERROR_NOMEM:
>>>> - return 0;
>>>> case SCTP_IERROR_ERROR:
>>>> - return 1;
>>>> + len = ntohs((*errp)->chunk_hdr->length);
>>>> + if ((*errp) && (len == sizeof(sctp_chunkhdr_t)))
>>>> + sctp_chunk_free(*errp);
>>>> + return (result == SCTP_IERROR_ERROR) ? 1 : 0;
>>>> case SCTP_IERROR_NO_ERROR:
>>>> default:
>>>> break;
>>>> @@ -2186,6 +2205,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
>>>>
>>>> } /* for (loop through all parameters) */
>>>>
>>>> + sctp_chunk_free(*errp);
>>>> return 1;
>>>> }
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox