Netdev List
 help / color / mirror / Atom feed
* [PATCH v6 BONUS 4/3] ipv4: Store rtable entries directly in FIB
From: David Miller @ 2011-05-05 23:36 UTC (permalink / raw)
  To: netdev; +Cc: tgraf, jpirko, herbert, eric.dumazet


Ok, here is the fun patch showing the scheme I'm working on.  Two
things going on here.

First, we store pre-constructed rtable entries, on demand, inside of
the routing table objects themselves.

Second, we get rid of RT_TABLE_LOCAL and load all routes equally
into RT_TABLE_MAIN.

Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 10422ef..f3c9598 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -44,6 +44,7 @@ struct fib_config {
  };
 
 struct fib_info;
+struct rtable;
 
 struct fib_nh {
 	struct net_device	*nh_dev;
@@ -62,6 +63,7 @@ struct fib_nh {
 	__be32			nh_gw;
 	__be32			nh_saddr;
 	int			nh_saddr_genid;
+	struct rtable		*nh_rtable;
 };
 
 /*
@@ -200,10 +202,6 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
 {
 	struct fib_table *table;
 
-	table = fib_get_table(net, RT_TABLE_LOCAL);
-	if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
-		return 0;
-
 	table = fib_get_table(net, RT_TABLE_MAIN);
 	if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
 		return 0;
diff --git a/include/net/route.h b/include/net/route.h
index 70155fb..04e7197 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -109,6 +109,7 @@ extern int		ip_rt_init(void);
 extern void		ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw,
 				       __be32 src, struct net_device *dev);
 extern void		rt_cache_flush(struct net *net, int how);
+extern struct rtable *ip_route_output_new(struct net *, struct flowi4 *flp);
 extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp);
 extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
 					   struct sock *sk);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 33bbbda..24e67d8 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -155,7 +155,7 @@ static inline unsigned __inet_dev_addr_type(struct net *net,
 	res.r = NULL;
 #endif
 
-	local_table = fib_get_table(net, RT_TABLE_LOCAL);
+	local_table = fib_get_table(net, RT_TABLE_MAIN);
 	if (local_table) {
 		ret = RTN_UNICAST;
 		rcu_read_lock();
@@ -662,11 +662,7 @@ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifad
 		},
 	};
 
-	if (type == RTN_UNICAST)
-		tb = fib_new_table(net, RT_TABLE_MAIN);
-	else
-		tb = fib_new_table(net, RT_TABLE_LOCAL);
-
+	tb = fib_new_table(net, RT_TABLE_MAIN);
 	if (tb == NULL)
 		return;
 
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 641a5a2..c37ebd3 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -148,6 +148,10 @@ static void free_fib_info_rcu(struct rcu_head *head)
 {
 	struct fib_info *fi = container_of(head, struct fib_info, rcu);
 
+	change_nexthops(fi) {
+		ip_rt_put(nexthop_nh->nh_rtable);
+		nexthop_nh->nh_rtable = NULL;
+	} endfor_nexthops(fi);
 	if (fi->fib_metrics != (u32 *) dst_default_metrics)
 		kfree(fi->fib_metrics);
 	kfree(fi);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 1e67624..2f77d28 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1861,6 +1861,68 @@ out:
 }
 EXPORT_SYMBOL_GPL(__ip_route_output_key);
 
+struct rtable *ip_route_output_new(struct net *net, struct flowi4 *fl4)
+{
+	struct net_device *dev_out = NULL;
+	u32 tos	= RT_FL_TOS(fl4);
+	unsigned int flags = 0;
+	struct fib_result res;
+	struct rtable *rth;
+	int orig_oif;
+
+	res.fi = NULL;
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+	res.r = NULL;
+#endif
+
+	orig_oif = fl4->flowi4_oif;
+
+	fl4->flowi4_iif = net->loopback_dev->ifindex;
+	fl4->flowi4_tos = tos & IPTOS_RT_MASK;
+	fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
+			 RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
+
+	rcu_read_lock();
+	if (fib_lookup(net, fl4, &res)) {
+		rth = ERR_PTR(-ENETUNREACH);
+		goto out;
+	}
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+	if (res.fi->fib_nhs > 1 && fl4->flowi4_oif == 0)
+		fib_select_multipath(&res);
+	else
+#endif
+	if (!res.prefixlen && res.table->tb_num_default > 1 &&
+	    res.type == RTN_UNICAST && !fl4->flowi4_oif)
+		fib_select_default(&res);
+
+	if (!fl4->saddr)
+		fl4->saddr = FIB_RES_PREFSRC(net, res);
+
+	dev_out = FIB_RES_DEV(res);
+	fl4->flowi4_oif = dev_out->ifindex;
+
+	rth = FIB_RES_NH(res).nh_rtable;
+	if (!rth) {
+		if (res.type == RTN_LOCAL)
+			flags |= RTCF_LOCAL;
+		rth = __mkroute_output(&res, fl4, orig_oif, dev_out, flags);
+		if (!IS_ERR(rth))
+			rth = rt_finalize(rth, NULL);
+		if (!IS_ERR(rth))
+			FIB_RES_NH(res).nh_rtable = rth;
+	}
+
+	if (!IS_ERR(rth))
+		atomic_inc(&rth->dst.__refcnt);
+
+out:
+	rcu_read_unlock();
+	return rth;
+}
+EXPORT_SYMBOL_GPL(ip_route_output_new);
+
 static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie)
 {
 	return NULL;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 544f435..9bb827e 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -929,7 +929,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 				   faddr, saddr, dport, inet->inet_sport);
 
 		security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
-		rt = ip_route_output_flow(net, &fl4, sk);
+		rt = ip_route_output_new(net, &fl4);
 		if (IS_ERR(rt)) {
 			err = PTR_ERR(rt);
 			rt = NULL;

^ permalink raw reply related

* [PATCH v6 3/3] ipv4: Remove rt_key_{src,dst,tos} from struct rtable.
From: David Miller @ 2011-05-05 23:36 UTC (permalink / raw)
  To: netdev; +Cc: tgraf, jpirko, herbert, eric.dumazet


They are always used in contexts where they can be reconstituted,
or where the finally resolved rt->rt_{src,dst} is semantically
equivalent.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/route.h     |    7 +-----
 net/ipv4/ip_options.c   |   10 ++++----
 net/ipv4/route.c        |   49 +++++++++++++---------------------------------
 net/ipv4/xfrm4_policy.c |    3 --
 4 files changed, 20 insertions(+), 49 deletions(-)

diff --git a/include/net/route.h b/include/net/route.h
index ef20edc..70155fb 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -45,14 +45,9 @@ struct fib_info;
 struct rtable {
 	struct dst_entry	dst;
 
-	/* Lookup key. */
-	__be32			rt_key_dst;
-	__be32			rt_key_src;
-
 	int			rt_genid;
 	unsigned		rt_flags;
 	__u16			rt_type;
-	__u8			rt_key_tos;
 
 	__be32			rt_dst;	/* Path destination	*/
 	__be32			rt_src;	/* Path source		*/
@@ -176,7 +171,7 @@ extern unsigned		inet_addr_type(struct net *net, __be32 addr);
 extern unsigned		inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr);
 extern void		ip_rt_multicast_event(struct in_device *);
 extern int		ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg);
-extern void		ip_rt_get_source(u8 *src, struct rtable *rt);
+extern void		ip_rt_get_source(struct iphdr *iph, u8 *src, struct rtable *rt);
 extern int		ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb);
 
 struct in_ifaddr;
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 01fc409..4dc0f22 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -50,9 +50,9 @@ void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
 
 	if (!is_frag) {
 		if (opt->rr_needaddr)
-			ip_rt_get_source(iph+opt->rr+iph[opt->rr+2]-5, rt);
+			ip_rt_get_source(ip_hdr(skb), iph+opt->rr+iph[opt->rr+2]-5, rt);
 		if (opt->ts_needaddr)
-			ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, rt);
+			ip_rt_get_source(ip_hdr(skb), iph+opt->ts+iph[opt->ts+2]-9, rt);
 		if (opt->ts_needtime) {
 			struct timespec tv;
 			__be32 midtime;
@@ -553,7 +553,7 @@ void ip_forward_options(struct sk_buff *skb)
 
 	if (opt->rr_needaddr) {
 		optptr = (unsigned char *)raw + opt->rr;
-		ip_rt_get_source(&optptr[optptr[2]-5], rt);
+		ip_rt_get_source(ip_hdr(skb), &optptr[optptr[2]-5], rt);
 		opt->is_changed = 1;
 	}
 	if (opt->srr_is_hit) {
@@ -572,14 +572,14 @@ void ip_forward_options(struct sk_buff *skb)
 		}
 		if (srrptr + 3 <= srrspace) {
 			opt->is_changed = 1;
-			ip_rt_get_source(&optptr[srrptr-1], rt);
+			ip_rt_get_source(ip_hdr(skb), &optptr[srrptr-1], rt);
 			ip_hdr(skb)->daddr = rt->rt_dst;
 			optptr[2] = srrptr+4;
 		} else if (net_ratelimit())
 			printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n");
 		if (opt->ts_needaddr) {
 			optptr = raw + opt->ts;
-			ip_rt_get_source(&optptr[optptr[2]-9], rt);
+			ip_rt_get_source(ip_hdr(skb), &optptr[optptr[2]-9], rt);
 			opt->is_changed = 1;
 		}
 	}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index be5976a..1e67624 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -628,8 +628,8 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
 			ret = NULL;
 		} else if (rt->rt_flags & RTCF_REDIRECTED) {
 #if RT_CACHE_DEBUG >= 1
-			printk(KERN_DEBUG "ipv4_negative_advice: redirect to %pI4/%02x dropped\n",
-			       &rt->rt_dst, rt->rt_key_tos);
+			printk(KERN_DEBUG "ipv4_negative_advice: redirect to %pI4 dropped\n",
+			       &rt->rt_dst);
 #endif
 			ip_rt_put(rt);
 			ret = NULL;
@@ -979,7 +979,7 @@ static int ip_rt_bug(struct sk_buff *skb)
    in IP options!
  */
 
-void ip_rt_get_source(u8 *addr, struct rtable *rt)
+void ip_rt_get_source(struct iphdr *iph, u8 *addr, struct rtable *rt)
 {
 	__be32 src;
 	struct fib_result res;
@@ -988,9 +988,9 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt)
 		src = rt->rt_src;
 	else {
 		struct flowi4 fl4 = {
-			.daddr = rt->rt_key_dst,
-			.saddr = rt->rt_key_src,
-			.flowi4_tos = rt->rt_key_tos,
+			.daddr = rt->rt_dst,
+			.saddr = rt->rt_src,
+			.flowi4_tos = iph->tos,
 			.flowi4_oif = rt->rt_oif,
 			.flowi4_iif = rt->rt_iif,
 			.flowi4_mark = rt->rt_mark,
@@ -1160,12 +1160,9 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 #endif
 	rth->dst.output = ip_rt_bug;
 
-	rth->rt_key_dst	= daddr;
-	rth->rt_key_src	= saddr;
 	rth->rt_genid	= rt_genid(dev_net(dev));
 	rth->rt_flags	= RTCF_MULTICAST;
 	rth->rt_type	= RTN_MULTICAST;
-	rth->rt_key_tos	= tos;
 	rth->rt_dst	= daddr;
 	rth->rt_src	= saddr;
 	rth->rt_route_iif = dev->ifindex;
@@ -1296,12 +1293,9 @@ static int __mkroute_input(struct sk_buff *skb,
 		goto cleanup;
 	}
 
-	rth->rt_key_dst	= daddr;
-	rth->rt_key_src	= saddr;
 	rth->rt_genid = rt_genid(dev_net(rth->dst.dev));
 	rth->rt_flags = flags;
 	rth->rt_type = res->type;
-	rth->rt_key_tos	= tos;
 	rth->rt_dst	= daddr;
 	rth->rt_src	= saddr;
 	rth->rt_route_iif = in_dev->dev->ifindex;
@@ -1471,12 +1465,9 @@ local_input:
 	rth->dst.tclassid = itag;
 #endif
 
-	rth->rt_key_dst	= daddr;
-	rth->rt_key_src	= saddr;
 	rth->rt_genid = rt_genid(net);
 	rth->rt_flags 	= flags|RTCF_LOCAL;
 	rth->rt_type	= res.type;
-	rth->rt_key_tos	= tos;
 	rth->rt_dst	= daddr;
 	rth->rt_src	= saddr;
 #ifdef CONFIG_IP_ROUTE_CLASSID
@@ -1589,12 +1580,10 @@ EXPORT_SYMBOL(ip_route_input);
 /* called with rcu_read_lock() */
 static struct rtable *__mkroute_output(const struct fib_result *res,
 				       const struct flowi4 *fl4,
-				       __be32 orig_daddr, __be32 orig_saddr,
 				       int orig_oif, struct net_device *dev_out,
 				       unsigned int flags)
 {
 	struct fib_info *fi = res->fi;
-	u32 tos = RT_FL_TOS(fl4);
 	struct in_device *in_dev;
 	u16 type = res->type;
 	struct rtable *rth;
@@ -1640,12 +1629,9 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
 
 	rth->dst.output = ip_output;
 
-	rth->rt_key_dst	= orig_daddr;
-	rth->rt_key_src	= orig_saddr;
 	rth->rt_genid = rt_genid(dev_net(dev_out));
 	rth->rt_flags	= flags;
 	rth->rt_type	= type;
-	rth->rt_key_tos	= tos;
 	rth->rt_dst	= fl4->daddr;
 	rth->rt_src	= fl4->saddr;
 	rth->rt_route_iif = 0;
@@ -1698,8 +1684,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 	unsigned int flags = 0;
 	struct fib_result res;
 	struct rtable *rth;
-	__be32 orig_daddr;
-	__be32 orig_saddr;
 	int orig_oif;
 
 	res.fi		= NULL;
@@ -1707,8 +1691,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 	res.r		= NULL;
 #endif
 
-	orig_daddr = fl4->daddr;
-	orig_saddr = fl4->saddr;
 	orig_oif = fl4->flowi4_oif;
 
 	fl4->flowi4_iif = net->loopback_dev->ifindex;
@@ -1869,8 +1851,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 
 
 make_route:
-	rth = __mkroute_output(&res, fl4, orig_daddr, orig_saddr, orig_oif,
-			       dev_out, flags);
+	rth = __mkroute_output(&res, fl4, orig_oif, dev_out, flags);
 	if (!IS_ERR(rth))
 		rth = rt_finalize(rth, NULL);
 
@@ -1928,9 +1909,6 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
 		if (new->dev)
 			dev_hold(new->dev);
 
-		rt->rt_key_dst = ort->rt_key_dst;
-		rt->rt_key_src = ort->rt_key_src;
-		rt->rt_key_tos = ort->rt_key_tos;
 		rt->rt_route_iif = ort->rt_route_iif;
 		rt->rt_iif = ort->rt_iif;
 		rt->rt_oif = ort->rt_oif;
@@ -1975,7 +1953,7 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4,
 }
 EXPORT_SYMBOL_GPL(ip_route_output_flow);
 
-static int rt_fill_info(struct net *net,
+static int rt_fill_info(struct net *net,  __be32 src, u8 tos,
 			struct sk_buff *skb, u32 pid, u32 seq, int event,
 			int nowait, unsigned int flags)
 {
@@ -1993,7 +1971,7 @@ static int rt_fill_info(struct net *net,
 	r->rtm_family	 = AF_INET;
 	r->rtm_dst_len	= 32;
 	r->rtm_src_len	= 0;
-	r->rtm_tos	= rt->rt_key_tos;
+	r->rtm_tos	= tos;
 	r->rtm_table	= RT_TABLE_MAIN;
 	NLA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
 	r->rtm_type	= rt->rt_type;
@@ -2005,9 +1983,9 @@ static int rt_fill_info(struct net *net,
 
 	NLA_PUT_BE32(skb, RTA_DST, rt->rt_dst);
 
-	if (rt->rt_key_src) {
+	if (src) {
 		r->rtm_src_len = 32;
-		NLA_PUT_BE32(skb, RTA_SRC, rt->rt_key_src);
+		NLA_PUT_BE32(skb, RTA_SRC, src);
 	}
 	if (rt->dst.dev)
 		NLA_PUT_U32(skb, RTA_OIF, rt->dst.dev->ifindex);
@@ -2017,7 +1995,7 @@ static int rt_fill_info(struct net *net,
 #endif
 	if (rt_is_input_route(rt))
 		NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst);
-	else if (rt->rt_src != rt->rt_key_src)
+	else if (rt->rt_src != src)
 		NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_src);
 
 	if (rt->rt_dst != rt->rt_gateway)
@@ -2158,7 +2136,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
 	if (rtm->rtm_flags & RTM_F_NOTIFY)
 		rt->rt_flags |= RTCF_NOTIFY;
 
-	err = rt_fill_info(net, skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
+	err = rt_fill_info(net, src, rtm->rtm_tos, skb,
+			   NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
 			   RTM_NEWROUTE, 0, 0);
 	if (err <= 0)
 		goto errout_free;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 7ff973b..bfe3d50 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -71,9 +71,6 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
 	struct rtable *rt = (struct rtable *)xdst->route;
 	const struct flowi4 *fl4 = &fl->u.ip4;
 
-	rt->rt_key_dst = fl4->daddr;
-	rt->rt_key_src = fl4->saddr;
-	rt->rt_key_tos = fl4->flowi4_tos;
 	rt->rt_route_iif = fl4->flowi4_iif;
 	rt->rt_iif = fl4->flowi4_iif;
 	rt->rt_oif = fl4->flowi4_oif;
-- 
1.7.5.1


^ permalink raw reply related

* [PATCH v6 2/3] ipv4: Kill ip_route_input_noref().
From: David Miller @ 2011-05-05 23:36 UTC (permalink / raw)
  To: netdev; +Cc: tgraf, jpirko, herbert, eric.dumazet


The "noref" argument to ip_route_input_common() is now always ignored
because we do not cache routes, and in that case we must always grab
a reference to the resulting 'dst'.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/route.h    |   16 ++--------------
 net/ipv4/arp.c         |    2 +-
 net/ipv4/ip_fragment.c |    4 ++--
 net/ipv4/ip_input.c    |    4 ++--
 net/ipv4/route.c       |    6 +++---
 net/ipv4/xfrm4_input.c |    4 ++--
 6 files changed, 12 insertions(+), 24 deletions(-)

diff --git a/include/net/route.h b/include/net/route.h
index f6d7673..ef20edc 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -165,20 +165,8 @@ static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4
 	return ip_route_output_key(net, fl4);
 }
 
-extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src,
-				 u8 tos, struct net_device *devin, bool noref);
-
-static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src,
-				 u8 tos, struct net_device *devin)
-{
-	return ip_route_input_common(skb, dst, src, tos, devin, false);
-}
-
-static inline int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src,
-				       u8 tos, struct net_device *devin)
-{
-	return ip_route_input_common(skb, dst, src, tos, devin, true);
-}
+extern int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src,
+			  u8 tos, struct net_device *devin);
 
 extern unsigned short	ip_rt_frag_needed(struct net *net, const struct iphdr *iph,
 					  unsigned short new_mtu, struct net_device *dev);
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 1b74d3b..ef44a91 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -875,7 +875,7 @@ static int arp_process(struct sk_buff *skb)
 	}
 
 	if (arp->ar_op == htons(ARPOP_REQUEST) &&
-	    ip_route_input_noref(skb, tip, sip, 0, dev) == 0) {
+	    ip_route_input(skb, tip, sip, 0, dev) == 0) {
 
 		rt = skb_rtable(skb);
 		addr_type = rt->rt_type;
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index b1d282f..ebe8bd3 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -234,8 +234,8 @@ static void ip_expire(unsigned long arg)
 		/* skb dst is stale, drop it, and perform route lookup again */
 		skb_dst_drop(head);
 		iph = ip_hdr(head);
-		err = ip_route_input_noref(head, iph->daddr, iph->saddr,
-					   iph->tos, head->dev);
+		err = ip_route_input(head, iph->daddr, iph->saddr,
+				     iph->tos, head->dev);
 		if (err)
 			goto out_rcu_unlock;
 
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index c8f48ef..c21ff9b 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -324,8 +324,8 @@ static int ip_rcv_finish(struct sk_buff *skb)
 	 *	how the packet travels inside Linux networking.
 	 */
 	if (skb_dst(skb) == NULL) {
-		int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
-					       iph->tos, skb->dev);
+		int err = ip_route_input(skb, iph->daddr, iph->saddr,
+					 iph->tos, skb->dev);
 		if (unlikely(err)) {
 			if (err == -EHOSTUNREACH)
 				IP_INC_STATS_BH(dev_net(skb->dev),
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index f3f4037..be5976a 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1540,8 +1540,8 @@ martian_source_keep_err:
 	goto out;
 }
 
-int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,
-			   u8 tos, struct net_device *dev, bool noref)
+int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+		   u8 tos, struct net_device *dev)
 {
 	int res;
 
@@ -1584,7 +1584,7 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	rcu_read_unlock();
 	return res;
 }
-EXPORT_SYMBOL(ip_route_input_common);
+EXPORT_SYMBOL(ip_route_input);
 
 /* called with rcu_read_lock() */
 static struct rtable *__mkroute_output(const struct fib_result *res,
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 06814b6..58d23a5 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -27,8 +27,8 @@ static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb)
 	if (skb_dst(skb) == NULL) {
 		const struct iphdr *iph = ip_hdr(skb);
 
-		if (ip_route_input_noref(skb, iph->daddr, iph->saddr,
-					 iph->tos, skb->dev))
+		if (ip_route_input(skb, iph->daddr, iph->saddr,
+				   iph->tos, skb->dev))
 			goto drop;
 	}
 	return dst_input(skb);
-- 
1.7.5.1


^ permalink raw reply related

* [PATCH v6 1/3] ipv4: Delete routing cache.
From: David Miller @ 2011-05-05 23:36 UTC (permalink / raw)
  To: netdev; +Cc: tgraf, jpirko, herbert, eric.dumazet


Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/route.h     |    1 -
 net/ipv4/fib_frontend.c |    5 -
 net/ipv4/route.c        |  910 +---------------------------------------------
 3 files changed, 20 insertions(+), 896 deletions(-)

diff --git a/include/net/route.h b/include/net/route.h
index 9f8070b..f6d7673 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -114,7 +114,6 @@ extern int		ip_rt_init(void);
 extern void		ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw,
 				       __be32 src, struct net_device *dev);
 extern void		rt_cache_flush(struct net *net, int how);
-extern void		rt_cache_flush_batch(struct net *net);
 extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp);
 extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
 					   struct sock *sk);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 2252471..33bbbda 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -1022,11 +1022,6 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
 		rt_cache_flush(dev_net(dev), 0);
 		break;
 	case NETDEV_UNREGISTER_BATCH:
