aboutsummaryrefslogtreecommitdiff
path: root/net/caif/chnl_net.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/caif/chnl_net.c')
-rw-r--r--net/caif/chnl_net.c62
1 files changed, 35 insertions, 27 deletions
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
index 865690948bb..4589ff67bfa 100644
--- a/net/caif/chnl_net.c
+++ b/net/caif/chnl_net.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) ST-Ericsson AB 2010
- * Authors: Sjur Brendeland/sjur.brandeland@stericsson.com
- * Daniel Martensson / Daniel.Martensson@stericsson.com
+ * Authors: Sjur Brendeland
+ * Daniel Martensson
* License terms: GNU General Public License (GPL) version 2
*/
@@ -28,6 +28,7 @@
/* 5 sec. connect timeout */
#define CONNECT_TIMEOUT (5 * HZ)
#define CAIF_NET_DEFAULT_QUEUE_LEN 500
+#define UNDEF_CONNID 0xffffffff
/*This list is protected by the rtnl lock. */
static LIST_HEAD(chnl_net_list);
@@ -72,14 +73,12 @@ static void robust_list_del(struct list_head *delete_node)
static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)
{
struct sk_buff *skb;
- struct chnl_net *priv = container_of(layr, struct chnl_net, chnl);
+ struct chnl_net *priv;
int pktlen;
- int err = 0;
const u8 *ip_version;
u8 buf;
priv = container_of(layr, struct chnl_net, chnl);
-
if (!priv)
return -EINVAL;
@@ -95,8 +94,11 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)
/* check the version of IP */
ip_version = skb_header_pointer(skb, 0, 1, &buf);
- if (!ip_version)
+ if (!ip_version) {
+ kfree_skb(skb);
return -EINVAL;
+ }
+
switch (*ip_version >> 4) {
case 4:
skb->protocol = htons(ETH_P_IP);
@@ -105,6 +107,8 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)
skb->protocol = htons(ETH_P_IPV6);
break;
default:
+ kfree_skb(skb);
+ priv->netdev->stats.rx_errors++;
return -EINVAL;
}
@@ -123,7 +127,7 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)
priv->netdev->stats.rx_packets++;
priv->netdev->stats.rx_bytes += pktlen;
- return err;
+ return 0;
}
static int delete_device(struct chnl_net *dev)
@@ -163,7 +167,7 @@ static void chnl_put(struct cflayer *lyr)
}
static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow,
- int phyid)
+ int phyid)
{
struct chnl_net *priv = container_of(layr, struct chnl_net, chnl);
pr_debug("NET flowctrl func called flow: %s\n",
@@ -221,12 +225,16 @@ static int chnl_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->len > priv->netdev->mtu) {
pr_warn("Size of skb exceeded MTU\n");
- return -ENOSPC;
+ kfree_skb(skb);
+ dev->stats.tx_errors++;
+ return NETDEV_TX_OK;
}
if (!priv->flowenabled) {
pr_debug("dropping packets flow off\n");
- return NETDEV_TX_BUSY;
+ kfree_skb(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
}
if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP)
@@ -240,9 +248,8 @@ static int chnl_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Send the packet down the stack. */
result = priv->chnl.dn->transmit(priv->chnl.dn, pkt);
if (result) {
- if (result == -EAGAIN)
- result = NETDEV_TX_BUSY;
- return result;
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
}
/* Update statistics. */
@@ -278,7 +285,7 @@ static int chnl_net_open(struct net_device *dev)
goto error;
}
- lldev = dev_get_by_index(dev_net(dev), llifindex);
+ lldev = __dev_get_by_index(dev_net(dev), llifindex);
if (lldev == NULL) {
pr_debug("no interface?\n");
@@ -300,7 +307,6 @@ static int chnl_net_open(struct net_device *dev)
mtu = min_t(int, dev->mtu, lldev->mtu - (headroom + tailroom));
mtu = min_t(int, GPRS_PDP_MTU, mtu);
dev_set_mtu(dev, mtu);
- dev_put(lldev);
if (mtu < 100) {
pr_warn("CAIF Interface MTU too small (%d)\n", mtu);
@@ -409,7 +415,7 @@ static void ipcaif_net_setup(struct net_device *dev)
priv->conn_req.link_selector = CAIF_LINK_HIGH_BANDW;
priv->conn_req.priority = CAIF_PRIO_LOW;
/* Insert illegal value */
- priv->conn_req.sockaddr.u.dgm.connection_id = 0;
+ priv->conn_req.sockaddr.u.dgm.connection_id = UNDEF_CONNID;
priv->flowenabled = false;
init_waitqueue_head(&priv->netmgmt_wq);
@@ -421,14 +427,14 @@ static int ipcaif_fill_info(struct sk_buff *skb, const struct net_device *dev)
struct chnl_net *priv;
u8 loop;
priv = netdev_priv(dev);
- NLA_PUT_U32(skb, IFLA_CAIF_IPV4_CONNID,
- priv->conn_req.sockaddr.u.dgm.connection_id);
- NLA_PUT_U32(skb, IFLA_CAIF_IPV6_CONNID,
- priv->conn_req.sockaddr.u.dgm.connection_id);
+ if (nla_put_u32(skb, IFLA_CAIF_IPV4_CONNID,
+ priv->conn_req.sockaddr.u.dgm.connection_id) ||
+ nla_put_u32(skb, IFLA_CAIF_IPV6_CONNID,
+ priv->conn_req.sockaddr.u.dgm.connection_id))
+ goto nla_put_failure;
loop = priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP;
- NLA_PUT_U8(skb, IFLA_CAIF_LOOPBACK, loop);
-
-
+ if (nla_put_u8(skb, IFLA_CAIF_LOOPBACK, loop))
+ goto nla_put_failure;
return 0;
nla_put_failure:
return -EMSGSIZE;
@@ -436,7 +442,7 @@ nla_put_failure:
}
static void caif_netlink_parms(struct nlattr *data[],
- struct caif_connect_request *conn_req)
+ struct caif_connect_request *conn_req)
{
if (!data) {
pr_warn("no params data found\n");
@@ -472,14 +478,16 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev,
else
list_add(&caifdev->list_field, &chnl_net_list);
- /* Take ifindex as connection-id if null */
- if (caifdev->conn_req.sockaddr.u.dgm.connection_id == 0)
+ /* Use ifindex as connection id, and use loopback channel default. */
+ if (caifdev->conn_req.sockaddr.u.dgm.connection_id == UNDEF_CONNID) {
caifdev->conn_req.sockaddr.u.dgm.connection_id = dev->ifindex;
+ caifdev->conn_req.protocol = CAIFPROTO_DATAGRAM_LOOP;
+ }
return ret;
}
static int ipcaif_changelink(struct net_device *dev, struct nlattr *tb[],
- struct nlattr *data[])
+ struct nlattr *data[])
{
struct chnl_net *caifdev;
ASSERT_RTNL();