diff options
Diffstat (limited to 'net/caif/chnl_net.c')
| -rw-r--r-- | net/caif/chnl_net.c | 62 |
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(); |