-		/* The batch unregister is only called on the first
-		 * device in the list of devices being unregistered.
-		 * Therefore we should not pass dev_net(dev) in here.
-		 */
-		rt_cache_flush_batch(NULL);
 		break;
 	}
 	return NOTIFY_DONE;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 6a83840..f3f4037 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -129,7 +129,6 @@ static int ip_rt_gc_elasticity __read_mostly	= 8;
 static int ip_rt_mtu_expires __read_mostly	= 10 * 60 * HZ;
 static int ip_rt_min_pmtu __read_mostly		= 512 + 20 + 20;
 static int ip_rt_min_advmss __read_mostly	= 256;
-static int rt_chain_length_max __read_mostly	= 20;
 
 /*
  *	Interface to generic destination cache.
@@ -142,7 +141,6 @@ static void		 ipv4_dst_destroy(struct dst_entry *dst);
 static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
 static void		 ipv4_link_failure(struct sk_buff *skb);
 static void		 ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
-static int rt_garbage_collect(struct dst_ops *ops);
 
 static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 			    int how)
@@ -187,7 +185,6 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old)
 static struct dst_ops ipv4_dst_ops = {
 	.family =		AF_INET,
 	.protocol =		cpu_to_be16(ETH_P_IP),
-	.gc =			rt_garbage_collect,
 	.check =		ipv4_dst_check,
 	.default_advmss =	ipv4_default_advmss,
 	.default_mtu =		ipv4_default_mtu,
@@ -222,184 +219,30 @@ const __u8 ip_tos2prio[16] = {
 };
 
 
-/*
- * Route cache.
- */
-
-/* The locking scheme is rather straight forward:
- *
- * 1) Read-Copy Update protects the buckets of the central route hash.
- * 2) Only writers remove entries, and they hold the lock
- *    as they look at rtable reference counts.
- * 3) Only readers acquire references to rtable entries,
- *    they do so with atomic increments and with the
- *    lock held.
- */
-
-struct rt_hash_bucket {
-	struct rtable __rcu	*chain;
-};
-
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) || \
-	defined(CONFIG_PROVE_LOCKING)
-/*
- * Instead of using one spinlock for each rt_hash_bucket, we use a table of spinlocks
- * The size of this table is a power of two and depends on the number of CPUS.
- * (on lockdep we have a quite big spinlock_t, so keep the size down there)
- */
-#ifdef CONFIG_LOCKDEP
-# define RT_HASH_LOCK_SZ	256
-#else
-# if NR_CPUS >= 32
-#  define RT_HASH_LOCK_SZ	4096
-# elif NR_CPUS >= 16
-#  define RT_HASH_LOCK_SZ	2048
-# elif NR_CPUS >= 8
-#  define RT_HASH_LOCK_SZ	1024
-# elif NR_CPUS >= 4
-#  define RT_HASH_LOCK_SZ	512
-# else
-#  define RT_HASH_LOCK_SZ	256
-# endif
-#endif
-
-static spinlock_t	*rt_hash_locks;
-# define rt_hash_lock_addr(slot) &rt_hash_locks[(slot) & (RT_HASH_LOCK_SZ - 1)]
-
-static __init void rt_hash_lock_init(void)
-{
-	int i;
-
-	rt_hash_locks = kmalloc(sizeof(spinlock_t) * RT_HASH_LOCK_SZ,
-			GFP_KERNEL);
-	if (!rt_hash_locks)
-		panic("IP: failed to allocate rt_hash_locks\n");
-
-	for (i = 0; i < RT_HASH_LOCK_SZ; i++)
-		spin_lock_init(&rt_hash_locks[i]);
-}
-#else
-# define rt_hash_lock_addr(slot) NULL
-
-static inline void rt_hash_lock_init(void)
-{
-}
-#endif
-
-static struct rt_hash_bucket 	*rt_hash_table __read_mostly;
-static unsigned			rt_hash_mask __read_mostly;
-static unsigned int		rt_hash_log  __read_mostly;
-
 static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
 #define RT_CACHE_STAT_INC(field) __this_cpu_inc(rt_cache_stat.field)
 
-static inline unsigned int rt_hash(__be32 daddr, __be32 saddr, int idx,
-				   int genid)
-{
-	return jhash_3words((__force u32)daddr, (__force u32)saddr,
-			    idx, genid)
-		& rt_hash_mask;
-}
-
 static inline int rt_genid(struct net *net)
 {
 	return atomic_read(&net->ipv4.rt_genid);
 }
 
 #ifdef CONFIG_PROC_FS
-struct rt_cache_iter_state {
-	struct seq_net_private p;
-	int bucket;
-	int genid;
-};
-
-static struct rtable *rt_cache_get_first(struct seq_file *seq)
-{
-	struct rt_cache_iter_state *st = seq->private;
-	struct rtable *r = NULL;
-
-	for (st->bucket = rt_hash_mask; st->bucket >= 0; --st->bucket) {
-		if (!rcu_dereference_raw(rt_hash_table[st->bucket].chain))
-			continue;
-		rcu_read_lock_bh();
-		r = rcu_dereference_bh(rt_hash_table[st->bucket].chain);
-		while (r) {
-			if (dev_net(r->dst.dev) == seq_file_net(seq) &&
-			    r->rt_genid == st->genid)
-				return r;
-			r = rcu_dereference_bh(r->dst.rt_next);
-		}
-		rcu_read_unlock_bh();
-	}
-	return r;
-}
-
-static struct rtable *__rt_cache_get_next(struct seq_file *seq,
-					  struct rtable *r)
-{
-	struct rt_cache_iter_state *st = seq->private;
-
-	r = rcu_dereference_bh(r->dst.rt_next);
-	while (!r) {
-		rcu_read_unlock_bh();
-		do {
-			if (--st->bucket < 0)
-				return NULL;
-		} while (!rcu_dereference_raw(rt_hash_table[st->bucket].chain));
-		rcu_read_lock_bh();
-		r = rcu_dereference_bh(rt_hash_table[st->bucket].chain);
-	}
-	return r;
-}
-
-static struct rtable *rt_cache_get_next(struct seq_file *seq,
-					struct rtable *r)
-{
-	struct rt_cache_iter_state *st = seq->private;
-	while ((r = __rt_cache_get_next(seq, r)) != NULL) {
-		if (dev_net(r->dst.dev) != seq_file_net(seq))
-			continue;
-		if (r->rt_genid == st->genid)
-			break;
-	}
-	return r;
-}
-
-static struct rtable *rt_cache_get_idx(struct seq_file *seq, loff_t pos)
-{
-	struct rtable *r = rt_cache_get_first(seq);
-
-	if (r)
-		while (pos && (r = rt_cache_get_next(seq, r)))
-			--pos;
-	return pos ? NULL : r;
-}
-
 static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	struct rt_cache_iter_state *st = seq->private;
 	if (*pos)
-		return rt_cache_get_idx(seq, *pos - 1);
-	st->genid = rt_genid(seq_file_net(seq));
+		return NULL;
 	return SEQ_START_TOKEN;
 }
 
 static void *rt_cache_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct rtable *r;
-
-	if (v == SEQ_START_TOKEN)
-		r = rt_cache_get_first(seq);
-	else
-		r = rt_cache_get_next(seq, v);
 	++*pos;
-	return r;
+	return NULL;
 }
 
 static void rt_cache_seq_stop(struct seq_file *seq, void *v)
 {
-	if (v && v != SEQ_START_TOKEN)
-		rcu_read_unlock_bh();
 }
 
 static int rt_cache_seq_show(struct seq_file *seq, void *v)
@@ -409,29 +252,6 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
 			   "Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\t"
 			   "Metric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\t"
 			   "HHUptod\tSpecDst");
-	else {
-		struct rtable *r = v;
-		int len;
-
-		seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t"
-			      "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n",
-			r->dst.dev ? r->dst.dev->name : "*",
-			(__force u32)r->rt_dst,
-			(__force u32)r->rt_gateway,
-			r->rt_flags, atomic_read(&r->dst.__refcnt),
-			r->dst.__use, 0, (__force u32)r->rt_src,
-			dst_metric_advmss(&r->dst) + 40,
-			dst_metric(&r->dst, RTAX_WINDOW),
-			(int)((dst_metric(&r->dst, RTAX_RTT) >> 3) +
-			      dst_metric(&r->dst, RTAX_RTTVAR)),
-			r->rt_key_tos,
-			r->dst.hh ? atomic_read(&r->dst.hh->hh_refcnt) : -1,
-			r->dst.hh ? (r->dst.hh->hh_output ==
-				       dev_queue_xmit) : 0,
-			r->rt_spec_dst, &len);
-
-		seq_printf(seq, "%*s\n", 127 - len, "");
-	}
 	return 0;
 }
 
@@ -444,8 +264,7 @@ static const struct seq_operations rt_cache_seq_ops = {
 
 static int rt_cache_seq_open(struct inode *inode, struct file *file)
 {
-	return seq_open_net(inode, file, &rt_cache_seq_ops,
-			sizeof(struct rt_cache_iter_state));
+	return seq_open(file, &rt_cache_seq_ops);
 }
 
 static const struct file_operations rt_cache_seq_fops = {
@@ -453,7 +272,7 @@ static const struct file_operations rt_cache_seq_fops = {
 	.open	 = rt_cache_seq_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
-	.release = seq_release_net,
+	.release = seq_release,
 };
 
 
@@ -643,184 +462,12 @@ static inline int ip_rt_proc_init(void)
 }
 #endif /* CONFIG_PROC_FS */
 
-static inline void rt_free(struct rtable *rt)
-{
-	call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
-}
-
-static inline void rt_drop(struct rtable *rt)
-{
-	ip_rt_put(rt);
-	call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
-}
-
-static inline int rt_fast_clean(struct rtable *rth)
-{
-	/* Kill broadcast/multicast entries very aggresively, if they
-	   collide in hash table with more useful entries */
-	return (rth->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) &&
-		rt_is_input_route(rth) && rth->dst.rt_next;
-}
-
-static inline int rt_valuable(struct rtable *rth)
-{
-	return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) ||
-		(rth->peer && rth->peer->pmtu_expires);
-}
-
-static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2)
-{
-	unsigned long age;
-	int ret = 0;
-
-	if (atomic_read(&rth->dst.__refcnt))
-		goto out;
-
-	age = jiffies - rth->dst.lastuse;
-	if ((age <= tmo1 && !rt_fast_clean(rth)) ||
-	    (age <= tmo2 && rt_valuable(rth)))
-		goto out;
-	ret = 1;
-out:	return ret;
-}
-
-/* Bits of score are:
- * 31: very valuable
- * 30: not quite useless
- * 29..0: usage counter
- */
-static inline u32 rt_score(struct rtable *rt)
-{
-	u32 score = jiffies - rt->dst.lastuse;
-
-	score = ~score & ~(3<<30);
-
-	if (rt_valuable(rt))
-		score |= (1<<31);
-
-	if (rt_is_output_route(rt) ||
-	    !(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL)))
-		score |= (1<<30);
-
-	return score;
-}
-
-static inline bool rt_caching(const struct net *net)
-{
-	return net->ipv4.current_rt_cache_rebuild_count <=
-		net->ipv4.sysctl_rt_cache_rebuild_count;
-}
-
-static inline bool compare_hash_inputs(const struct rtable *rt1,
-				       const struct rtable *rt2)
-{
-	return ((((__force u32)rt1->rt_key_dst ^ (__force u32)rt2->rt_key_dst) |
-		((__force u32)rt1->rt_key_src ^ (__force u32)rt2->rt_key_src) |
-		(rt1->rt_iif ^ rt2->rt_iif)) == 0);
-}
-
-static inline int compare_keys(struct rtable *rt1, struct rtable *rt2)
-{
-	return (((__force u32)rt1->rt_key_dst ^ (__force u32)rt2->rt_key_dst) |
-		((__force u32)rt1->rt_key_src ^ (__force u32)rt2->rt_key_src) |
-		(rt1->rt_mark ^ rt2->rt_mark) |
-		(rt1->rt_key_tos ^ rt2->rt_key_tos) |
-		(rt1->rt_oif ^ rt2->rt_oif) |
-		(rt1->rt_iif ^ rt2->rt_iif)) == 0;
-}
-
-static inline int compare_netns(struct rtable *rt1, struct rtable *rt2)
-{
-	return net_eq(dev_net(rt1->dst.dev), dev_net(rt2->dst.dev));
-}
-
 static inline int rt_is_expired(struct rtable *rth)
 {
 	return rth->rt_genid != rt_genid(dev_net(rth->dst.dev));
 }
 
 /*
- * Perform a full scan of hash table and free all entries.
- * Can be called by a softirq or a process.
- * In the later case, we want to be reschedule if necessary
- */
-static void rt_do_flush(struct net *net, int process_context)
-{
-	unsigned int i;
-	struct rtable *rth, *next;
-
-	for (i = 0; i <= rt_hash_mask; i++) {
-		struct rtable __rcu **pprev;
-		struct rtable *list;
-
-		if (process_context && need_resched())
-			cond_resched();
-		rth = rcu_dereference_raw(rt_hash_table[i].chain);
-		if (!rth)
-			continue;
-
-		spin_lock_bh(rt_hash_lock_addr(i));
-
-		list = NULL;
-		pprev = &rt_hash_table[i].chain;
-		rth = rcu_dereference_protected(*pprev,
-			lockdep_is_held(rt_hash_lock_addr(i)));
-
-		while (rth) {
-			next = rcu_dereference_protected(rth->dst.rt_next,
-				lockdep_is_held(rt_hash_lock_addr(i)));
-
-			if (!net ||
-			    net_eq(dev_net(rth->dst.dev), net)) {
-				rcu_assign_pointer(*pprev, next);
-				rcu_assign_pointer(rth->dst.rt_next, list);
-				list = rth;
-			} else {
-				pprev = &rth->dst.rt_next;
-			}
-			rth = next;
-		}
-
-		spin_unlock_bh(rt_hash_lock_addr(i));
-
-		for (; list; list = next) {
-			next = rcu_dereference_protected(list->dst.rt_next, 1);
-			rt_free(list);
-		}
-	}
-}
-
-/*
- * While freeing expired entries, we compute average chain length
- * and standard deviation, using fixed-point arithmetic.
- * This to have an estimation of rt_chain_length_max
- *  rt_chain_length_max = max(elasticity, AVG + 4*SD)
- * We use 3 bits for frational part, and 29 (or 61) for magnitude.
- */
-
-#define FRACT_BITS 3
-#define ONE (1UL << FRACT_BITS)
-
-/*
- * Given a hash chain and an item in this hash chain,
- * find if a previous entry has the same hash_inputs
- * (but differs on tos, mark or oif)
- * Returns 0 if an alias is found.
- * Returns ONE if rth has no alias before itself.
- */
-static int has_noalias(const struct rtable *head, const struct rtable *rth)
-{
-	const struct rtable *aux = head;
-
-	while (aux != rth) {
-		if (compare_hash_inputs(aux, rth))
-			return 0;
-		aux = rcu_dereference_protected(aux->dst.rt_next, 1);
-	}
-	return ONE;
-}
-
-/*
  * Perturbation of rt_genid by a small quantity [1..256]
  * Using 8 bits of shuffling ensure we can call rt_cache_invalidate()
  * many times (2^24) without giving recent rt_genid.
@@ -841,364 +488,20 @@ static void rt_cache_invalidate(struct net *net)
 void rt_cache_flush(struct net *net, int delay)
 {
 	rt_cache_invalidate(net);
-	if (delay >= 0)
-		rt_do_flush(net, !in_softirq());
-}
-
-/* Flush previous cache invalidated entries from the cache */
-void rt_cache_flush_batch(struct net *net)
-{
-	rt_do_flush(net, !in_softirq());
-}
-
-static void rt_emergency_hash_rebuild(struct net *net)
-{
-	if (net_ratelimit())
-		printk(KERN_WARNING "Route hash chain too long!\n");
-	rt_cache_invalidate(net);
-}
-
-/*
-   Short description of GC goals.
-
-   We want to build algorithm, which will keep routing cache
-   at some equilibrium point, when number of aged off entries
-   is kept approximately equal to newly generated ones.
-
-   Current expiration strength is variable "expire".
-   We try to adjust it dynamically, so that if networking
-   is idle expires is large enough to keep enough of warm entries,
-   and when load increases it reduces to limit cache size.
- */
-
-static int rt_garbage_collect(struct dst_ops *ops)
-{
-	static unsigned long expire = RT_GC_TIMEOUT;
-	static unsigned long last_gc;
-	static int rover;
-	static int equilibrium;
-	struct rtable *rth;
-	struct rtable __rcu **rthp;
-	unsigned long now = jiffies;
-	int goal;
-	int entries = dst_entries_get_fast(&ipv4_dst_ops);
-
-	/*
-	 * Garbage collection is pretty expensive,
-	 * do not make it too frequently.
-	 */
-
-	RT_CACHE_STAT_INC(gc_total);
-
-	if (now - last_gc < ip_rt_gc_min_interval &&
-	    entries < ip_rt_max_size) {
-		RT_CACHE_STAT_INC(gc_ignored);
-		goto out;
-	}
-
-	entries = dst_entries_get_slow(&ipv4_dst_ops);
-	/* Calculate number of entries, which we want to expire now. */
-	goal = entries - (ip_rt_gc_elasticity << rt_hash_log);
-	if (goal <= 0) {
-		if (equilibrium < ipv4_dst_ops.gc_thresh)
-			equilibrium = ipv4_dst_ops.gc_thresh;
-		goal = entries - equilibrium;
-		if (goal > 0) {
-			equilibrium += min_t(unsigned int, goal >> 1, rt_hash_mask + 1);
-			goal = entries - equilibrium;
-		}
-	} else {
-		/* We are in dangerous area. Try to reduce cache really
-		 * aggressively.
-		 */
-		goal = max_t(unsigned int, goal >> 1, rt_hash_mask + 1);
-		equilibrium = entries - goal;
-	}
-
-	if (now - last_gc >= ip_rt_gc_min_interval)
-		last_gc = now;
-
-	if (goal <= 0) {
-		equilibrium += goal;
-		goto work_done;
-	}
-
-	do {
-		int i, k;
-
-		for (i = rt_hash_mask, k = rover; i >= 0; i--) {
-			unsigned long tmo = expire;
-
-			k = (k + 1) & rt_hash_mask;
-			rthp = &rt_hash_table[k].chain;
-			spin_lock_bh(rt_hash_lock_addr(k));
-			while ((rth = rcu_dereference_protected(*rthp,
-					lockdep_is_held(rt_hash_lock_addr(k)))) != NULL) {
-				if (!rt_is_expired(rth) &&
-					!rt_may_expire(rth, tmo, expire)) {
-					tmo >>= 1;
-					rthp = &rth->dst.rt_next;
-					continue;
-				}
-				*rthp = rth->dst.rt_next;
-				rt_free(rth);
-				goal--;
-			}
-			spin_unlock_bh(rt_hash_lock_addr(k));
-			if (goal <= 0)
-				break;
-		}
-		rover = k;
-
-		if (goal <= 0)
-			goto work_done;
-
-		/* Goal is not achieved. We stop process if:
-
-		   - if expire reduced to zero. Otherwise, expire is halfed.
-		   - if table is not full.
-		   - if we are called from interrupt.
-		   - jiffies check is just fallback/debug loop breaker.
-		     We will not spin here for long time in any case.
-		 */
-
-		RT_CACHE_STAT_INC(gc_goal_miss);
-
-		if (expire == 0)
-			break;
-
-		expire >>= 1;
-#if RT_CACHE_DEBUG >= 2
-		printk(KERN_DEBUG "expire>> %u %d %d %d\n", expire,
-				dst_entries_get_fast(&ipv4_dst_ops), goal, i);
-#endif
-
-		if (dst_entries_get_fast(&ipv4_dst_ops) < ip_rt_max_size)
-			goto out;
-	} while (!in_softirq() && time_before_eq(jiffies, now));
-
-	if (dst_entries_get_fast(&ipv4_dst_ops) < ip_rt_max_size)
-		goto out;
-	if (dst_entries_get_slow(&ipv4_dst_ops) < ip_rt_max_size)
-		goto out;
-	if (net_ratelimit())
-		printk(KERN_WARNING "dst cache overflow\n");
-	RT_CACHE_STAT_INC(gc_dst_overflow);
-	return 1;
-
-work_done:
-	expire += ip_rt_gc_min_interval;
-	if (expire > ip_rt_gc_timeout ||
-	    dst_entries_get_fast(&ipv4_dst_ops) < ipv4_dst_ops.gc_thresh ||
-	    dst_entries_get_slow(&ipv4_dst_ops) < ipv4_dst_ops.gc_thresh)
-		expire = ip_rt_gc_timeout;
-#if RT_CACHE_DEBUG >= 2
-	printk(KERN_DEBUG "expire++ %u %d %d %d\n", expire,
-			dst_entries_get_fast(&ipv4_dst_ops), goal, rover);
-#endif
-out:	return 0;
 }
 
-/*
- * Returns number of entries in a hash chain that have different hash_inputs
- */
-static int slow_chain_length(const struct rtable *head)
+static struct rtable *rt_finalize(struct rtable *rt, struct sk_buff *skb)
 {
-	int length = 0;
-	const struct rtable *rth = head;
-
-	while (rth) {
-		length += has_noalias(head, rth);
-		rth = rcu_dereference_protected(rth->dst.rt_next, 1);
-	}
-	return length >> FRACT_BITS;
-}
-
-static struct rtable *rt_intern_hash(unsigned hash, struct rtable *rt,
-				     struct sk_buff *skb, int ifindex)
-{
-	struct rtable	*rth, *cand;
-	struct rtable __rcu **rthp, **candp;
-	unsigned long	now;
-	u32 		min_score;
-	int		chain_length;
-	int attempts = !in_softirq();
-
-restart:
-	chain_length = 0;
-	min_score = ~(u32)0;
-	cand = NULL;
-	candp = NULL;
-	now = jiffies;
-
-	if (!rt_caching(dev_net(rt->dst.dev))) {
-		/*
-		 * If we're not caching, just tell the caller we
-		 * were successful and don't touch the route.  The
-		 * caller hold the sole reference to the cache entry, and
-		 * it will be released when the caller is done with it.
-		 * If we drop it here, the callers have no way to resolve routes
-		 * when we're not caching.  Instead, just point *rp at rt, so
-		 * the caller gets a single use out of the route
-		 * Note that we do rt_free on this new route entry, so that
-		 * once its refcount hits zero, we are still able to reap it
-		 * (Thanks Alexey)
-		 * Note: To avoid expensive rcu stuff for this uncached dst,
-		 * we set DST_NOCACHE so that dst_release() can free dst without
-		 * waiting a grace period.
-		 */
-
-		rt->dst.flags |= DST_NOCACHE;
-		if (rt->rt_type == RTN_UNICAST || rt_is_output_route(rt)) {
-			int err = arp_bind_neighbour(&rt->dst);
-			if (err) {
-				if (net_ratelimit())
-					printk(KERN_WARNING
-					    "Neighbour table failure & not caching routes.\n");
-				ip_rt_put(rt);
-				return ERR_PTR(err);
-			}
-		}
-
-		goto skip_hashing;
-	}
-
-	rthp = &rt_hash_table[hash].chain;
-
-	spin_lock_bh(rt_hash_lock_addr(hash));
-	while ((rth = rcu_dereference_protected(*rthp,
-			lockdep_is_held(rt_hash_lock_addr(hash)))) != NULL) {
-		if (rt_is_expired(rth)) {
-			*rthp = rth->dst.rt_next;
-			rt_free(rth);
-			continue;
-		}
-		if (compare_keys(rth, rt) && compare_netns(rth, rt)) {
-			/* Put it first */
-			*rthp = rth->dst.rt_next;
-			/*
-			 * Since lookup is lockfree, the deletion
-			 * must be visible to another weakly ordered CPU before
-			 * the insertion at the start of the hash chain.
-			 */
-			rcu_assign_pointer(rth->dst.rt_next,
-					   rt_hash_table[hash].chain);
-			/*
-			 * Since lookup is lockfree, the update writes
-			 * must be ordered for consistency on SMP.
-			 */
-			rcu_assign_pointer(rt_hash_table[hash].chain, rth);
-
-			dst_use(&rth->dst, now);
-			spin_unlock_bh(rt_hash_lock_addr(hash));
-
-			rt_drop(rt);
-			if (skb)
-				skb_dst_set(skb, &rth->dst);
-			return rth;
-		}
-
-		if (!atomic_read(&rth->dst.__refcnt)) {
-			u32 score = rt_score(rth);
-
-			if (score <= min_score) {
-				cand = rth;
-				candp = rthp;
-				min_score = score;
-			}
-		}
-
-		chain_length++;
-
-		rthp = &rth->dst.rt_next;
-	}
-
-	if (cand) {
-		/* ip_rt_gc_elasticity used to be average length of chain
-		 * length, when exceeded gc becomes really aggressive.
-		 *
-		 * The second limit is less certain. At the moment it allows
-		 * only 2 entries per bucket. We will see.
-		 */
-		if (chain_length > ip_rt_gc_elasticity) {
-			*candp = cand->dst.rt_next;
-			rt_free(cand);
-		}
-	} else {
-		if (chain_length > rt_chain_length_max &&
-		    slow_chain_length(rt_hash_table[hash].chain) > rt_chain_length_max) {
-			struct net *net = dev_net(rt->dst.dev);
-			int num = ++net->ipv4.current_rt_cache_rebuild_count;
-			if (!rt_caching(net)) {
-				printk(KERN_WARNING "%s: %d rebuilds is over limit, route caching disabled\n",
-					rt->dst.dev->name, num);
-			}
-			rt_emergency_hash_rebuild(net);
-			spin_unlock_bh(rt_hash_lock_addr(hash));
-
-			hash = rt_hash(rt->rt_key_dst, rt->rt_key_src,
-					ifindex, rt_genid(net));
-			goto restart;
-		}
-	}
-
-	/* Try to bind route to arp only if it is output
-	   route or unicast forwarding path.
-	 */
 	if (rt->rt_type == RTN_UNICAST || rt_is_output_route(rt)) {
 		int err = arp_bind_neighbour(&rt->dst);
 		if (err) {
-			spin_unlock_bh(rt_hash_lock_addr(hash));
-
-			if (err != -ENOBUFS) {
-				rt_drop(rt);
-				return ERR_PTR(err);
-			}
-
-			/* Neighbour tables are full and nothing
-			   can be released. Try to shrink route cache,
-			   it is most likely it holds some neighbour records.
-			 */
-			if (attempts-- > 0) {
-				int saved_elasticity = ip_rt_gc_elasticity;
-				int saved_int = ip_rt_gc_min_interval;
-				ip_rt_gc_elasticity	= 1;
-				ip_rt_gc_min_interval	= 0;
-				rt_garbage_collect(&ipv4_dst_ops);
-				ip_rt_gc_min_interval	= saved_int;
-				ip_rt_gc_elasticity	= saved_elasticity;
-				goto restart;
-			}
-
 			if (net_ratelimit())
-				printk(KERN_WARNING "ipv4: Neighbour table overflow.\n");
-			rt_drop(rt);
-			return ERR_PTR(-ENOBUFS);
+				printk(KERN_WARNING
+				       "Neighbour table failure & not caching routes.\n");
+			ip_rt_put(rt);
+			return ERR_PTR(err);
 		}
 	}
-
-	rt->dst.rt_next = rt_hash_table[hash].chain;
-
-#if RT_CACHE_DEBUG >= 2
-	if (rt->dst.rt_next) {
-		struct rtable *trt;
-		printk(KERN_DEBUG "rt_cache @%02x: %pI4",
-		       hash, &rt->rt_dst);
-		for (trt = rt->dst.rt_next; trt; trt = trt->dst.rt_next)
-			printk(" . %pI4", &trt->rt_dst);
-		printk("\n");
-	}
-#endif
-	/*
-	 * Since lookup is lockfree, we must make sure
-	 * previous writes to rt are committed to memory
-	 * before making rt visible to other CPUS.
-	 */
-	rcu_assign_pointer(rt_hash_table[hash].chain, rt);
-
-	spin_unlock_bh(rt_hash_lock_addr(hash));
-
-skip_hashing:
 	if (skb)
 		skb_dst_set(skb, &rt->dst);
 	return rt;
@@ -1266,26 +569,6 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more)
 }
 EXPORT_SYMBOL(__ip_select_ident);
 
-static void rt_del(unsigned hash, struct rtable *rt)
-{
-	struct rtable __rcu **rthp;
-	struct rtable *aux;
-
-	rthp = &rt_hash_table[hash].chain;
-	spin_lock_bh(rt_hash_lock_addr(hash));
-	ip_rt_put(rt);
-	while ((aux = rcu_dereference_protected(*rthp,
-			lockdep_is_held(rt_hash_lock_addr(hash)))) != NULL) {
-		if (aux == rt || rt_is_expired(aux)) {
-			*rthp = aux->dst.rt_next;
-			rt_free(aux);
-			continue;
-		}
-		rthp = &aux->dst.rt_next;
-	}
-	spin_unlock_bh(rt_hash_lock_addr(hash));
-}
-
 /* called in rcu_read_lock() section */
 void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
 		    __be32 saddr, struct net_device *dev)
@@ -1344,14 +627,11 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
 			ip_rt_put(rt);
 			ret = NULL;
 		} else if (rt->rt_flags & RTCF_REDIRECTED) {
-			unsigned hash = rt_hash(rt->rt_key_dst, rt->rt_key_src,
-						rt->rt_oif,
-						rt_genid(dev_net(dst->dev)));
 #if RT_CACHE_DEBUG >= 1
 			printk(KERN_DEBUG "ipv4_negative_advice: redirect to %pI4/%02x dropped\n",
-				&rt->rt_dst, rt->rt_key_tos);
+			       &rt->rt_dst, rt->rt_key_tos);
 #endif
-			rt_del(hash, rt);
+			ip_rt_put(rt);
 			ret = NULL;
 		} else if (rt->peer &&
 			   rt->peer->pmtu_expires &&
@@ -1836,7 +1116,7 @@ static struct rtable *rt_dst_alloc(struct net_device *dev,
 				   bool nopolicy, bool noxfrm)
 {
 	return dst_alloc(&ipv4_dst_ops, dev, 1, -1,
-			 DST_HOST |
+			 DST_HOST | DST_NOCACHE |
 			 (nopolicy ? DST_NOPOLICY : 0) |
 			 (noxfrm ? DST_NOXFRM : 0));
 }
@@ -1845,7 +1125,6 @@ static struct rtable *rt_dst_alloc(struct net_device *dev,
 static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 				u8 tos, struct net_device *dev, int our)
 {
-	unsigned int hash;
 	struct rtable *rth;
 	__be32 spec_dst;
 	struct in_device *in_dev = __in_dev_get_rcu(dev);
@@ -1909,8 +1188,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 #endif
 	RT_CACHE_STAT_INC(in_slow_mc);
 
-	hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev)));
-	rth = rt_intern_hash(hash, rth, skb, dev->ifindex);
+	rth = rt_finalize(rth, skb);
 	err = 0;
 	if (IS_ERR(rth))
 		err = PTR_ERR(rth);
@@ -2055,7 +1333,6 @@ static int ip_mkroute_input(struct sk_buff *skb,
 {
 	struct rtable* rth = NULL;
 	int err;
-	unsigned hash;
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 	if (res->fi && res->fi->fib_nhs > 1)
@@ -2067,10 +1344,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
 	if (err)
 		return err;
 
-	/* put it into the cache */
-	hash = rt_hash(daddr, saddr, fl4->flowi4_iif,
-		       rt_genid(dev_net(rth->dst.dev)));
-	rth = rt_intern_hash(hash, rth, skb, fl4->flowi4_iif);
+	rth = rt_finalize(rth, skb);
 	if (IS_ERR(rth))
 		return PTR_ERR(rth);
 	return 0;
@@ -2096,7 +1370,6 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	unsigned	flags = 0;
 	u32		itag = 0;
 	struct rtable * rth;
-	unsigned	hash;
 	__be32		spec_dst;
 	int		err = -EINVAL;
 	struct net    * net = dev_net(dev);
@@ -2223,8 +1496,7 @@ local_input:
 		rth->dst.error= -err;
 		rth->rt_flags 	&= ~RTCF_LOCAL;
 	}
-	hash = rt_hash(daddr, saddr, fl4.flowi4_iif, rt_genid(net));
-	rth = rt_intern_hash(hash, rth, skb, fl4.flowi4_iif);
+	rth = rt_finalize(rth, skb);
 	err = 0;
 	if (IS_ERR(rth))
 		err = PTR_ERR(rth);
@@ -2271,47 +1543,10 @@ martian_source_keep_err:
 int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 			   u8 tos, struct net_device *dev, bool noref)
 {
-	struct rtable * rth;
-	unsigned	hash;
-	int iif = dev->ifindex;
-	struct net *net;
 	int res;
 
-	net = dev_net(dev);
-
 	rcu_read_lock();
 
-	if (!rt_caching(net))
-		goto skip_cache;
-
-	tos &= IPTOS_RT_MASK;
-	hash = rt_hash(daddr, saddr, iif, rt_genid(net));
-
-	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
-	     rth = rcu_dereference(rth->dst.rt_next)) {
-		if ((((__force u32)rth->rt_key_dst ^ (__force u32)daddr) |
-		     ((__force u32)rth->rt_key_src ^ (__force u32)saddr) |
-		     (rth->rt_iif ^ iif) |
-		     rth->rt_oif |
-		     (rth->rt_key_tos ^ tos)) == 0 &&
-		    rth->rt_mark == skb->mark &&
-		    net_eq(dev_net(rth->dst.dev), net) &&
-		    !rt_is_expired(rth)) {
-			if (noref) {
-				dst_use_noref(&rth->dst, jiffies);
-				skb_dst_set_noref(skb, &rth->dst);
-			} else {
-				dst_use(&rth->dst, jiffies);
-				skb_dst_set(skb, &rth->dst);
-			}
-			RT_CACHE_STAT_INC(in_hit);
-			rcu_read_unlock();
-			return 0;
-		}
-		RT_CACHE_STAT_INC(in_hlist_search);
-	}
-
-skip_cache:
 	/* Multicast recognition logic is moved from route cache to here.
 	   The problem was that too many Ethernet cards have broken/missing
 	   hardware multicast filters :-( As result the host on multicasting
@@ -2454,10 +1689,9 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
 
 /*
  * Major route resolver routine.
- * called with rcu_read_lock();
  */
 
-static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4)
+struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 {
 	struct net_device *dev_out = NULL;
 	u32 tos	= RT_FL_TOS(fl4);
@@ -2637,57 +1871,13 @@ static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4)
 make_route:
 	rth = __mkroute_output(&res, fl4, orig_daddr, orig_saddr, orig_oif,
 			       dev_out, flags);
-	if (!IS_ERR(rth)) {
-		unsigned int hash;
-
-		hash = rt_hash(orig_daddr, orig_saddr, orig_oif,
-			       rt_genid(dev_net(dev_out)));
-		rth = rt_intern_hash(hash, rth, NULL, orig_oif);
-	}
+	if (!IS_ERR(rth))
+		rth = rt_finalize(rth, NULL);
 
 out:
 	rcu_read_unlock();
 	return rth;
 }
-
-struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4)
-{
-	struct rtable *rth;
-	unsigned int hash;
-
-	if (!rt_caching(net))
-		goto slow_output;
-
-	hash = rt_hash(flp4->daddr, flp4->saddr, flp4->flowi4_oif, rt_genid(net));
-
-	rcu_read_lock_bh();
-	for (rth = rcu_dereference_bh(rt_hash_table[hash].chain); rth;
-		rth = rcu_dereference_bh(rth->dst.rt_next)) {
-		if (rth->rt_key_dst == flp4->daddr &&
-		    rth->rt_key_src == flp4->saddr &&
-		    rt_is_output_route(rth) &&
-		    rth->rt_oif == flp4->flowi4_oif &&
-		    rth->rt_mark == flp4->flowi4_mark &&
-		    !((rth->rt_key_tos ^ flp4->flowi4_tos) &
-			    (IPTOS_RT_MASK | RTO_ONLINK)) &&
-		    net_eq(dev_net(rth->dst.dev), net) &&
-		    !rt_is_expired(rth)) {
-			dst_use(&rth->dst, jiffies);
-			RT_CACHE_STAT_INC(out_hit);
-			rcu_read_unlock_bh();
-			if (!flp4->saddr)
-				flp4->saddr = rth->rt_src;
-			if (!flp4->daddr)
-				flp4->daddr = rth->rt_dst;
-			return rth;
-		}
-		RT_CACHE_STAT_INC(out_hlist_search);
-	}
-	rcu_read_unlock_bh();
-
-slow_output:
-	return ip_route_output_slow(net, flp4);
-}
 EXPORT_SYMBOL_GPL(__ip_route_output_key);
 
 static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie)
@@ -2984,43 +2174,6 @@ errout_free:
 
 int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
 {
-	struct rtable *rt;
-	int h, s_h;
-	int idx, s_idx;
-	struct net *net;
-
-	net = sock_net(skb->sk);
-
-	s_h = cb->args[0];
-	if (s_h < 0)
-		s_h = 0;
-	s_idx = idx = cb->args[1];
-	for (h = s_h; h <= rt_hash_mask; h++, s_idx = 0) {
-		if (!rt_hash_table[h].chain)
-			continue;
-		rcu_read_lock_bh();
-		for (rt = rcu_dereference_bh(rt_hash_table[h].chain), idx = 0; rt;
-		     rt = rcu_dereference_bh(rt->dst.rt_next), idx++) {
-			if (!net_eq(dev_net(rt->dst.dev), net) || idx < s_idx)
-				continue;
-			if (rt_is_expired(rt))
-				continue;
-			skb_dst_set_noref(skb, &rt->dst);
-			if (rt_fill_info(net, skb, NETLINK_CB(cb->skb).pid,
-					 cb->nlh->nlmsg_seq, RTM_NEWROUTE,
-					 1, NLM_F_MULTI) <= 0) {
-				skb_dst_drop(skb);
-				rcu_read_unlock_bh();
-				goto done;
-			}
-			skb_dst_drop(skb);
-		}
-		rcu_read_unlock_bh();
-	}
-
-done:
-	cb->args[0] = h;
-	cb->args[1] = idx;
 	return skb->len;
 }
 
@@ -3255,16 +2408,6 @@ static __net_initdata struct pernet_operations rt_genid_ops = {
 struct ip_rt_acct __percpu *ip_rt_acct __read_mostly;
 #endif /* CONFIG_IP_ROUTE_CLASSID */
 
-static __initdata unsigned long rhash_entries;
-static int __init set_rhash_entries(char *str)
-{
-	if (!str)
-		return 0;
-	rhash_entries = simple_strtoul(str, &str, 0);
-	return 1;
-}
-__setup("rhash_entries=", set_rhash_entries);
-
 int __init ip_rt_init(void)
 {
 	int rc = 0;
@@ -3287,21 +2430,8 @@ int __init ip_rt_init(void)
 	if (dst_entries_init(&ipv4_dst_blackhole_ops) < 0)
 		panic("IP: failed to allocate ipv4_dst_blackhole_ops counter\n");
 
-	rt_hash_table = (struct rt_hash_bucket *)
-		alloc_large_system_hash("IP route cache",
-					sizeof(struct rt_hash_bucket),
-					rhash_entries,
-					(totalram_pages >= 128 * 1024) ?
-					15 : 17,
-					0,
-					&rt_hash_log,
-					&rt_hash_mask,
-					rhash_entries ? 0 : 512 * 1024);
-	memset(rt_hash_table, 0, (rt_hash_mask + 1) * sizeof(struct rt_hash_bucket));
-	rt_hash_lock_init();
-
-	ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1);
-	ip_rt_max_size = (rt_hash_mask + 1) * 16;
+	ipv4_dst_ops.gc_thresh = ~0;
+	ip_rt_max_size = INT_MAX;
 
 	devinet_init();
 	ip_fib_init();
-- 
1.7.5.1


^ permalink raw reply related

* [PATCH v6 0/3] rtcache removal respin
From: David Miller @ 2011-05-05 23:35 UTC (permalink / raw)
  To: netdev; +Cc: tgraf, jpirko, herbert, eric.dumazet


As before, this is just a respin of the routing cache removal patches
for people who want to play with this stuff.

The patch set has shrunk significantly, because several changes in the
previous series have been integrated to net-next-2.6

One new change is that now rt->rt_key_tos is removed alongside
rt->rt_key_{dst,src}

And finally, I've included an extra bonus patch showing an
experimental scheme I'm working on which will make output route
resolution in a routing-cache-less environment extremely fast.

Enjoy.

^ permalink raw reply

* Re: [PATCHv4 2/2] tg3: Allow ethtool to enable/disable loopback.
From: Mahesh Bandewar @ 2011-05-05 23:16 UTC (permalink / raw)
  To: Michał Mirosław
  Cc: Matt Carlson, David Miller, netdev, Michael Chan, Tom Herbert
In-Reply-To: <BANLkTikJ67YLGzR-3rjazkUgmffMxp1nJQ@mail.gmail.com>

On Thu, May 5, 2011 at 11:35 AM, Michał Mirosław <mirqus@gmail.com> wrote:
> W dniu 5 maja 2011 19:47 użytkownik Mahesh Bandewar
> <maheshb@google.com> napisał:
>> On Wed, May 4, 2011 at 11:59 PM, Michał Mirosław <mirqus@gmail.com> wrote:
>>> 2011/5/5 Mahesh Bandewar <maheshb@google.com>:
>>>> This patch adds tg3_set_features() to handle loopback mode. Currently the
>>>> capability is added for the devices which support internal MAC loopback mode.
>>>> So when enabled, it enables internal-MAC loopback.
> [...]
>>>> @@ -9485,6 +9533,15 @@ static int tg3_open(struct net_device *dev)
>>>>
>>>>        netif_tx_start_all_queues(dev);
>>>>
>>>> +       /*
>>>> +        * Reset loopback feature if it was turned on while the device was down
>>>> +        * to avoid and any discrepancy in features reporting.
>>>> +        */
>>>> +       if (dev->features & NETIF_F_LOOPBACK) {
>>>> +               dev->features &= ~NETIF_F_LOOPBACK;
>>>> +               dev->wanted_features &= ~NETIF_F_LOOPBACK;
>>>> +       }
>>>> +
>>>
>>> if (dev->features & NETIF_F_LOOPBACK)
>>>  tg3_set_loopback(dev, dev->features);
>>>
>> Unfortunately at this stage device will not be able to set-loopback so
>> I resorted to clearing the bit(s).
>
> ndo_fix_features+ndo_set_features might be caled before ndo_open - the
> first might be just from register_netdev() so even before ndo_open
> callback.
>
ndo_open is the triggering event, so anything before that point does
not really help.

>>> Whatever you do, don't modify wanted_features in drivers.
>> Since just clearing the 'features' would leave wanted_features in
>> discrepant state, I thought this will bring it to a sane state. So
>> what is a preferred way?
>
> If you really can't do other way, driver should keep additional state
> that is checked in ndo_fix_features callback.
>
ndo_fix_features callback is called just before calling
ndo_set_features callback. Also this is called during update_features,
so having the state maintained is not really going to help in this
scenario since that is not happening when device reaches ready state
(to remove this discrepancy in the feature-set).

There must be a reason (that you did not explain!) why driver code
should not alter wanted_feature set. So in this scenario, just leaving
the wanted_features as it is and clearing the features bit is correct
/ enough?


>>> BTW, similar problems (also like in previous versions) are in
>>> forcedeth implementation.
>> Yes, whatever we decide about the state of the wanted_features, I'll
>> implement similarly for forcedeth. Which previous problem you are
>> referring to? Is it the return value? There is a different kind of
>> failure (error while writing the register). Since update_features()
>> cant handle return value, I'm ignoring the return value. As far as the
>> correct return code is concerned, I wasn't sure what is appropriate
>> return code here (may be PHY_ERROR would be appropriate there) but
>> again I could ignore it just the way rest of the code is ignoring.
>
> Let's wait for this threads points to be resolved. You will probably
> change the forcedeth's implementation then anyway. :-)
>
agreed.

Thanks,
--mahesh..
> Best Regards,
> Michał Mirosław
>

^ permalink raw reply

* Re: [Bugme-new] [Bug 34322] New: No ECN marking in IPv6
From: Andrew Morton @ 2011-05-05 21:41 UTC (permalink / raw)
  To: netdev; +Cc: bugzilla-daemon, bugme-daemon, sgunderson
In-Reply-To: <bug-34322-10286@https.bugzilla.kernel.org/>


(switched to email.  Please respond via emailed reply-to-all, not via the
bugzilla web interface).

On Tue, 3 May 2011 20:05:00 GMT
bugzilla-daemon@bugzilla.kernel.org wrote:

> https://bugzilla.kernel.org/show_bug.cgi?id=34322
> 
>            Summary: No ECN marking in IPv6
>            Product: Networking
>            Version: 2.5
>     Kernel Version: 2.6.38.4
>           Platform: All
>         OS/Version: Linux
>               Tree: Mainline
>             Status: NEW
>           Severity: normal
>           Priority: P1
>          Component: IPV6
>         AssignedTo: yoshfuji@linux-ipv6.org
>         ReportedBy: sgunderson@bigfoot.com
>         Regression: No
> 
> 
> Hi,
> 
> I'm completely unable to get ECN to work for IPv6. /proc/sys/net/ipv4/tcp_ecn
> is set to 1 on both sides, and ECN works just fine for IPv4 TCP connections,
> but when I connect over IPv6 tclass just stays at 0x0, and as far as I'd
> understood, there should be two bits here set to 10 (like in the diffserv field
> of IPv4), right?
> 
> I do get ECN-echo bits in the TCP header, though (for the initial SYN and
> SYN/ACK  packets).
> 

and

> I looked at the code, and although I don't understand all of it, it
> looks like e9df2e8fd8fbc95c57dbd1d33dada66c4627b44c (which also brought
> ECN for IPv6 SCTP) might be the culprit.  It seems like TCP_ECN_send()
> calls INET_ECN_xmit(), which only sets the ECN bit in the IPv4 ToS
> field (inet_sk(sk)->tos), but after the patch, what's checked is
> inet6_sk(sk)->tclass, which is a completely different field.
> 
> Is the analysis correct? Should the tclass be set as well?

and

> OK, as a quick hack, I did this:
> 
> --- a/linux-2.6.38.5/include/net/inet_ecn.h    2011-04-14 22:03:56.000000000+0200
> +++ b/linux-2.6.38.5/include/net/inet_ecn.h    2011-05-04 00:36:52.803377902+0200
> @@ -38,7 +38,7 @@
>      return outer;
>  }
> 
> -#define    INET_ECN_xmit(sk) do { inet_sk(sk)->tos |= INET_ECN_ECT_0; } while (0)
> +#define    INET_ECN_xmit(sk) do { inet_sk(sk)->tos |= INET_ECN_ECT_0; if (inet6_sk(sk) != NULL) inet6_sk(sk)->tclass |= INET_ECN_ECT_0; } while (0)
>  #define    INET_ECN_dontxmit(sk) \
>      do { inet_sk(sk)->tos &= ~INET_ECN_MASK; } while (0)
> 
> and now my packets are properly marked with tclass 0x02 (ie.,
> signalling ECN-capable transport, no congestion experienced yet).
> 
> I guess this isn't the right way of doing it, but at least it confirms
> that the lack of setting tclass is part of the problem.


^ permalink raw reply

* Re: [PATCH 0/2] wireless: Make and use const struct ieee80211_channel
From: Joe Perches @ 2011-05-05 22:21 UTC (permalink / raw)
  To: John W. Linville
  Cc: libertas-dev, linux-wireless, orinoco-users, orinoco-devel,
	netdev, LKML
In-Reply-To: <20110505184934.GB3005@tuxdriver.com>

On Thu, 2011-05-05 at 14:49 -0400, John W. Linville wrote:
> These patches generated a lot of warnings in net/mac80211.  Did you
> actually build them?

Yes.

Did you apply patch 1/2 first?
It's a dependent patch.

^ permalink raw reply

* Re: [PATCH V2 2/3] MIPS: lantiq: add ethernet driver
From: John Crispin @ 2011-05-05 22:16 UTC (permalink / raw)
  To: David Miller; +Cc: ralf, ralph.hempel, linux-mips, netdev
In-Reply-To: <20110505.151049.35056363.davem@davemloft.net>

On 06/05/11 00:10, David Miller wrote:
> From: John Crispin <blogic@openwrt.org>
> Date: Fri,  6 May 2011 00:10:01 +0200
>
>   
>> This patch adds the driver for the ETOP Packet Processing Engine (PPE32) found
>> inside the XWAY family of Lantiq MIPS SoCs. This driver makes 100MBit ethernet
>> work. Support for all 8 dma channels, gbit and the embedded switch found on
>> the ar9/vr9 still needs to be implemented.
>>
>> Signed-off-by: John Crispin <blogic@openwrt.org>
>> Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
>>     
> No objections from me and this can go via the MIPS tree:
>
> Acked-by: David S. Miller <davem@davemloft.net>
>
>   
Thank you !



^ permalink raw reply

* Re: [PATCH V2 2/3] MIPS: lantiq: add ethernet driver
From: David Miller @ 2011-05-05 22:10 UTC (permalink / raw)
  To: blogic; +Cc: ralf, ralph.hempel, linux-mips, netdev
In-Reply-To: <1304633402-24161-3-git-send-email-blogic@openwrt.org>

From: John Crispin <blogic@openwrt.org>
Date: Fri,  6 May 2011 00:10:01 +0200

> This patch adds the driver for the ETOP Packet Processing Engine (PPE32) found
> inside the XWAY family of Lantiq MIPS SoCs. This driver makes 100MBit ethernet
> work. Support for all 8 dma channels, gbit and the embedded switch found on
> the ar9/vr9 still needs to be implemented.
> 
> Signed-off-by: John Crispin <blogic@openwrt.org>
> Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>

No objections from me and this can go via the MIPS tree:

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* [PATCH V2 2/3] MIPS: lantiq: add ethernet driver
From: John Crispin @ 2011-05-05 22:10 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: John Crispin, Ralph Hempel, linux-mips, netdev
In-Reply-To: <1304633402-24161-1-git-send-email-blogic@openwrt.org>

This patch adds the driver for the ETOP Packet Processing Engine (PPE32) found
inside the XWAY family of Lantiq MIPS SoCs. This driver makes 100MBit ethernet
work. Support for all 8 dma channels, gbit and the embedded switch found on
the ar9/vr9 still needs to be implemented.

Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org

---

Changes in V2:
* use spinlocks
* use NAPI
* remove duplicate stats counter

 .../mips/include/asm/mach-lantiq/lantiq_platform.h |    7 +
 .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    4 +-
 drivers/net/Kconfig                                |    7 +
 drivers/net/Makefile                               |    1 +
 drivers/net/lantiq_etop.c                          |  794 ++++++++++++++++++++
 5 files changed, 811 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/lantiq_etop.c

diff --git a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
index 1f1dba6..a305f1d 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
@@ -10,6 +10,7 @@
 #define _LANTIQ_PLATFORM_H__
 
 #include <linux/mtd/partitions.h>
+#include <linux/socket.h>
 
 /* struct used to pass info to the pci core */
 enum {
@@ -43,4 +44,10 @@ struct ltq_pci_data {
 	int irq[16];
 };
 
+/* struct used to pass info to network drivers */
+struct ltq_eth_data {
+	struct sockaddr mac;
+	int mii_mode;
+};
+
 #endif
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 95f1882..0213601 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -81,8 +81,8 @@
 #define PMU_SWITCH		0x10000000
 
 /* ETOP - ethernet */
-#define LTQ_PPE32_BASE_ADDR	0xBE180000
-#define LTQ_PPE32_SIZE		0x40000
+#define LTQ_ETOP_BASE_ADDR	0x1E180000
+#define LTQ_ETOP_SIZE		0x40000
 
 /* DMA */
 #define LTQ_DMA_BASE_ADDR	0x1E104100
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b30c688..4878587 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2017,6 +2017,13 @@ config FTMAC100
 	  from Faraday. It is used on Faraday A320, Andes AG101 and some
 	  other ARM/NDS32 SoC's.
 
+config LANTIQ_ETOP
+	tristate "Lantiq SoC ETOP driver"
+	depends on SOC_TYPE_XWAY
+	help
+	  Support for the MII0 inside the Lantiq SoC
+
+
 source "drivers/net/fs_enet/Kconfig"
 
 source "drivers/net/octeon/Kconfig"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index fbfca11..df71da7 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -261,6 +261,7 @@ obj-$(CONFIG_MLX4_CORE) += mlx4/
 obj-$(CONFIG_ENC28J60) += enc28j60.o
 obj-$(CONFIG_ETHOC) += ethoc.o
 obj-$(CONFIG_GRETH) += greth.o
+obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
 
 obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
 
diff --git a/drivers/net/lantiq_etop.c b/drivers/net/lantiq_etop.c
new file mode 100644
index 0000000..3c9d34f
--- /dev/null
+++ b/drivers/net/lantiq_etop.c
@@ -0,0 +1,794 @@
+/*
+ *   This program is free software; you can redistribute it and/or modify it
+ *   under the terms of the GNU General Public License version 2 as published
+ *   by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *   Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+#include <linux/in.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/phy.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <asm/checksum.h>
+
+#include <lantiq_soc.h>
+#include <xway_dma.h>
+#include <lantiq_platform.h>
+
+#define LTQ_ETOP_MDIO		0x11804
+#define MDIO_REQUEST		0x80000000
+#define MDIO_READ		0x40000000
+#define MDIO_ADDR_MASK		0x1f
+#define MDIO_ADDR_OFFSET	0x15
+#define MDIO_REG_MASK		0x1f
+#define MDIO_REG_OFFSET		0x10
+#define MDIO_VAL_MASK		0xffff
+
+#define PPE32_CGEN		0x800
+#define LQ_PPE32_ENET_MAC_CFG	0x1840
+
+#define LTQ_ETOP_ENETS0		0x11850
+#define LTQ_ETOP_MAC_DA0	0x1186C
+#define LTQ_ETOP_MAC_DA1	0x11870
+#define LTQ_ETOP_CFG		0x16020
+#define LTQ_ETOP_IGPLEN		0x16080
+
+#define MAX_DMA_CHAN            0x8
+#define MAX_DMA_CRC_LEN		0x4
+#define MAX_DMA_DATA_LEN	0x600
+
+#define ETOP_FTCU		BIT(28)
+#define ETOP_MII_MASK		0xf
+#define ETOP_MII_NORMAL		0xd
+#define ETOP_MII_REVERSE	0xe
+#define ETOP_PLEN_UNDER		0x40
+#define ETOP_CGEN		0x800
+
+/* use 2 static channels for TX/RX */
+#define LTQ_ETOP_TX_CHANNEL	1
+#define LTQ_ETOP_RX_CHANNEL	6
+#define IS_TX(x)		(x == LTQ_ETOP_TX_CHANNEL)
+#define IS_RX(x)		(x == LTQ_ETOP_RX_CHANNEL)
+
+#define ltq_etop_r32(x)		ltq_r32(ltq_etop_membase + (x))
+#define ltq_etop_w32(x, y)	ltq_w32(x, ltq_etop_membase + (y))
+#define ltq_etop_w32_mask(x, y, z)	\
+		ltq_w32_mask(x, y, ltq_etop_membase + (z))
+
+#define DRV_VERSION	"1.0"
+
+static void __iomem *ltq_etop_membase;
+
+struct ltq_etop_chan {
+	int idx;
+	int tx_free;
+	struct net_device *netdev;
+	struct napi_struct napi;
+	struct ltq_dma_channel dma;
+	struct sk_buff *skb[LTQ_DESC_NUM];
+};
+
+struct ltq_etop_priv {
+	struct net_device *netdev;
+	struct ltq_eth_data *pldata;
+	struct resource *res;
+
+	struct mii_bus *mii_bus;
+	struct phy_device *phydev;
+
+	struct ltq_etop_chan ch[MAX_DMA_CHAN];
+	int tx_free[MAX_DMA_CHAN >> 1];
+
+	spinlock_t lock;
+};
+
+static int
+ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
+{
+	ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN);
+	if (!ch->skb[ch->dma.desc])
+		return -ENOMEM;
+	ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
+		ch->skb[ch->dma.desc]->data, MAX_DMA_DATA_LEN, DMA_FROM_DEVICE);
+	ch->dma.desc_base[ch->dma.desc].addr =
+		CPHYSADDR(ch->skb[ch->dma.desc]->data);
+	ch->dma.desc_base[ch->dma.desc].ctl =
+		LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | MAX_DMA_DATA_LEN;
+	skb_reserve(ch->skb[ch->dma.desc], NET_IP_ALIGN);
+	return 0;
+}
+
+static void
+ltq_etop_hw_receive(struct ltq_etop_chan *ch)
+{
+	struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
+	struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+	struct sk_buff *skb = ch->skb[ch->dma.desc];
+	int len = (desc->ctl & LTQ_DMA_SIZE_MASK) - MAX_DMA_CRC_LEN;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (ltq_etop_alloc_skb(ch)) {
+		netdev_err(ch->netdev,
+			"failed to allocate new rx buffer, stopping DMA\n");
+		ltq_dma_close(&ch->dma);
+	}
+	ch->dma.desc++;
+	ch->dma.desc %= LTQ_DESC_NUM;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	skb_put(skb, len);
+	skb->dev = ch->netdev;
+	skb->protocol = eth_type_trans(skb, ch->netdev);
+	netif_receive_skb(skb);
+}
+
+static int
+ltq_etop_poll_rx(struct napi_struct *napi, int budget)
+{
+	struct ltq_etop_chan *ch = container_of(napi, struct ltq_etop_chan, napi);
+	int rx = 0;
+	int complete = 0;
+
+	while ((rx < budget) && !complete) {
+		struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+
+		if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
+			ltq_etop_hw_receive(ch);
+			rx++;
+		} else {
+			complete = 1;
+		}
+	}
+	if (complete || !rx) {
+		napi_complete(&ch->napi);
+		ltq_dma_ack_irq(&ch->dma);
+	}
+	return rx;
+}
+
+static int
+ltq_etop_poll_tx(struct napi_struct *napi, int budget)
+{
+	struct ltq_etop_chan *ch =
+		container_of(napi, struct ltq_etop_chan, napi);
+	struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
+	struct netdev_queue *txq =
+		netdev_get_tx_queue(ch->netdev, ch->idx >> 1);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	while ((ch->dma.desc_base[ch->tx_free].ctl &
+			(LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
+		dev_kfree_skb_any(ch->skb[ch->tx_free]);
+		ch->skb[ch->tx_free] = NULL;
+		memset(&ch->dma.desc_base[ch->tx_free], 0,
+			sizeof(struct ltq_dma_desc));
+		ch->tx_free++;
+		ch->tx_free %= LTQ_DESC_NUM;
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (netif_tx_queue_stopped(txq))
+		netif_tx_start_queue(txq);
+	napi_complete(&ch->napi);
+	ltq_dma_ack_irq(&ch->dma);
+	return 1;
+}
+
+static irqreturn_t
+ltq_etop_dma_irq(int irq, void *_priv)
+{
+	struct ltq_etop_priv *priv = _priv;
+	int ch = irq - LTQ_DMA_CH0_INT;
+
+	napi_schedule(&priv->ch[ch].napi);
+	return IRQ_HANDLED;
+}
+
+static void
+ltq_etop_free_channel(struct net_device *dev, struct ltq_etop_chan *ch)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+
+	ltq_dma_free(&ch->dma);
+	if (ch->dma.irq)
+		free_irq(ch->dma.irq, priv);
+	if (IS_RX(ch->idx)) {
+		int desc;
+		for (desc = 0; desc < LTQ_DESC_NUM; desc++)
+			dev_kfree_skb_any(ch->skb[ch->dma.desc]);
+	}
+}
+
+static void
+ltq_etop_hw_exit(struct net_device *dev)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+	int i;
+
+	ltq_pmu_disable(PMU_PPE);
+	for (i = 0; i < MAX_DMA_CHAN; i++)
+		if (IS_TX(i) || IS_RX(i))
+			ltq_etop_free_channel(dev, &priv->ch[i]);
+}
+
+static int
+ltq_etop_hw_init(struct net_device *dev)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+	int i;
+
+	ltq_pmu_enable(PMU_PPE);
+
+	switch (priv->pldata->mii_mode) {
+	case PHY_INTERFACE_MODE_RMII:
+		ltq_etop_w32_mask(ETOP_MII_MASK,
+			ETOP_MII_REVERSE, LTQ_ETOP_CFG);
+		break;
+
+	case PHY_INTERFACE_MODE_MII:
+		ltq_etop_w32_mask(ETOP_MII_MASK,
+			ETOP_MII_NORMAL, LTQ_ETOP_CFG);
+		break;
+
+	default:
+		netdev_err(dev, "unknown mii mode %d\n",
+			priv->pldata->mii_mode);
+		return -ENOTSUPP;
+	}
+
+	/* enable crc generation */
+	ltq_etop_w32(PPE32_CGEN, LQ_PPE32_ENET_MAC_CFG);
+
+	ltq_dma_init_port(DMA_PORT_ETOP);
+
+	for (i = 0; i < MAX_DMA_CHAN; i++) {
+		int irq = LTQ_DMA_CH0_INT + i;
+		struct ltq_etop_chan *ch = &priv->ch[i];
+
+		ch->idx = ch->dma.nr = i;
+
+		if (IS_TX(i)) {
+			ltq_dma_alloc_tx(&ch->dma);
+			request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+				"etop_tx", priv);
+		} else if (IS_RX(i)) {
+			ltq_dma_alloc_rx(&ch->dma);
+			for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
+					ch->dma.desc++)
+				if (ltq_etop_alloc_skb(ch))
+					return -ENOMEM;
+			ch->dma.desc = 0;
+			request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+				"etop_rx", priv);
+		}
+		ch->dma.irq = irq;
+	}
+	return 0;
+}
+
+static void
+ltq_etop_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, "Lantiq ETOP");
+	strcpy(info->bus_info, "internal");
+	strcpy(info->version, DRV_VERSION);
+}
+
+static int
+ltq_etop_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+
+	return phy_ethtool_gset(priv->phydev, cmd);
+}
+
+static int
+ltq_etop_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+
+	return phy_ethtool_sset(priv->phydev, cmd);
+}
+
+static int
+ltq_etop_nway_reset(struct net_device *dev)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+
+	return phy_start_aneg(priv->phydev);
+}
+
+static const struct ethtool_ops ltq_etop_ethtool_ops = {
+	.get_drvinfo = ltq_etop_get_drvinfo,
+	.get_settings = ltq_etop_get_settings,
+	.set_settings = ltq_etop_set_settings,
+	.nway_reset = ltq_etop_nway_reset,
+};
+
+static int
+ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
+{
+	u32 val = MDIO_REQUEST |
+		((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) |
+		((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET) |
+		phy_data;
+
+	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
+		;
+	ltq_etop_w32(val, LTQ_ETOP_MDIO);
+	return 0;
+}
+
+static int
+ltq_etop_mdio_rd(struct mii_bus *bus, int phy_addr, int phy_reg)
+{
+	u32 val = MDIO_REQUEST | MDIO_READ |
+		((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) |
+		((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET);
+
+	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
+		;
+	ltq_etop_w32(val, LTQ_ETOP_MDIO);
+	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
+		;
+	val = ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_VAL_MASK;
+	return val;
+}
+
+static void
+ltq_etop_mdio_link(struct net_device *dev)
+{
+	/* nothing to do  */
+}
+
+static int
+ltq_etop_mdio_probe(struct net_device *dev)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+	struct phy_device *phydev = NULL;
+	int phy_addr;
+
+	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+		if (priv->mii_bus->phy_map[phy_addr]) {
+			phydev = priv->mii_bus->phy_map[phy_addr];
+			break;
+		}
+	}
+
+	if (!phydev) {
+		netdev_err(dev, "no PHY found\n");
+		return -ENODEV;
+	}
+
+	phydev = phy_connect(dev, dev_name(&phydev->dev), &ltq_etop_mdio_link,
+			0, priv->pldata->mii_mode);
+
+	if (IS_ERR(phydev)) {
+		netdev_err(dev, "Could not attach to PHY\n");
+		return PTR_ERR(phydev);
+	}
+
+	phydev->supported &= (SUPPORTED_10baseT_Half
+			      | SUPPORTED_10baseT_Full
+			      | SUPPORTED_100baseT_Half
+			      | SUPPORTED_100baseT_Full
+			      | SUPPORTED_Autoneg
+			      | SUPPORTED_MII
+			      | SUPPORTED_TP);
+
+	phydev->advertising = phydev->supported;
+	priv->phydev = phydev;
+	pr_info("%s: attached PHY [%s] (phy_addr=%s, irq=%d)\n",
+	       dev->name, phydev->drv->name,
+	       dev_name(&phydev->dev), phydev->irq);
+
+	return 0;
+}
+
+static int
+ltq_etop_mdio_init(struct net_device *dev)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+	int i;
+	int err;
+
+	priv->mii_bus = mdiobus_alloc();
+	if (!priv->mii_bus) {
+		netdev_err(dev, "failed to allocate mii bus\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	priv->mii_bus->priv = dev;
+	priv->mii_bus->read = ltq_etop_mdio_rd;
+	priv->mii_bus->write = ltq_etop_mdio_wr;
+	priv->mii_bus->name = "ltq_mii";
+	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
+	priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+	if (!priv->mii_bus->irq) {
+		err = -ENOMEM;
+		goto err_out_free_mdiobus;
+	}
+
+	for (i = 0; i < PHY_MAX_ADDR; ++i)
+		priv->mii_bus->irq[i] = PHY_POLL;
+
+	if (mdiobus_register(priv->mii_bus)) {
+		err = -ENXIO;
+		goto err_out_free_mdio_irq;
+	}
+
+	if (ltq_etop_mdio_probe(dev)) {
+		err = -ENXIO;
+		goto err_out_unregister_bus;
+	}
+	return 0;
+
+err_out_unregister_bus:
+	mdiobus_unregister(priv->mii_bus);
+err_out_free_mdio_irq:
+	kfree(priv->mii_bus->irq);
+err_out_free_mdiobus:
+	mdiobus_free(priv->mii_bus);
+err_out:
+	return err;
+}
+
+static void
+ltq_etop_mdio_cleanup(struct net_device *dev)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+
+	phy_disconnect(priv->phydev);
+	mdiobus_unregister(priv->mii_bus);
+	kfree(priv->mii_bus->irq);
+	mdiobus_free(priv->mii_bus);
+}
+
+static int
+ltq_etop_open(struct net_device *dev)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+	int i;
+
+	for (i = 0; i < MAX_DMA_CHAN; i++) {
+		struct ltq_etop_chan *ch = &priv->ch[i];
+
+		if (!IS_TX(i) && (!IS_RX(i)))
+			continue;
+		ltq_dma_open(&ch->dma);
+		napi_enable(&ch->napi);
+	}
+	phy_start(priv->phydev);
+	netif_tx_start_all_queues(dev);
+	return 0;
+}
+
+static int
+ltq_etop_stop(struct net_device *dev)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+	int i;
+
+	netif_tx_stop_all_queues(dev);
+	phy_stop(priv->phydev);
+	for (i = 0; i < MAX_DMA_CHAN; i++) {
+		struct ltq_etop_chan *ch = &priv->ch[i];
+
+		if (!IS_RX(i) && !IS_TX(i))
+			continue;
+		napi_disable(&ch->napi);
+		ltq_dma_close(&ch->dma);
+	}
+	return 0;
+}
+
+static int
+ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	int queue = skb_get_queue_mapping(skb);
+	struct netdev_queue *txq = netdev_get_tx_queue(dev, queue);
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+	struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1];
+	struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+	int len;
+	unsigned long flags;
+	u32 byte_offset;
+
+	len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+
+	if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
+		dev_kfree_skb_any(skb);
+		netdev_err(dev, "tx ring full\n");
+		netif_tx_stop_queue(txq);
+		return NETDEV_TX_BUSY;
+	}
+
+	/* dma needs to start on a 16 byte aligned address */
+	byte_offset = CPHYSADDR(skb->data) % 16;
+	ch->skb[ch->dma.desc] = skb;
+
+	dev->trans_start = jiffies;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	desc->addr = ((unsigned int) dma_map_single(NULL, skb->data, len,
+						DMA_TO_DEVICE)) - byte_offset;
+	wmb();
+	desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
+		LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
+	ch->dma.desc++;
+	ch->dma.desc %= LTQ_DESC_NUM;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN)
+		netif_tx_stop_queue(txq);
+
+	return NETDEV_TX_OK;
+}
+
+static int
+ltq_etop_change_mtu(struct net_device *dev, int new_mtu)
+{
+	int ret = eth_change_mtu(dev, new_mtu);
+
+	if (!ret) {
+		struct ltq_etop_priv *priv = netdev_priv(dev);
+		unsigned long flags;
+
+		spin_lock_irqsave(&priv->lock, flags);
+		ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu,
+			LTQ_ETOP_IGPLEN);
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+	return ret;
+}
+
+static int
+ltq_etop_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+
+	/* TODO: mii-toll reports "No MII transceiver present!." ?!*/
+	return phy_mii_ioctl(priv->phydev, rq, cmd);
+}
+
+static int
+ltq_etop_set_mac_address(struct net_device *dev, void *p)
+{
+	int ret = eth_mac_addr(dev, p);
+
+	if (!ret) {
+		struct ltq_etop_priv *priv = netdev_priv(dev);
+		unsigned long flags;
+
+		/* store the mac for the unicast filter */
+		spin_lock_irqsave(&priv->lock, flags);
+		ltq_etop_w32(*((u32 *)dev->dev_addr), LTQ_ETOP_MAC_DA0);
+		ltq_etop_w32(*((u16 *)&dev->dev_addr[4]) << 16,
+			LTQ_ETOP_MAC_DA1);
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+	return ret;
+}
+
+static void
+ltq_etop_set_multicast_list(struct net_device *dev)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+	unsigned long flags;
+
+	/* ensure that the unicast filter is not enabled in promiscious mode */
+	spin_lock_irqsave(&priv->lock, flags);
+	if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI))
+		ltq_etop_w32_mask(ETOP_FTCU, 0, LTQ_ETOP_ENETS0);
+	else
+		ltq_etop_w32_mask(0, ETOP_FTCU, LTQ_ETOP_ENETS0);
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static u16
+ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+	/* we are currently only using the first queue */
+	return 0;
+}
+
+static int
+ltq_etop_init(struct net_device *dev)
+{
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+	int err;
+
+	ether_setup(dev);
+	dev->watchdog_timeo = 10 * HZ;
+	err = ltq_etop_hw_init(dev);
+	if (err)
+		goto err_hw;
+	ltq_etop_change_mtu(dev, 1500);
+	err = ltq_etop_set_mac_address(dev, &priv->pldata->mac);
+	if (err)
+		goto err_netdev;
+	ltq_etop_set_multicast_list(dev);
+	err = ltq_etop_mdio_init(dev);
+	if (err)
+		goto err_netdev;
+	return 0;
+
+err_netdev:
+	unregister_netdev(dev);
+	free_netdev(dev);
+err_hw:
+	ltq_etop_hw_exit(dev);
+	return err;
+}
+
+static void
+ltq_etop_tx_timeout(struct net_device *dev)
+{
+	int err;
+
+	ltq_etop_hw_exit(dev);
+	err = ltq_etop_hw_init(dev);
+	if (err)
+		goto err_hw;
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+	return;
+
+err_hw:
+	ltq_etop_hw_exit(dev);
+	netdev_err(dev, "failed to restart etop after TX timeout\n");
+}
+
+static const struct net_device_ops ltq_eth_netdev_ops = {
+	.ndo_open = ltq_etop_open,
+	.ndo_stop = ltq_etop_stop,
+	.ndo_start_xmit = ltq_etop_tx,
+	.ndo_change_mtu = ltq_etop_change_mtu,
+	.ndo_do_ioctl = ltq_etop_ioctl,
+	.ndo_set_mac_address = ltq_etop_set_mac_address,
+	.ndo_validate_addr = eth_validate_addr,
+	.ndo_set_multicast_list = ltq_etop_set_multicast_list,
+	.ndo_select_queue = ltq_etop_select_queue,
+	.ndo_init = ltq_etop_init,
+	.ndo_tx_timeout = ltq_etop_tx_timeout,
+};
+
+static int __init
+ltq_etop_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct ltq_etop_priv *priv;
+	struct resource *res;
+	int err;
+	int i;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get etop resource\n");
+		err = -ENOENT;
+		goto err_out;
+	}
+
+	res = devm_request_mem_region(&pdev->dev, res->start,
+		resource_size(res), dev_name(&pdev->dev));
+	if (!res) {
+		dev_err(&pdev->dev, "failed to request etop resource\n");
+		err = -EBUSY;
+		goto err_out;
+	}
+
+	ltq_etop_membase = devm_ioremap_nocache(&pdev->dev,
+		res->start, resource_size(res));
+	if (!ltq_etop_membase) {
+		dev_err(&pdev->dev, "failed to remap etop engine %d\n",
+			pdev->id);
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
+	strcpy(dev->name, "eth%d");
+	dev->netdev_ops = &ltq_eth_netdev_ops;
+	dev->ethtool_ops = &ltq_etop_ethtool_ops;
+	priv = netdev_priv(dev);
+	priv->res = res;
+	priv->pldata = dev_get_platdata(&pdev->dev);
+	priv->netdev = dev;
+	spin_lock_init(&priv->lock);
+
+	for (i = 0; i < MAX_DMA_CHAN; i++) {
+		if (IS_TX(i))
+			netif_napi_add(dev, &priv->ch[i].napi,
+				ltq_etop_poll_tx, 8);
+		else if (IS_RX(i))
+			netif_napi_add(dev, &priv->ch[i].napi,
+				ltq_etop_poll_rx, 32);
+		priv->ch[i].netdev = dev;
+	}
+
+	err = register_netdev(dev);
+	if (err)
+		goto err_free;
+
+	platform_set_drvdata(pdev, dev);
+	return 0;
+
+err_free:
+	kfree(dev);
+err_out:
+	return err;
+}
+
+static int __devexit
+ltq_etop_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+
+	if (dev) {
+		netif_tx_stop_all_queues(dev);
+		ltq_etop_hw_exit(dev);
+		ltq_etop_mdio_cleanup(dev);
+		unregister_netdev(dev);
+	}
+	return 0;
+}
+
+static struct platform_driver ltq_mii_driver = {
+	.remove = __devexit_p(ltq_etop_remove),
+	.driver = {
+		.name = "ltq_etop",
+		.owner = THIS_MODULE,
+	},
+};
+
+int __init
+init_ltq_etop(void)
+{
+	int ret = platform_driver_probe(&ltq_mii_driver, ltq_etop_probe);
+
+	if (ret)
+		pr_err("ltq_etop: Error registering platfom driver!");
+	return ret;
+}
+
+static void __exit
+exit_ltq_etop(void)
+{
+	platform_driver_unregister(&ltq_mii_driver);
+}
+
+module_init(init_ltq_etop);
+module_exit(exit_ltq_etop);
+
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq SoC ETOP");
+MODULE_LICENSE("GPL");
-- 
1.7.2.3


^ permalink raw reply related

* Re: [RFC v3 02/10] Revert "lsm: Remove the socket_post_accept() hook"
From: Tetsuo Handa @ 2011-05-05 21:43 UTC (permalink / raw)
  To: paul.moore, sam
  Cc: linux-security-module, linux-kernel, netdev, netfilter-devel,
	hadi, kaber, zbr, root
In-Reply-To: <201105051011.32845.paul.moore@hp.com>

Paul Moore wrote:
> On Tuesday, May 03, 2011 10:28:24 PM Tetsuo Handa wrote:
> > Paul Moore wrote:
> > > On Tuesday, May 03, 2011 10:24:15 AM Samir Bellabes wrote:
> > > > snet needs to reintroduce this hook, as it was designed to be: a hook
> > > > for updating security informations on objects.
> > > 
> > > Looking at this and 5/10 again, it seems that you should be able to do
> > > what you need with the sock_graft() hook.  Am I missing something?
> > > 
> > > My apologies if we've already discussed this approach previously ...
> > 
> > Second problem is that genlmsg_unicast() might return -EAGAIN because we
> > can't sleep inside write_lock_bh()/write_unlock_bh().
> 
> Ah yes, the real problem.  I forgot that snet relied on a user space tool.  I 
> tend to agree with others who have suggested this is not the right approach, 
> but I understand why you want the post_accept() hook; thanks for reminding me.
> 
However, it sounds that Samir says genlmsg_unicast() failure is not fatal.

Samir Bellabes wrote:
> using snet_do_send_event() means that system is sending data to
> userspace. the system is not waiting for a verdict from userspace.
> 
> If error occurs, we actually loose the information data.
> I may be able to write a solution which try to send the data again, but
> we need a exit solution for this loop (a number of try ?).

If genlmsg_unicast() failure is not fatal, snet doesn't need the
socket_post_accept hook. Samir, is genlmsg_unicast() failure fatal for snet?
(Although, I'd like to ask for revival of the hook for TOMOYO anyway.)

^ permalink raw reply

* Re: pull request: wireless-next-2.6 2011-05-05
From: David Miller @ 2011-05-05 21:12 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev
In-Reply-To: <20110505191219.GC3005@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Thu, 5 May 2011 15:12:20 -0400

> Another big Cinco de Mayo batch of stuff intended for 2.6.40...

Aye caramba! :-)

> Highlights include a number of mwifiex bug fixes, a batch of wl12xx
> updates (including some new hardware support), a big batch of rtlwifi
> fixups in preparation for some new hardware drivers, some mwl8k and
> rt2x00 updates, the usual variety of iwlwifi and ath9k updates, a set
> of updates to the iwlegacy drivers from Stanislaw, some ssb udpates
> form Rafał, a bunch of Bluetooth updates from Gustavo and friends,
> and a handful of enhancements to other drivers and to mac80211.
> 
> Please let me know if there are problems!

Pulled, thanks a lot John!

^ permalink raw reply

* Re: [PATCH V4 2/8] netdevice.h: Add a new zerocopy device flag
From: Shirley Ma @ 2011-05-05 21:02 UTC (permalink / raw)
  To: Sridhar Samudrala
  Cc: David Miller, mst, Eric Dumazet, Avi Kivity, Arnd Bergmann,
	netdev, kvm, linux-kernel
In-Reply-To: <4DC1DD9D.6070708@us.ibm.com>

On Wed, 2011-05-04 at 16:13 -0700, Sridhar Samudrala wrote:
> On Wed, 2011-05-04 at 00:55 -0700, Shirley Ma wrote: 
> > Signed-off-by: Shirley Ma <xma@us.ibm.com>
> > ---
> > 
> >  include/linux/netdevice.h |   10 ++++++++++
> >  1 files changed, 10 insertions(+), 0 deletions(-)
> > 
> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > index 0249fe7..0808f1e 100644
> > --- a/include/linux/netdevice.h
> > +++ b/include/linux/netdevice.h
> > @@ -1067,6 +1067,16 @@ struct net_device {
> >  #define NETIF_F_RXHASH		(1 << 28) /* Receive hashing offload */
> >  #define NETIF_F_RXCSUM		(1 << 29) /* Receive checksumming offload */
> > 
> > +/*
> > + * Bit 31 is for device to map userspace buffers -- zerocopy
> > + * Device can set this flag when it supports HIGHDMA.
> > + * Device can't recycle this kind of skb buffers.
> > + * There are 256 bytes copied, the rest of buffers are mapped.
> > + * The userspace callback should only be called when last reference to this skb
> > + * is gone.
> > + */
> > +#define NETIF_F_ZEROCOPY	(1 << 31)
> > +
> Should we make this TX_ZEROCOPY as we may need a seperate flag for
> RX_ZEROCOPY in future?
> 
> Same with socket flag.

We might be able to use the same flag for both TX and RX. If RX
zero-copy requires only HIGHDMA feature only. If not, then we might need
different feature bit. Same for sock flag.

> Thanks
> Sridhar
> 
> 

^ permalink raw reply

* Re: [PATCH V4 5/8]macvtap: macvtap TX zero-copy support
From: Shirley Ma @ 2011-05-05 20:59 UTC (permalink / raw)
  To: Sridhar Samudrala
  Cc: David Miller, mst, Eric Dumazet, Avi Kivity, Arnd Bergmann,
	netdev, kvm, linux-kernel
In-Reply-To: <4DC1DD83.2020801@us.ibm.com>

On Wed, 2011-05-04 at 16:13 -0700, Sridhar Samudrala wrote:
> On Wed, 2011-05-04 at 01:14 -0700, Shirley Ma wrote: 
> > Only when buffer size is greater than GOODCOPY_LEN (256), macvtap
> > enables zero-copy.
> > 
> > Signed-off-by: Shirley Ma <xma@us.ibm.com>
> > ---
> > 
> >  drivers/net/macvtap.c |  126 ++++++++++++++++++++++++++++++++++++++++++++----
> >  1 files changed, 115 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
> > index 6696e56..e8bc5ff 100644
> > --- a/drivers/net/macvtap.c
> > +++ b/drivers/net/macvtap.c
> > @@ -60,6 +60,7 @@ static struct proto macvtap_proto = {
> >   */
> >  static dev_t macvtap_major;
> >  #define MACVTAP_NUM_DEVS 65536
> > +#define GOODCOPY_LEN 256
> >  static struct class *macvtap_class;
> >  static struct cdev macvtap_cdev;
> > 
> > @@ -340,6 +341,7 @@ static int macvtap_open(struct inode *inode, struct file *file)
> >  {
> >  	struct net *net = current->nsproxy->net_ns;
> >  	struct net_device *dev = dev_get_by_index(net, iminor(inode));
> > +	struct macvlan_dev *vlan = netdev_priv(dev);
> >  	struct macvtap_queue *q;
> >  	int err;
> > 
> > @@ -369,6 +371,16 @@ static int macvtap_open(struct inode *inode, struct file *file)
> >  	q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
> >  	q->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
> > 
> > +	/*
> > +	 * so far only VM uses macvtap, enable zero copy between guest
> > +	 * kernel and host kernel when lower device supports high memory
> > +	 * DMA
> > +	 */
> Instead of VM uses macvtap, it makes it more clear to say  'KVM virtio
> uses macvtap for guest networking'.
> Also you are checking if lower device allows zerocopy, not high dma.

Sure.

>  
> > +	if (vlan) {
> > +		if (vlan->lowerdev->features & NETIF_F_ZEROCOPY)
> > +			sock_set_flag(&q->sk, SOCK_ZEROCOPY);
> > +	}
> > +
> 
> Do we need to check for vlan? If required, both if conditions can be
> combined. 

Yes, I will run more test before enabling it.

> > 	err = macvtap_set_queue(dev, file, q);
> >  	if (err)
> >  		sock_put(&q->sk);
> > @@ -433,6 +445,80 @@ static inline struct sk_buff *macvtap_alloc_skb(struct sock *sk, size_t prepad,
> >  	return skb;
> >  }
> > 
> > +/* set skb frags from iovec, this can move to core network code for reuse */
> > +static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
> > +				  int offset, size_t count)
> > +{
> > +	int len = iov_length(from, count) - offset;
> > +	int copy = skb_headlen(skb);
> > +	int size, offset1 = 0;
> > +	int i = 0;
> > +	skb_frag_t *f;
> > +
> > +	/* Skip over from offset */
> > +	while (offset >= from->iov_len) {
> > +		offset -= from->iov_len;
> > +		++from;
> > +		--count;
> > +	}
> > +
> > +	/* copy up to skb headlen */
> > +	while (copy > 0) {
> > +		size = min_t(unsigned int, copy, from->iov_len - offset);
> > +		if (copy_from_user(skb->data + offset1, from->iov_base + offset,
> > +				   size))
> > +			return -EFAULT;
> > +		if (copy > size) {
> > +			++from;
> > +			--count;
> > +		}
> > +		copy -= size;
> > +		offset1 += size;
> > +		offset = 0;
> > +	}
> 
> I think you need to check for count reaching zero in the above 2 while
> loops.

Doesn't hurt to check count here, in this case, caller has
copylen/len/offset less than count/len already.

> > +
> > +	if (len == offset1)
> > +		return 0;
> > +
> > +	while (count--) {
> > +		struct page *page[MAX_SKB_FRAGS];
> > +		int num_pages;
> > +		unsigned long base;
> > +
> > +		len = from->iov_len - offset1;
> > +		if (!len) {
> > +			offset1 = 0;
> > +			++from;
> > +			continue;
> > +		}
> > +		base = (unsigned long)from->iov_base + offset1;
> > +		size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
> > +		num_pages = get_user_pages_fast(base, size, 0, &page[i]);
> > +		if ((num_pages != size) ||
> > +		    (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags))
> > +			/* put_page is in skb free */
> > +			return -EFAULT;
> > +		skb->data_len += len;
> > +		skb->len += len;
> > +		skb->truesize += len;
> > +		while (len) {
> > +			f = &skb_shinfo(skb)->frags[i];
> > +			f->page = page[i];
> > +			f->page_offset = base & ~PAGE_MASK;
> > +			f->size = min_t(int, len, PAGE_SIZE - f->page_offset);
> > +			skb_shinfo(skb)->nr_frags++;
> > +			/* increase sk_wmem_alloc */
> > +			atomic_add(f->size, &skb->sk->sk_wmem_alloc);
> > +			base += f->size;
> > +			len -= f->size;
> > +			i++;
> > +		}
> > +		offset1 = 0;
> > +		++from;
> > +	}
> > +	return 0;
> > +}
> > +
> >  /*
> >   * macvtap_skb_from_vnet_hdr and macvtap_skb_to_vnet_hdr should
> >   * be shared with the tun/tap driver.
> > @@ -515,17 +601,19 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
> > 
> > 
> >  /* Get packet from user space buffer */
> > -static ssize_t macvtap_get_user(struct macvtap_queue *q,
> > -				const struct iovec *iv, size_t count,
> > -				int noblock)
> > +static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
> > +				const struct iovec *iv, unsigned long total_len,
> > +				size_t count, int noblock)
> >  {
> >  	struct sk_buff *skb;
> >  	struct macvlan_dev *vlan;
> > -	size_t len = count;
> > +	unsigned long len = total_len;
> >  	int err;
> >  	struct virtio_net_hdr vnet_hdr = { 0 };
> >  	int vnet_hdr_len = 0;
> > +	int copylen, zerocopy;
> zerocopy can be boolean 

Yes, I have changed it in V5.

> > +	zerocopy = sock_flag(&q->sk, SOCK_ZEROCOPY) && (len > GOODCOPY_LEN);
> >  	if (q->flags & IFF_VNET_HDR) {
> >  		vnet_hdr_len = q->vnet_hdr_sz;
> > 
> > @@ -552,12 +640,28 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
> >  	if (unlikely(len < ETH_HLEN))
> >  		goto err;
> > 
> > -	skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, len, vnet_hdr.hdr_len,
> > -				noblock, &err);
> > +	if (zerocopy)
> > +		/* There are 256 bytes to be copied in skb, so there is enough
> > +		 * room for skb expand head in case it is used.
> > +		 * The rest buffer is mapped from userspace.
> > +		 */
> > +		copylen = GOODCOPY_LEN;
> > +	else
> > +		copylen = len;
> > +
> > +	skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen,
> > +				vnet_hdr.hdr_len, noblock, &err);
> >  	if (!skb)
> >  		goto err;
> > 
> > -	err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, len);
> > +	if (zerocopy)
> > +		err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count);
> > +	else
> > +		err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len,
> > +						   len);
> > +	if (sock_flag(&q->sk, SOCK_ZEROCOPY))
> > +		memcpy(&skb_shinfo(skb)->ubuf, m->msg_control,
> > +			sizeof(struct skb_ubuf_info));
> Why are you doing a separate check for this memcpy? Is this required
> if the len < 256? 

Yes. But I have changed it V5 based on MST's suggestion to leave copied
buffer maintain in vhost.

> > 	if (err)
> >  		goto err_kfree;
> > 
> > @@ -579,7 +683,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
> >  		kfree_skb(skb);
> >  	rcu_read_unlock_bh();
> > 
> > -	return count;
> > +	return total_len;
> > 
> >  err_kfree:
> >  	kfree_skb(skb);
> > @@ -601,8 +705,8 @@ static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv,
> >  	ssize_t result = -ENOLINK;
> >  	struct macvtap_queue *q = file->private_data;
> > 
> > -	result = macvtap_get_user(q, iv, iov_length(iv, count),
> > -			      file->f_flags & O_NONBLOCK);
> > +	result = macvtap_get_user(q, NULL, iv, iov_length(iv, count), count,
> > +				  file->f_flags & O_NONBLOCK);
> >  	return result;
> >  }
> > 
> > @@ -815,7 +919,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,
> >  			   struct msghdr *m, size_t total_len)
> >  {
> >  	struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
> > -	return macvtap_get_user(q, m->msg_iov, total_len,
> > +	return macvtap_get_user(q, m, m->msg_iov, total_len, m->msg_iovlen,
> >  			    m->msg_flags & MSG_DONTWAIT);
> >  }
> > 
> > 
> > 
> 

^ permalink raw reply

* Re: ARM, AF_PACKET: caching problems on Marvell Kirkwood
From: Andrew Lunn @ 2011-05-05 19:46 UTC (permalink / raw)
  To: linux-arm-kernel, netdev, ne, Johann Baudy, Lennert Buytenhek,
	Nicolas Pitre
In-Reply-To: <20110505141107.GC30443@orbit.nwl.cc>

On Thu, May 05, 2011 at 04:11:07PM +0200, Phil Sutter wrote:
> Hi,
> 
> Hasn't anyone experienced this bug but me? Can anyone reproduce the
> described behaviour on his Kirkwood-based (or even generic ARM) machine?
> I am still not sure if this is a problem of just my CPU or common
> amongst Kirkwood/VIPT/ARM machines.

Hi Phil

I can reproduce it on a Kirkwood:

[    0.000000] CPU: Feroceon 88FR131 [56251311] revision 1 (ARMv5TE), cr=00053977

     Andrew

^ permalink raw reply

* pull request: wireless-next-2.6 2011-05-05
From: John W. Linville @ 2011-05-05 19:12 UTC (permalink / raw)
  To: davem; +Cc: linux-wireless, netdev

Dave,

Another big Cinco de Mayo batch of stuff intended for 2.6.40...

Highlights include a number of mwifiex bug fixes, a batch of wl12xx
updates (including some new hardware support), a big batch of rtlwifi
fixups in preparation for some new hardware drivers, some mwl8k and
rt2x00 updates, the usual variety of iwlwifi and ath9k updates, a set
of updates to the iwlegacy drivers from Stanislaw, some ssb udpates
form Rafał, a bunch of Bluetooth updates from Gustavo and friends,
and a handful of enhancements to other drivers and to mac80211.

Please let me know if there are problems!

John

---

The following changes since commit 5a412ad7f4c95bb5b756aa12b52646e857e7c75d:

  Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/jkirsher/net-next-2.6 (2011-05-04 13:54:50 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6.git for-davem

Adrian Chadd (1):
      ath9k: fix AR9160 xpaBiasLvlFreq endianness handling

Amitkumar Karwar (4):
      cfg80211: module_param to disable HT40 in 2.4GHz band
      mwifiex: check firmware capabilities while initialising 5GHz band parameters
      mwifiex: HT capability information handling
      mwifiex: fix bug in mwifiex_save_curr_bcn()

Arik Nemtsov (5):
      wl12xx: 1281/1283 support - Use different FW file for AP mode wl127x/wl128x chips
      wl12xx: Clamp byte mode transfers for 128x chips
      wl12xx: configure channel/band while FW is off
      mac80211: allow low level drivers to report packet loss
      wl12xx: support FW TX inactivity triggers

Bing Zhao (1):
      mwifiex: fix missing tsf_val TLV

Chaoming_Li (17):
      rtlwifi: Change efuse routines addition of RTL8192SE and RTL8192DE
      rtlwifi: Change wifi.h for rtl8192se and rtl8192de
      rtlwifi: Change base routines for addition of rtl8192se and rtl8192de
      rtlwifi: Change cam routines for addition of rtl8192se and rtl8192de
      rtlwifi: Convert core routines for addition of rtl8192se and rtl8192de
      rtlwifi: Convert pci routines for addition of rtl8192se and rtl8192de
      rtlwifi: Convert ps routines for addition of rtl8192se and rtl8192de
      rtlwifi: Convert rc routines for addition of rtl8192se and rtl8192de
      rtlwifi: Convert regulatory domain routines for addition of rtl8192se and rtl8192de
      rtlwifi: Convert usb routines for addition of rtl8192se and rtl8192de
      rtlwifi: rtl8192c-common: Convert common dynamic management routines for addition of rtl8192se and rtl8192de
      rtlwifi: rtl8192c-common: Change common firmware routines for addition of rtl8192se and rtl8192de
      rtlwifi: rtl8192c-common: Change common PHY routines for addition of rtl8192se and rtl8192de
      rtlwifi: rtl8192ce: Change hw routine for addition of rtl8192se and rtl8192de
      rtlwifi: rtl8192ce: Change sw and LED routines for addition of rtl8192se and rtl8192de
      rtlwifi: rtl8192ce: Change phy and rc routines for addition of rtl8192se and rtl8192de
      rtlwifi: rtl8192ce: Change rtl8192ce routines phy and trx and modify rtl8192cu for addition of rtl8192se and rtl8192de

Christian Lamparter (4):
      p54: implement multicast filter
      carl9170: improve unicast PS buffering
      mac80211: fix too early reorder release timer
      mac80211: consolidate MIC failure report handling

Don Fry (2):
      iwlagn: mod param cleanup
      iwlagn: semaphore and calib cleanup

Eliad Peller (2):
      wl12xx: set the actual tid instead of the ac
      wl12xx: rearrange some ELP wake_up/sleep calls

Gertjan van Wingerde (2):
      rt2x00: Streamline rt2800 eeprom initialisations.
      rt2x00: Introduce capability flag for Bluetooth co-existence.

Gustavo F. Padovan (11):
      Merge master.kernel.org:/.../padovan/bluetooth-2.6
      Bluetooth: Refactor L2CAP channel allocation
      Bluetooth: Move conf_state to struct l2cap_chan
      Bluetooth: Rename l2cap_do_connect() to l2cap_chan_connect()
      Bluetooth: Move some more elements to struct l2cap_chan
      Bluetooth: Move more vars to struct l2cap_chan
      Bluetooth: Move more channel info to struct l2cap_chan
      Bluetooth: Move more vars to struct l2cap_chan
      Bluetooth: Move conn to struct l2cap_chan
      Bluetooth: Fix memory leak with L2CAP channels
      Bluetooth: Don't export l2cap_sock_ops

Ido Yariv (5):
      wl12xx: Clean up and fix the 128x boot sequence
      wl12xx: Clean up the block size alignment code
      wl12xx: Clean up the dummy packet mechanism
      wl12xx: Simplify TX blocks accounting
      wl12xx: Handle platforms without level trigger interrupts

Ivo van Doorn (4):
      rt2x00: Reduce tx status reading timeout
      rt2x00: Optimize TX_STA_FIFO register reading
      rt2x00: Fix optimize register access for rt2800pci
      rt2x00: Add autowake support for USB hardware

Johan Hedberg (14):
      Bluetooth: Add basic discovery commands to the management interface
      Bluetooth: Add discovering event to the Management interface
      Bluetooth: Add automated SSP user confirmation responses
      Bluetooth: Add variable SSP auto-accept delay support
      Bluetooth: Fix HCI_CONN_AUTH_PEND flag for all authentication requests
      Bluetooth: Add confirm_hint parameter to user confirmation requests
      Bluetooth: Fix reason code for pairing rejection
      Bluetooth: Fix logic in hci_pin_code_request_evt
      Bluetooth: Fix link key persistent storage criteria
      Bluetooth: Fix old_key_type logic for non-persistent keys
      Bluetooth: Fix connection key type updating for buggy controllers
      Bluetooth: Remove old_key_type from mgmt_ev_new_key
      Bluetooth: Add store_hint parameter to mgmt_new_key
      Bluetooth: Fix updating conn->auth_type in hci_io_capa_request_evt

Johannes Berg (18):
      iwlagn: simplify error table reading
      iwlagn: clean up some exit code
      iwlagn: refactor down path
      iwlagn: refactor up path
      iwlagn: extend notification wait function
      iwlagn: make iwlagn_wait_notification return error code
      iwlagn: leave notification waits on firmware errors
      iwlagn: implement synchronous firmware load
      iwlagn: combine firmware code/data
      iwlagn: remove hw_ready variable
      mac80211: tear down BA sessions properly on suspend
      iwlagn: avoid hangs when restarting device
      iwlagn: introduce silent grabbing of NIC access
      iwlagn: refactor restart
      iwlagn: use proper good CRC threshold behaviour
      iwlagn: remove spectrum measurement header
      iwlagn: improve RXON checking
      iwlagn: prefer BSS context

John W. Linville (10):
      Merge branch 'for-linville' of git://git.kernel.org/.../luca/wl12xx
      Merge branch 'wireless-next-2.6' of git://git.kernel.org/.../iwlwifi/iwlwifi-2.6
      Merge branch 'master' of git://git.kernel.org/.../linville/wireless-2.6
      mwl8k: replace rateinfo bitfields with mask and shift macros
      ath5k: fix uninitialized var warning for txf2txs
      b43: avoid uninitialized variable warnings in phy_n
      mwifiex: fix copy-n-paste 'thinko' for tsf_val
      p54: avoid uninitialized variable warning for freq
      Merge branch 'master' of git://git.kernel.org/.../padovan/bluetooth-next-2.6
      Merge branch 'master' of git://git.kernel.org/.../linville/wireless-next-2.6 into for-davem

Juuso Oikarinen (3):
      wl12xx: Fix potential incorrect band in rx-status
      wl12xx: Add mutex protection for interface list
      wl12xx: Handle duplicate calling of remove interface

Larry Finger (2):
      rtlwifi: rtl8192ce: rtl8192cu: Fix most sparse warnings
      rtlwifi: Fix typo in pci.c

Luciano Coelho (11):
      wl12xx: add new board_tcxo_clock element to the platform data
      wl12xx: 1281/1283 support - add block size handling for sdio and spi
      wl12xx: use 1 spare TX block instead of two
      wl12xx: set the skbuff priority for dummy packets
      wl12xx: fix SG BT load value to reflect its new meaning
      wl12xx: fix a couple of sparse warnings about undeclared functions
      wl12xx: use a bitmask instead of list of booleans in scanned_ch
      wl12xx: use kstrtoul functions
      wl12xx: move hardcoded hci_io_ds value into the conf struct
      wl12xx: remove unused conf_radio_params structure
      wl12xx: fix sparse warning about undeclared wl12xx_alloc_dummy_packet

Luis R. Rodriguez (1):
      cfg80211: fix regresion on reg user timeout

Mohammed Shafi Shajakhan (3):
      ath9k: remove the unlikely check for autosleep
      ath9k: Add TSFOOR interrupt stats in debug info
      mac80211: Fix a warning due to skipping tailroom reservation for IV

Nishant Sarmukadam (2):
      mwl8k: Reserve buffers for tx management frames
      mwl8k: Enable life time expiry for tx packets in the hardware

Ohad Ben-Cohen (3):
      wl12xx: update bet_max_consecutive
      wl12xx: fix roaming
      wl12xx: fix "JOIN while associated" commentary

Pradeep Nemavat (2):
      mwl8k: Do not stop tx queues
      mwl8k: Add timestamp information for tx packets

Rafał Miłecki (10):
      ssb: pci: trivial: correct amount of maximum retries
      ssb: cc: use correct min_msk for 0x4312
      ssb: cc: add & fix defines
      ssb: cc: clear GPIOPULL registers on init
      ssb: mark bus as powered up earlier
      ssb: update reject bit for Target State Low
      ssb: pci: separate workarounds
      ssb: pci: update PCIe workarounds
      ssb: pci: early fix for SPROM core index
      ssb: cc: prepare clockmode support for cores rev 10+

Rajkumar Manoharan (3):
      ath9k_hw: Fix Tx IQ Calibration hang issue in AR9003 chips
      ath9k: set beacon related ps flags on bss_info change
      mac80211: Fix warnings due to -Wunused-but-set-variable

Randy Dunlap (1):
      libertas: use kernel-doc notation, fix comment style

Senthil Balasubramanian (5):
      ath9k: Fix LED gpio for AR93xx chipsets.
      ath9k_hw: Fix incorrect baseband PLL phase shift for AR9485
      ath9k: optimize the usage of power save wrappers.
      ath9k: cleanup hw pll work handler
      ath9k: Add power save wrappers and modularize hw_pll handler

Shahar Levi (11):
      wl12xx: 1281/1283 support - move IRQ polarity
      wl12xx: 1281/1283 support - Add Definitions
      wl12xx: 1281/1283 support - Add acx commands
      wl12xx: 1281/1283 support - New radio structs and functions
      wl12xx: 1281/1283 support - Loading FW & NVS
      wl12xx: 1281/1283 support - New boot sequence
      wl12xx: 1281/1283 support - use dynamic memory for the RX/TX pools
      wl12xx: 1281/1283 support - Improve Tx & Rx path
      wl12xx: 1281/1283 support - Add dummy packet support
      wl12xx: 1281/1283 support - enable chip support
      wl12xx: Add support for 11n Rx STBC one spatial stream

Stanislaw Gruszka (12):
      iwlwifi: fix possible data overwrite in hcmd callback
      iwlagn: fix tx power initialization
      iwlegacy: remove duplicate initialization in iwl4956_down()
      iwlegacy: enable only rfkill interrupt when device is down
      iwlegacy: simplify init geos
      iwlegacy: remove unneeded disable_hw_scan check
      iwlegacy: remove unneeded __packed
      iwlegacy: remove scan_tx_antennas
      iwlegacy: comment typo fix diable -> disable
      iwlegacy: fix enqueue hcmd race conditions
      iwlegacy: more priv->mutex serialization
      iwlegacy: remove sync_cmd_mutex

Sujith Manoharan (13):
      ath9k: Fix warnings from -Wunused-but-set-variable
      ath9k_htc: Fix AMPDU subframe handling
      ath9k_htc: Fix max A-MPDU size handling
      ath9k_htc: Use power save wrappers when accessing HW
      ath9k_htc: Remove unused macros and structures
      mac80211: Add new API for rate selection
      ath9k_htc: Increase credit size for AR7010 devices
      ath9k_htc: Remove unused WMI_AGGR_LIMIT_CMD
      ath9k_htc: Add a new WMI command to set a rate mask
      ath9k_htc: Add set_bitrate_mask() callback
      ath9k_htc: Dump base eeprom header for UB91/94/95
      ath9k_htc: Dump modal eeprom header for UB91/94/95
      ath9k_htc: Revamp LED management

Vasanthakumar Thiagarajan (24):
      ath9k_hw: Define devid and mac version for AR9340
      ath9k_hw: Take care of few host interface register changes for AR9340
      ath9k_hw: Get AHB clock information from ath9k_platform_data
      ath9k_hw: Configure pll control register accordingly for AR9340
      ath9k_hw: Add initvals.h for ar9340
      ath9k_hw: Initialize mode registers from initvals.h for AR9340
      ath9k_hw: Don't do ani initialization for AR9340
      ath9k_hw: Initialize tx and rx gain table from initvals.h for ar9340
      ath9k_hw: Read spur frequency information from eeprom for AR9340
      ath9k_hw: Configure RF channel freqency for AR9340
      ath9k_hw: Clean up rx/tx chain configuration before AGC/IQ cal
      ath9k_hw: Fix register offset AR_PHY_65NM_CH0_THERM for AR9340
      ath9k_hw: Don't configure AR_CH0_THERM for AR9340
      ath9k_hw: Skip internal regulator configuration for AR9340
      ath9k_hw: Configure tuning capacitance value for AR9340 as well
      ath9k_hw: Enable byte Tx/Rx data swap for AR9340
      ath9k_hw: Configure chain switch table and attenuation control only for active chains
      ath9k_hw: Read iq calibration data only for active chains
      ath9k: Add AR9340 platform id to id table
      ath9k_hw: Assign macversion based on devid for built-in wmac
      ath9k_hw: Disable INTR_HOST1_FATAL to avoid interrupt strom with ar9430
      ath9k_hw: Enable AR9340 support
      ath9k: Fix bug in configuring hw timer
      ath9k: Fix warning: symbol 'ath9k_platform_id_table' was not declared. Should it be static?

Vivek Natarajan (4):
      ath9k_hw: Move bt_stomp to hw from common.
      ath9k_hw: Add support for btcoexistence in AR9300.
      ath9k_hw: Enable generic timer interrupt.
      ath9k: Use ps wrappers for btcoex logic.

Waldemar Rymarkiewicz (6):
      Bluetooth: Add definitions for link key types
      Bluetooth: Don't modify sec_level if auth failed
      Bluetooth: Map sec_level to link key requirements
      Bluetooth: Ignore key unauthenticated for high security
      Bluetooth: Respect local MITM req in io_cap reply
      Bluetooth: Add secure flag for mgmt_pin_code_req

Wey-Yi Guy (5):
      iwlagn: make rxon_assoc static function
      iwlagn: remove 5000 from rxon_assoc structure
      iwlagn: connect and disconnect sequence for RXON
      iwlagn: new 105 series device
      iwlagn: remove un-necessary debugfs callback

Yogesh Ashok Powar (2):
      mac80211: Skip tailroom reservation for full HW-crypto devices
      mwl8k: Reducing extra_tx_headroom for tx optimization in AP mode

 drivers/net/wireless/ath/ath5k/reset.c             |    5 +
 drivers/net/wireless/ath/ath9k/ahb.c               |    6 +-
 drivers/net/wireless/ath/ath9k/ani.c               |    6 -
 drivers/net/wireless/ath/ath9k/ar9003_calib.c      |  387 ++---
 drivers/net/wireless/ath/ath9k/ar9003_eeprom.c     |   61 +-
 drivers/net/wireless/ath/ath9k/ar9003_hw.c         |  101 ++-
 drivers/net/wireless/ath/ath9k/ar9003_phy.c        |   36 +-
 drivers/net/wireless/ath/ath9k/ar9003_phy.h        |   25 +-
 drivers/net/wireless/ath/ath9k/ar9340_initvals.h   | 1525 ++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/ath9k.h             |    2 +
 drivers/net/wireless/ath/ath9k/beacon.c            |    6 -
 drivers/net/wireless/ath/ath9k/btcoex.c            |  100 ++-
 drivers/net/wireless/ath/ath9k/btcoex.h            |   20 +-
 drivers/net/wireless/ath/ath9k/common.c            |   31 -
 drivers/net/wireless/ath/ath9k/common.h            |    8 -
 drivers/net/wireless/ath/ath9k/debug.c             |    5 +
 drivers/net/wireless/ath/ath9k/debug.h             |    4 +
 drivers/net/wireless/ath/ath9k/eeprom_9287.c       |    3 +-
 drivers/net/wireless/ath/ath9k/eeprom_def.c        |    4 +
 drivers/net/wireless/ath/ath9k/gpio.c              |   19 +-
 drivers/net/wireless/ath/ath9k/hif_usb.h           |    3 +
 drivers/net/wireless/ath/ath9k/htc.h               |   89 +-
 drivers/net/wireless/ath/ath9k/htc_drv_beacon.c    |    6 +-
 drivers/net/wireless/ath/ath9k/htc_drv_debug.c     |  477 ++++++-
 drivers/net/wireless/ath/ath9k/htc_drv_gpio.c      |  204 +---
 drivers/net/wireless/ath/ath9k/htc_drv_init.c      |   41 +-
 drivers/net/wireless/ath/ath9k/htc_drv_main.c      |   95 ++-
 drivers/net/wireless/ath/ath9k/htc_drv_txrx.c      |    2 -
 drivers/net/wireless/ath/ath9k/htc_hst.h           |   11 -
 drivers/net/wireless/ath/ath9k/hw.c                |  125 ++-
 drivers/net/wireless/ath/ath9k/hw.h                |   13 +-
 drivers/net/wireless/ath/ath9k/init.c              |    2 +
 drivers/net/wireless/ath/ath9k/mac.c               |   13 +-
 drivers/net/wireless/ath/ath9k/main.c              |   49 +-
 drivers/net/wireless/ath/ath9k/phy.h               |    3 +
 drivers/net/wireless/ath/ath9k/rc.c                |   12 +-
 drivers/net/wireless/ath/ath9k/recv.c              |    5 +-
 drivers/net/wireless/ath/ath9k/reg.h               |   99 +-
 drivers/net/wireless/ath/ath9k/wmi.c               |    4 +-
 drivers/net/wireless/ath/ath9k/wmi.h               |    2 +-
 drivers/net/wireless/ath/ath9k/xmit.c              |   23 -
 drivers/net/wireless/ath/carl9170/carl9170.h       |    2 +
 drivers/net/wireless/ath/carl9170/main.c           |   92 +--
 drivers/net/wireless/ath/carl9170/tx.c             |  157 ++-
 drivers/net/wireless/b43/phy_n.c                   |    7 +-
 drivers/net/wireless/iwlegacy/iwl-4965-lib.c       |    3 -
 drivers/net/wireless/iwlegacy/iwl-core.c           |   20 +-
 drivers/net/wireless/iwlegacy/iwl-core.h           |    1 -
 drivers/net/wireless/iwlegacy/iwl-dev.h            |    4 +-
 drivers/net/wireless/iwlegacy/iwl-hcmd.c           |    4 +-
 drivers/net/wireless/iwlegacy/iwl-helpers.h        |    6 +
 drivers/net/wireless/iwlegacy/iwl-tx.c             |   52 +-
 drivers/net/wireless/iwlegacy/iwl3945-base.c       |   22 +-
 drivers/net/wireless/iwlegacy/iwl4965-base.c       |   45 +-
 drivers/net/wireless/iwlwifi/Makefile              |    1 -
 drivers/net/wireless/iwlwifi/iwl-1000.c            |   19 +-
 drivers/net/wireless/iwlwifi/iwl-2000.c            |   79 +-
 drivers/net/wireless/iwlwifi/iwl-5000.c            |   36 +-
 drivers/net/wireless/iwlwifi/iwl-6000.c            |   37 +-
 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c     | 1025 -------------
 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h     |   70 -
 drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c      |   41 +-
 drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c        |   50 -
 drivers/net/wireless/iwlwifi/iwl-agn-lib.c         |  124 ++-
 drivers/net/wireless/iwlwifi/iwl-agn-rxon.c        |  259 +++--
 drivers/net/wireless/iwlwifi/iwl-agn-ucode.c       |  245 +++-
 drivers/net/wireless/iwlwifi/iwl-agn.c             |  545 +++-----
 drivers/net/wireless/iwlwifi/iwl-agn.h             |   45 +-
 drivers/net/wireless/iwlwifi/iwl-commands.h        |  105 +-
 drivers/net/wireless/iwlwifi/iwl-core.c            |   87 +-
 drivers/net/wireless/iwlwifi/iwl-core.h            |   23 +-
 drivers/net/wireless/iwlwifi/iwl-debugfs.c         | 1012 +++++++++++++-
 drivers/net/wireless/iwlwifi/iwl-dev.h             |   35 +-
 drivers/net/wireless/iwlwifi/iwl-eeprom.c          |   50 +-
 drivers/net/wireless/iwlwifi/iwl-eeprom.h          |    3 -
 drivers/net/wireless/iwlwifi/iwl-helpers.h         |   24 -
 drivers/net/wireless/iwlwifi/iwl-io.c              |   36 +-
 drivers/net/wireless/iwlwifi/iwl-io.h              |   11 +
 drivers/net/wireless/iwlwifi/iwl-rx.c              |   57 +-
 drivers/net/wireless/iwlwifi/iwl-spectrum.h        |   92 --
 drivers/net/wireless/iwlwifi/iwl-tx.c              |   15 +-
 drivers/net/wireless/libertas/cfg.c                |   45 +-
 drivers/net/wireless/libertas/cmd.c                |  245 ++--
 drivers/net/wireless/libertas/cmdresp.c            |   19 +-
 drivers/net/wireless/libertas/debugfs.c            |   36 +-
 drivers/net/wireless/libertas/decl.h               |    8 +-
 drivers/net/wireless/libertas/defs.h               |  113 +-
 drivers/net/wireless/libertas/dev.h                |   20 +-
 drivers/net/wireless/libertas/ethtool.c            |    3 +-
 drivers/net/wireless/libertas/host.h               |   33 +-
 drivers/net/wireless/libertas/if_cs.c              |   35 +-
 drivers/net/wireless/libertas/if_spi.c             |  134 ++-
 drivers/net/wireless/libertas/if_spi.h             |   68 +-
 drivers/net/wireless/libertas/if_usb.c             |  113 +-
 drivers/net/wireless/libertas/if_usb.h             |   14 +-
 drivers/net/wireless/libertas/main.c               |   99 +-
 drivers/net/wireless/libertas/mesh.c               |  210 ++-
 drivers/net/wireless/libertas/mesh.h               |    6 +-
 drivers/net/wireless/libertas/rx.c                 |   34 +-
 drivers/net/wireless/libertas/tx.c                 |   34 +-
 drivers/net/wireless/libertas/types.h              |   18 +-
 drivers/net/wireless/mwifiex/11n.c                 |  102 +-
 drivers/net/wireless/mwifiex/11n.h                 |    2 +-
 drivers/net/wireless/mwifiex/cfg80211.c            |   61 +-
 drivers/net/wireless/mwifiex/join.c                |    4 +-
 drivers/net/wireless/mwifiex/main.h                |    2 +-
 drivers/net/wireless/mwifiex/scan.c                |   32 +-
 drivers/net/wireless/mwl8k.c                       |  111 +-
 drivers/net/wireless/p54/eeprom.c                  |    2 +-
 drivers/net/wireless/p54/fwio.c                    |   31 +
 drivers/net/wireless/p54/lmac.h                    |    1 +
 drivers/net/wireless/p54/main.c                    |   31 +
 drivers/net/wireless/p54/p54.h                     |    2 +
 drivers/net/wireless/rt2x00/rt2500usb.c            |    1 +
 drivers/net/wireless/rt2x00/rt2800lib.c            |   31 +-
 drivers/net/wireless/rt2x00/rt2800pci.c            |    4 +-
 drivers/net/wireless/rt2x00/rt2800usb.c            |   14 +-
 drivers/net/wireless/rt2x00/rt2x00.h               |   18 +
 drivers/net/wireless/rt2x00/rt2x00config.c         |   31 +
 drivers/net/wireless/rt2x00/rt2x00dev.c            |   88 ++
 drivers/net/wireless/rt2x00/rt2x00usb.c            |   11 +-
 drivers/net/wireless/rt2x00/rt2x00usb.h            |    4 +-
 drivers/net/wireless/rt2x00/rt73usb.c              |    1 +
 drivers/net/wireless/rtlwifi/base.c                |  720 ++++++++--
 drivers/net/wireless/rtlwifi/base.h                |   60 +-
 drivers/net/wireless/rtlwifi/cam.c                 |  106 ++-
 drivers/net/wireless/rtlwifi/cam.h                 |    5 +-
 drivers/net/wireless/rtlwifi/core.c                |  408 ++++--
 drivers/net/wireless/rtlwifi/core.h                |    1 +
 drivers/net/wireless/rtlwifi/efuse.c               |   97 +-
 drivers/net/wireless/rtlwifi/efuse.h               |    5 +-
 drivers/net/wireless/rtlwifi/pci.c                 |  626 ++++++---
 drivers/net/wireless/rtlwifi/pci.h                 |   15 +-
 drivers/net/wireless/rtlwifi/ps.c                  |  258 +++-
 drivers/net/wireless/rtlwifi/ps.h                  |    9 +
 drivers/net/wireless/rtlwifi/rc.c                  |  212 ++--
 drivers/net/wireless/rtlwifi/rc.h                  |    9 +-
 drivers/net/wireless/rtlwifi/regd.c                |   97 +-
 drivers/net/wireless/rtlwifi/regd.h                |    2 +-
 drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c  |  523 ++++++-
 drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h  |    2 +
 drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c  |   81 +-
 drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h  |    4 +-
 drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c |  128 +-
 drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h |   76 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/def.h       |   27 -
 drivers/net/wireless/rtlwifi/rtl8192ce/dm.c        |    2 +
 drivers/net/wireless/rtlwifi/rtl8192ce/dm.h        |    1 +
 drivers/net/wireless/rtlwifi/rtl8192ce/hw.c        |  509 +++++---
 drivers/net/wireless/rtlwifi/rtl8192ce/hw.h        |   34 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/led.c       |    5 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/led.h       |    2 -
 drivers/net/wireless/rtlwifi/rtl8192ce/phy.c       |  223 +--
 drivers/net/wireless/rtlwifi/rtl8192ce/phy.h       |   55 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/reg.h       |   58 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/rf.c        |   24 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/rf.h        |   17 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/sw.c        |  122 ++-
 drivers/net/wireless/rtlwifi/rtl8192ce/sw.h        |   14 +-
 drivers/net/wireless/rtlwifi/rtl8192ce/trx.c       |  180 +--
 drivers/net/wireless/rtlwifi/rtl8192ce/trx.h       |    7 +-
 drivers/net/wireless/rtlwifi/rtl8192cu/hw.c        |   11 +-
 drivers/net/wireless/rtlwifi/rtl8192cu/hw.h        |    5 +-
 drivers/net/wireless/rtlwifi/rtl8192cu/phy.c       |   14 +-
 drivers/net/wireless/rtlwifi/rtl8192cu/phy.h       |   14 +
 drivers/net/wireless/rtlwifi/rtl8192cu/rf.c        |    4 +-
 drivers/net/wireless/rtlwifi/rtl8192cu/rf.h        |    4 +
 drivers/net/wireless/rtlwifi/rtl8192cu/sw.c        |    2 +-
 drivers/net/wireless/rtlwifi/rtl8192cu/trx.c       |   48 +-
 drivers/net/wireless/rtlwifi/rtl8192cu/trx.h       |    5 +-
 drivers/net/wireless/rtlwifi/usb.c                 |   19 +-
 drivers/net/wireless/rtlwifi/usb.h                 |    2 +
 drivers/net/wireless/rtlwifi/wifi.h                |  155 ++-
 drivers/net/wireless/wl12xx/Kconfig                |    2 +-
 drivers/net/wireless/wl12xx/acx.c                  |   93 +-
 drivers/net/wireless/wl12xx/acx.h                  |   23 +-
 drivers/net/wireless/wl12xx/boot.c                 |  285 +++-
 drivers/net/wireless/wl12xx/boot.h                 |   52 +
 drivers/net/wireless/wl12xx/cmd.c                  |   99 ++-
 drivers/net/wireless/wl12xx/cmd.h                  |   34 +
 drivers/net/wireless/wl12xx/conf.h                 |   29 +-
 drivers/net/wireless/wl12xx/debugfs.c              |    2 +-
 drivers/net/wireless/wl12xx/event.c                |   64 +-
 drivers/net/wireless/wl12xx/event.h                |   17 +-
 drivers/net/wireless/wl12xx/ini.h                  |   98 ++-
 drivers/net/wireless/wl12xx/init.c                 |   51 +-
 drivers/net/wireless/wl12xx/init.h                 |    1 +
 drivers/net/wireless/wl12xx/io.c                   |   11 +
 drivers/net/wireless/wl12xx/io.h                   |    3 +
 drivers/net/wireless/wl12xx/main.c                 |  353 ++++-
 drivers/net/wireless/wl12xx/ps.c                   |    3 -
 drivers/net/wireless/wl12xx/reg.h                  |   15 +-
 drivers/net/wireless/wl12xx/rx.c                   |   44 +-
 drivers/net/wireless/wl12xx/scan.c                 |   17 +-
 drivers/net/wireless/wl12xx/sdio.c                 |   27 +-
 drivers/net/wireless/wl12xx/sdio_test.c            |   20 +-
 drivers/net/wireless/wl12xx/spi.c                  |   17 +-
 drivers/net/wireless/wl12xx/testmode.c             |    6 +-
 drivers/net/wireless/wl12xx/tx.c                   |  234 +++-
 drivers/net/wireless/wl12xx/tx.h                   |   60 +-
 drivers/net/wireless/wl12xx/wl12xx.h               |   66 +-
 drivers/ssb/driver_chipcommon.c                    |   68 +-
 drivers/ssb/driver_chipcommon_pmu.c                |    2 +
 drivers/ssb/driver_pcicore.c                       |  131 ++-
 drivers/ssb/main.c                                 |   23 +-
 include/linux/ath9k_platform.h                     |    2 +
 include/linux/ssb/ssb_driver_chipcommon.h          |   11 +-
 include/linux/ssb/ssb_regs.h                       |    2 +-
 include/linux/wl12xx.h                             |   29 +-
 include/net/bluetooth/hci.h                        |    9 +
 include/net/bluetooth/hci_core.h                   |   16 +-
 include/net/bluetooth/l2cap.h                      |   69 +-
 include/net/bluetooth/mgmt.h                       |   10 +-
 include/net/mac80211.h                             |   17 +
 net/bluetooth/cmtp/core.c                          |    3 +-
 net/bluetooth/hci_conn.c                           |   78 +-
 net/bluetooth/hci_core.c                           |   75 +-
 net/bluetooth/hci_event.c                          |  163 ++-
 net/bluetooth/hci_sysfs.c                          |   31 +
 net/bluetooth/hidp/core.c                          |    6 +-
 net/bluetooth/l2cap_core.c                         |  588 ++++----
 net/bluetooth/l2cap_sock.c                         |  242 ++--
 net/bluetooth/mgmt.c                               |   95 ++-
 net/bluetooth/rfcomm/core.c                        |   21 +-
 net/bluetooth/rfcomm/sock.c                        |    5 +-
 net/mac80211/aes_ccm.c                             |    6 +-
 net/mac80211/cfg.c                                 |   15 +-
 net/mac80211/driver-ops.h                          |   18 +
 net/mac80211/driver-trace.h                        |   27 +
 net/mac80211/ibss.c                                |    7 +-
 net/mac80211/ieee80211_i.h                         |    3 +
 net/mac80211/key.c                                 |   21 +-
 net/mac80211/main.c                                |   18 -
 net/mac80211/mesh.c                                |    3 -
 net/mac80211/mesh_hwmp.c                           |    4 -
 net/mac80211/pm.c                                  |   16 +-
 net/mac80211/rx.c                                  |   49 +-
 net/mac80211/sta_info.c                            |    2 -
 net/mac80211/status.c                              |    8 +
 net/mac80211/tx.c                                  |   15 +-
 net/mac80211/work.c                                |    6 +-
 net/mac80211/wpa.c                                 |   62 +-
 net/wireless/core.c                                |   17 +
 net/wireless/reg.c                                 |    3 +-
 244 files changed, 12283 insertions(+), 6490 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath9k/ar9340_initvals.h
 delete mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
 delete mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h
 delete mode 100644 drivers/net/wireless/iwlwifi/iwl-spectrum.h

Omnibus patch available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-next-2.6-2011-05-05.patch.bz2

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [Bugme-new] [Bug 33502] New: Caught 64-bit read from uninitialized memory in __alloc_skb
From: Christoph Lameter @ 2011-05-05 19:05 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Pekka Enberg, casteyde.christian, Andrew Morton, netdev,
	bugzilla-daemon, bugme-daemon, Vegard Nossum
In-Reply-To: <1304621296.3032.98.camel@edumazet-laptop>

On Thu, 5 May 2011, Eric Dumazet wrote:

> > Combining this one with the patch I sent to remove the #ifdeffery would
> > make this much simpler.
>
> I must missed it, could you please resend it ?


Subject: slub: Remove CONFIG_CMPXCHG_LOCAL ifdeffery

Remove the #ifdefs. This means that the irqsafe_cpu_cmpxchg_double() is used
everywhere.

There may be performance implications since:

A. We now have to manage a transaction ID for all arches

B. The interrupt holdoff for arches not supporting CONFIG_CMPXCHG_LOCAL is reduced
to a very short irqoff section.

There are no multiple irqoff/irqon sequences as a result of this change. Even in the fallback
case we only have to do one disable and enable like before.

Signed-off-by: Christoph Lameter <cl@linux.com>

---
 include/linux/slub_def.h |    2 -
 mm/slub.c                |   56 -----------------------------------------------
 2 files changed, 58 deletions(-)

Index: linux-2.6/include/linux/slub_def.h
===================================================================
--- linux-2.6.orig/include/linux/slub_def.h	2011-05-04 09:33:08.000000000 -0500
+++ linux-2.6/include/linux/slub_def.h	2011-05-04 09:42:05.000000000 -0500
@@ -37,9 +37,7 @@ enum stat_item {

 struct kmem_cache_cpu {
 	void **freelist;	/* Pointer to next available object */
-#ifdef CONFIG_CMPXCHG_LOCAL
 	unsigned long tid;	/* Globally unique transaction id */
-#endif
 	struct page *page;	/* The slab from which we are allocating */
 	int node;		/* The node of the page (or -1 for debug) */
 #ifdef CONFIG_SLUB_STATS
Index: linux-2.6/mm/slub.c
===================================================================
--- linux-2.6.orig/mm/slub.c	2011-05-04 09:41:59.000000000 -0500
+++ linux-2.6/mm/slub.c	2011-05-04 09:48:11.000000000 -0500
@@ -1540,7 +1540,6 @@ static void unfreeze_slab(struct kmem_ca
 	}
 }

-#ifdef CONFIG_CMPXCHG_LOCAL
 #ifdef CONFIG_PREEMPT
 /*
  * Calculate the next globally unique transaction for disambiguiation
@@ -1600,17 +1599,12 @@ static inline void note_cmpxchg_failure(
 	stat(s, CMPXCHG_DOUBLE_CPU_FAIL);
 }

-#endif
-
 void init_kmem_cache_cpus(struct kmem_cache *s)
 {
-#ifdef CONFIG_CMPXCHG_LOCAL
 	int cpu;

 	for_each_possible_cpu(cpu)
 		per_cpu_ptr(s->cpu_slab, cpu)->tid = init_tid(cpu);
-#endif
-
 }
 /*
  * Remove the cpu slab
@@ -1643,9 +1637,7 @@ static void deactivate_slab(struct kmem_
 		page->inuse--;
 	}
 	c->page = NULL;
-#ifdef CONFIG_CMPXCHG_LOCAL
 	c->tid = next_tid(c->tid);
-#endif
 	unfreeze_slab(s, page, tail);
 }

@@ -1780,7 +1772,6 @@ static void *__slab_alloc(struct kmem_ca
 {
 	void **object;
 	struct page *new;
-#ifdef CONFIG_CMPXCHG_LOCAL
 	unsigned long flags;

 	local_irq_save(flags);
@@ -1792,7 +1783,6 @@ static void *__slab_alloc(struct kmem_ca
 	 */
 	c = this_cpu_ptr(s->cpu_slab);
 #endif
-#endif

 	/* We handle __GFP_ZERO in the caller */
 	gfpflags &= ~__GFP_ZERO;
@@ -1819,10 +1809,8 @@ load_freelist:
 	c->node = page_to_nid(c->page);
 unlock_out:
 	slab_unlock(c->page);
-#ifdef CONFIG_CMPXCHG_LOCAL
 	c->tid = next_tid(c->tid);
 	local_irq_restore(flags);
-#endif
 	stat(s, ALLOC_SLOWPATH);
 	return object;

@@ -1858,9 +1846,7 @@ new_slab:
 	}
 	if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit())
 		slab_out_of_memory(s, gfpflags, node);
-#ifdef CONFIG_CMPXCHG_LOCAL
 	local_irq_restore(flags);
-#endif
 	return NULL;
 debug:
 	if (!alloc_debug_processing(s, c->page, object, addr))
@@ -1887,20 +1873,12 @@ static __always_inline void *slab_alloc(
 {
 	void **object;
 	struct kmem_cache_cpu *c;
-#ifdef CONFIG_CMPXCHG_LOCAL
 	unsigned long tid;
-#else
-	unsigned long flags;
-#endif

 	if (slab_pre_alloc_hook(s, gfpflags))
 		return NULL;

-#ifndef CONFIG_CMPXCHG_LOCAL
-	local_irq_save(flags);
-#else
 redo:
-#endif

 	/*
 	 * Must read kmem_cache cpu data via this cpu ptr. Preemption is
@@ -1910,7 +1888,6 @@ redo:
 	 */
 	c = __this_cpu_ptr(s->cpu_slab);

-#ifdef CONFIG_CMPXCHG_LOCAL
 	/*
 	 * The transaction ids are globally unique per cpu and per operation on
 	 * a per cpu queue. Thus they can be guarantee that the cmpxchg_double
@@ -1919,7 +1896,6 @@ redo:
 	 */
 	tid = c->tid;
 	barrier();
-#endif

 	object = c->freelist;
 	if (unlikely(!object || !node_match(c, node)))
@@ -1927,7 +1903,6 @@ redo:
 		object = __slab_alloc(s, gfpflags, node, addr, c);

 	else {
-#ifdef CONFIG_CMPXCHG_LOCAL
 		/*
 		 * The cmpxchg will only match if there was no additional
 		 * operation and if we are on the right processor.
@@ -1948,16 +1923,9 @@ redo:
 			note_cmpxchg_failure("slab_alloc", s, tid);
 			goto redo;
 		}
-#else
-		c->freelist = get_freepointer(s, object);
-#endif
 		stat(s, ALLOC_FASTPATH);
 	}

-#ifndef CONFIG_CMPXCHG_LOCAL
-	local_irq_restore(flags);
-#endif
-
 	if (unlikely(gfpflags & __GFP_ZERO) && object)
 		memset(object, 0, s->objsize);

@@ -2034,11 +2002,9 @@ static void __slab_free(struct kmem_cach
 {
 	void *prior;
 	void **object = (void *)x;
-#ifdef CONFIG_CMPXCHG_LOCAL
 	unsigned long flags;

 	local_irq_save(flags);
-#endif
 	slab_lock(page);
 	stat(s, FREE_SLOWPATH);

@@ -2070,9 +2036,7 @@ checks_ok:

 out_unlock:
 	slab_unlock(page);
-#ifdef CONFIG_CMPXCHG_LOCAL
 	local_irq_restore(flags);
-#endif
 	return;

 slab_empty:
@@ -2084,9 +2048,7 @@ slab_empty:
 		stat(s, FREE_REMOVE_PARTIAL);
 	}
 	slab_unlock(page);
-#ifdef CONFIG_CMPXCHG_LOCAL
 	local_irq_restore(flags);
-#endif
 	stat(s, FREE_SLAB);
 	discard_slab(s, page);
 	return;
@@ -2113,20 +2075,11 @@ static __always_inline void slab_free(st
 {
 	void **object = (void *)x;
 	struct kmem_cache_cpu *c;
-#ifdef CONFIG_CMPXCHG_LOCAL
 	unsigned long tid;
-#else
-	unsigned long flags;
-#endif

 	slab_free_hook(s, x);

-#ifndef CONFIG_CMPXCHG_LOCAL
-	local_irq_save(flags);
-
-#else
 redo:
-#endif

 	/*
 	 * Determine the currently cpus per cpu slab.
@@ -2136,15 +2089,12 @@ redo:
 	 */
 	c = __this_cpu_ptr(s->cpu_slab);

-#ifdef CONFIG_CMPXCHG_LOCAL
 	tid = c->tid;
 	barrier();
-#endif

 	if (likely(page == c->page && c->node != NUMA_NO_NODE)) {
 		set_freepointer(s, object, c->freelist);

-#ifdef CONFIG_CMPXCHG_LOCAL
 		if (unlikely(!irqsafe_cpu_cmpxchg_double(
 				s->cpu_slab->freelist, s->cpu_slab->tid,
 				c->freelist, tid,
@@ -2153,16 +2103,10 @@ redo:
 			note_cmpxchg_failure("slab_free", s, tid);
 			goto redo;
 		}
-#else
-		c->freelist = object;
-#endif
 		stat(s, FREE_FASTPATH);
 	} else
 		__slab_free(s, page, x, addr);

-#ifndef CONFIG_CMPXCHG_LOCAL
-	local_irq_restore(flags);
-#endif
 }

 void kmem_cache_free(struct kmem_cache *s, void *x)

^ permalink raw reply

* Re: [PATCH 0/2] wireless: Make and use const struct ieee80211_channel
From: John W. Linville @ 2011-05-05 18:49 UTC (permalink / raw)
  To: Joe Perches
  Cc: linux-wireless, libertas-dev, orinoco-users, orinoco-devel,
	netdev, linux-kernel
In-Reply-To: <cover.1304054543.git.joe@perches.com>

These patches generated a lot of warnings in net/mac80211.  Did you
actually build them?

On Thu, Apr 28, 2011 at 10:25:06PM -0700, Joe Perches wrote:
> Joe Perches (2):
>   wireless: Make struct ieee80211_channel const where possible
>   wireless: Use const struct ieee80211_channel where possible
> 
>  drivers/net/wireless/iwlegacy/iwl-4965-lib.c |    2 +-
>  drivers/net/wireless/iwlegacy/iwl3945-base.c |    2 +-
>  drivers/net/wireless/iwlwifi/iwl-agn-lib.c   |    2 +-
>  drivers/net/wireless/iwmc3200wifi/cfg80211.c |    4 +-
>  drivers/net/wireless/libertas/cfg.c          |    2 +-
>  drivers/net/wireless/mwifiex/cfg80211.c      |    9 ++++---
>  drivers/net/wireless/orinoco/cfg.c           |    2 +-
>  drivers/net/wireless/rndis_wlan.c            |    9 ++++---
>  drivers/net/wireless/wl1251/cmd.c            |    2 +-
>  drivers/net/wireless/wl1251/cmd.h            |    2 +-
>  include/net/cfg80211.h                       |   34 +++++++++++++-------------
>  net/wireless/chan.c                          |   10 ++++----
>  net/wireless/core.h                          |   14 ++++++----
>  net/wireless/debugfs.c                       |    2 +-
>  net/wireless/ibss.c                          |    6 ++--
>  net/wireless/mlme.c                          |   15 ++++++-----
>  net/wireless/nl80211.c                       |   31 ++++++++++++-----------
>  net/wireless/nl80211.h                       |    9 ++++---
>  net/wireless/reg.c                           |   11 ++++----
>  net/wireless/reg.h                           |    4 +-
>  net/wireless/scan.c                          |    6 ++--
>  net/wireless/wext-sme.c                      |    2 +-
>  22 files changed, 94 insertions(+), 86 deletions(-)
> 
> -- 
> 1.7.5.rc3.dirty
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [Bugme-new] [Bug 33502] New: Caught 64-bit read from uninitialized memory in __alloc_skb
From: Eric Dumazet @ 2011-05-05 18:48 UTC (permalink / raw)
  To: Christoph Lameter
  Cc: Pekka Enberg, casteyde.christian, Andrew Morton, netdev,
	bugzilla-daemon, bugme-daemon, Vegard Nossum
In-Reply-To: <alpine.DEB.2.00.1105051339310.6821@router.home>

Le jeudi 05 mai 2011 à 13:40 -0500, Christoph Lameter a écrit :
> On Thu, 5 May 2011, Pekka Enberg wrote:
> 
> > > > -#ifdef CONFIG_CMPXCHG_LOCAL
> > > > +#ifdef SLUB_USE_CMPXCHG_DOUBLE
> > > >   	/*
> > > >   	 * Must align to double word boundary for the double cmpxchg
> > > > instructions
> > > >   	 * to work.
> > > >
> > >
> > >
> > > Is anybody taking the patch and sending it upstream ?
> >
> > Oh, sorry, it got lost in my inbox. I can take care of it.
> 
> Combining this one with the patch I sent to remove the #ifdeffery would
> make this much simpler.

I must missed it, could you please resend it ?

Thanks



^ permalink raw reply

* Re: [Bugme-new] [Bug 33502] New: Caught 64-bit read from uninitialized memory in __alloc_skb
From: Christoph Lameter @ 2011-05-05 18:40 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: Eric Dumazet, casteyde.christian, Andrew Morton, netdev,
	bugzilla-daemon, bugme-daemon, Vegard Nossum
In-Reply-To: <4DC24239.7050806@cs.helsinki.fi>

On Thu, 5 May 2011, Pekka Enberg wrote:

> > > -#ifdef CONFIG_CMPXCHG_LOCAL
> > > +#ifdef SLUB_USE_CMPXCHG_DOUBLE
> > >   	/*
> > >   	 * Must align to double word boundary for the double cmpxchg
> > > instructions
> > >   	 * to work.
> > >
> >
> >
> > Is anybody taking the patch and sending it upstream ?
>
> Oh, sorry, it got lost in my inbox. I can take care of it.

Combining this one with the patch I sent to remove the #ifdeffery would
make this much simpler.


^ permalink raw reply

* Re: [PATCHv4 2/2] tg3: Allow ethtool to enable/disable loopback.
From: Michał Mirosław @ 2011-05-05 18:35 UTC (permalink / raw)
  To: Mahesh Bandewar
  Cc: Matt Carlson, David Miller, netdev, Michael Chan, Tom Herbert
In-Reply-To: <BANLkTin88L+YBrpdaHR57CSx3dg2dMF7Yg@mail.gmail.com>

W dniu 5 maja 2011 19:47 użytkownik Mahesh Bandewar
<maheshb@google.com> napisał:
> On Wed, May 4, 2011 at 11:59 PM, Michał Mirosław <mirqus@gmail.com> wrote:
>> 2011/5/5 Mahesh Bandewar <maheshb@google.com>:
>>> This patch adds tg3_set_features() to handle loopback mode. Currently the
>>> capability is added for the devices which support internal MAC loopback mode.
>>> So when enabled, it enables internal-MAC loopback.
[...]
>>> @@ -9485,6 +9533,15 @@ static int tg3_open(struct net_device *dev)
>>>
>>>        netif_tx_start_all_queues(dev);
>>>
>>> +       /*
>>> +        * Reset loopback feature if it was turned on while the device was down
>>> +        * to avoid and any discrepancy in features reporting.
>>> +        */
>>> +       if (dev->features & NETIF_F_LOOPBACK) {
>>> +               dev->features &= ~NETIF_F_LOOPBACK;
>>> +               dev->wanted_features &= ~NETIF_F_LOOPBACK;
>>> +       }
>>> +
>>
>> if (dev->features & NETIF_F_LOOPBACK)
>>  tg3_set_loopback(dev, dev->features);
>>
> Unfortunately at this stage device will not be able to set-loopback so
> I resorted to clearing the bit(s).

ndo_fix_features+ndo_set_features might be caled before ndo_open - the
first might be just from register_netdev() so even before ndo_open
callback.

>> Whatever you do, don't modify wanted_features in drivers.
> Since just clearing the 'features' would leave wanted_features in
> discrepant state, I thought this will bring it to a sane state. So
> what is a preferred way?

If you really can't do other way, driver should keep additional state
that is checked in ndo_fix_features callback.

>> BTW, similar problems (also like in previous versions) are in
>> forcedeth implementation.
> Yes, whatever we decide about the state of the wanted_features, I'll
> implement similarly for forcedeth. Which previous problem you are
> referring to? Is it the return value? There is a different kind of
> failure (error while writing the register). Since update_features()
> cant handle return value, I'm ignoring the return value. As far as the
> correct return code is concerned, I wasn't sure what is appropriate
> return code here (may be PHY_ERROR would be appropriate there) but
> again I could ignore it just the way rest of the code is ignoring.

Let's wait for this threads points to be resolved. You will probably
change the forcedeth's implementation then anyway. :-)

Best Regards,
Michał Mirosław

^ permalink raw reply

* Re: [PATCH 1/2] net: use NETIF_F_ALL_TSO for vlan features
From: Michał Mirosław @ 2011-05-05 18:19 UTC (permalink / raw)
  To: David Miller; +Cc: shanwei, netdev, eilong, dm, leedom, bhutchings
In-Reply-To: <20110505.105350.183065364.davem@davemloft.net>

2011/5/5 David Miller <davem@davemloft.net>:
> From: Shan Wei <shanwei@cn.fujitsu.com>
> Date: Fri, 29 Apr 2011 13:20:52 +0800
>> As Dimitris Michailidis suggested, use NETIF_F_ALL_TSO for vlan_features,
>> which is a mask, but not hw_features.
> I do not understand why we want to advertise a set of ->vlan_features
> TSO flags that are different from the flags advertised in ->hw_features.
>
> Why do we want to do this?

I remember some posts about hardware that needs HW tag insertion for
TSO on VLAN to work or other additional constraints for offloads on
VLANs. I wonder if vlan_features handling should be converted to
something like ndo_fix_features.

Best Regards,
Michał Mirosław

^ permalink raw reply

* Re: [PATCH] net: Add sendmmsg socket system call
From: David Miller @ 2011-05-05 18:06 UTC (permalink / raw)
  To: anton; +Cc: acme, netdev
In-Reply-To: <20110503162135.5e410fcf@kryten>

From: Anton Blanchard <anton@samba.org>
Date: Tue, 3 May 2011 16:21:35 +1000

> This patch adds a multiple message send syscall and is the send
> version of the existing recvmmsg syscall. This is heavily
> based on the patch by Arnaldo that added recvmmsg.
> 
> I wrote a microbenchmark to test the performance gains of using
> this new syscall:
> 
> http://ozlabs.org/~anton/junkcode/sendmmsg_test.c
> 
> The test was run on a ppc64 box with a 10 Gbit network card. The
> benchmark can send both UDP and RAW ethernet packets.
...
> We see a 20% improvement in throughput on UDP send and 30%
> on raw socket send.
> 
> Signed-off-by: Anton Blanchard <anton@samba.org>

Great work, applied, thanks!

^ permalink raw reply

* Re: [PATCH] can: fix SJA1000 dlc for RTR packets
From: David Miller @ 2011-05-05 18:02 UTC (permalink / raw)
  To: kurt.van.dijck; +Cc: socketcan-core, netdev
In-Reply-To: <20110502145048.GF338@e-circ.dyndns.org>

From: Kurt Van Dijck <kurt.van.dijck@eia.be>
Date: Mon, 2 May 2011 16:50:48 +0200

> RTR frames do have a valid data length code on CAN.
> The driver for SJA1000 did not handle that situation properly.
> 
> Signed-off-by: Kurt Van Dijck <kurt.van.dijck@eia.be>

Applied, thanks.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox