Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] tproxy: nf_tproxy_assign_sock() can handle tw sockets
From: Felipe W Damasio @ 2010-07-14  3:27 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Avi Kivity, David Miller, Patrick McHardy, linux-kernel, netdev
In-Reply-To: <1279077678.2444.95.camel@edumazet-laptop>

Hi Mr. Dumazet,

2010/7/14 Eric Dumazet <eric.dumazet@gmail.com>:
> RDX being the sk pointer (and sk+0x38 contains the corrupted "sk_prot" value)
> , we notice RBP contains same "sk" value + 0x200000  (2 Mbytes).
>
> (same remark on your initial bug report)
>
> Could you enable CONFIG_FRAME_POINTER=y in your config ?

I can, but my bosses will kick my ass if I bring down the ISP again :)

If you think it's the only way to find the problem I'll tell them that
I need to do it. In this case, please tell me what other config
options/tools I can use to get as much info as possible...since I'll
probably be able to test this only once more on the production
environment for debugging purposes.

Cheers,

Felipe Damasio

^ permalink raw reply

* Re: [PATCH RFC] act_cpu: packet distributing
From: Changli Gao @ 2010-07-14  3:27 UTC (permalink / raw)
  To: Jamal Hadi Salim
  Cc: David S. Miller, Patrick McHardy, Tom Herbert, Eric Dumazet,
	netdev, Changli Gao
In-Reply-To: <1279077475-2956-1-git-send-email-xiaosuo@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 666 bytes --]

On Wed, Jul 14, 2010 at 11:17 AM, Changli Gao <xiaosuo@gmail.com> wrote:
> I want to know if I can assign the sk to skb as nf_tproxy_core does to avoid
> the duplicate search later. Thanks.
>
> act_cpu: packet distributing
>
> This TC action can be used to redirect packets to the CPU:
>  * specified by the cpuid option
>  * specified by the class minor ID obtained previously
>  * on which the corresponding application runs
>
> It supports the similar functions of RPS and RFS, but is more flexible.
>
> Signed-off-by: Changli Gao <xiaosuo@gmail.com>

The iproute2 patch against 2.6.31 is attached

-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

[-- Attachment #2: iproute2-act_cpu.diff --]
[-- Type: text/plain, Size: 5350 bytes --]

diff -urN iproute2-2.6.31.orig/include/linux/tc_act/tc_cpu.h iproute2-2.6.31/include/linux/tc_act/tc_cpu.h
--- iproute2-2.6.31.orig/include/linux/tc_act/tc_cpu.h	1970-01-01 08:00:00.000000000 +0800
+++ iproute2-2.6.31/include/linux/tc_act/tc_cpu.h	2010-07-02 16:57:10.000000000 +0800
@@ -0,0 +1,31 @@
+#ifndef __LINUX_TC_CPU_H
+#define __LINUX_TC_CPU_H
+
+#include <linux/pkt_cls.h>
+#include <linux/types.h>
+
+#define TCA_ACT_CPU 12
+
+enum {
+	TCA_CPU_UNSPEC,
+	TCA_CPU_PARMS,
+	TCA_CPU_TM,
+	__TCA_CPU_MAX
+};
+#define TCA_CPU_MAX (__TCA_CPU_MAX - 1)
+
+enum {
+	TCA_CPU_TYPE_MAP,
+	TCA_CPU_TYPE_CPUID,
+	TCA_CPU_TYPE_SOCKET,
+	__TCA_CPU_TYPE_MAX
+};
+#define TCA_CPU_TYPE_MAX (__TCA_CPU_TYPE_MAX - 1)
+
+struct tc_cpu {
+	tc_gen;
+	__u32		type;
+	__u32		value;
+};
+
+#endif /* __LINUX_TC_CPU_H */
diff -urN iproute2-2.6.31.orig/tc/Makefile iproute2-2.6.31/tc/Makefile
--- iproute2-2.6.31.orig/tc/Makefile	2010-07-14 11:21:05.000000000 +0800
+++ iproute2-2.6.31/tc/Makefile	2010-07-02 16:56:41.000000000 +0800
@@ -32,6 +32,7 @@
 TCMODULES += m_gact.o
 TCMODULES += m_mirred.o
 TCMODULES += m_nat.o
+TCMODULES += m_cpu.o
 TCMODULES += m_pedit.o
 TCMODULES += m_skbedit.o
 TCMODULES += p_ip.o
diff -urN iproute2-2.6.31.orig/tc/m_cpu.c iproute2-2.6.31/tc/m_cpu.c
--- iproute2-2.6.31.orig/tc/m_cpu.c	1970-01-01 08:00:00.000000000 +0800
+++ iproute2-2.6.31/tc/m_cpu.c	2010-07-12 16:38:56.000000000 +0800
@@ -0,0 +1,186 @@
+/*
+ * m_cpu.c	Packet distributing module
+ *
+ *		This program is free software; you can distribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Changli Gao <xiaosuo@gmail.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include "utils.h"
+#include "tc_util.h"
+#include <linux/tc_act/tc_cpu.h>
+
+static void
+explain(void)
+{
+	fprintf(stderr, "Usage: ... cpu METHOD\n"
+			"METHOD := { CPUID-SPEC | MAP-SPEC | SOCKET-SPEC }\n"
+			"CPUID-SPEC := cpuid CPUID\n"
+			"MAP-SPEC := map OFFSET\n"
+			"SOCKET-SPEC := socket\n");
+}
+
+static void
+usage(void)
+{
+	explain();
+	exit(-1);
+}
+
+static int
+parse_cpu_args(int *argc_p, char ***argv_p,struct tc_cpu *sel)
+{
+	int argc = *argc_p;
+	char **argv = *argv_p;
+
+	if (argc <= 0)
+		return -1;
+
+	if (matches(*argv, "map") == 0)
+		sel->type = TCA_CPU_TYPE_MAP;
+	else if (matches(*argv, "cpuid") == 0)
+		sel->type = TCA_CPU_TYPE_CPUID;
+	else if (matches(*argv, "socket") == 0) {
+		sel->type = TCA_CPU_TYPE_SOCKET;
+		goto out;
+	} else
+		return -1;
+
+	NEXT_ARG();
+
+	if (get_u32(&sel->value, *argv, 10)) {
+		fprintf(stderr, "Cpu: Illegal \"%s\"\n",
+			sel->type == TCA_CPU_TYPE_CPUID ? "CPUID" : "OFFSET");
+		return -1;
+	}
+
+out:
+	argc--;
+	argv++;
+
+	*argc_p = argc;
+	*argv_p = argv;
+	return 0;
+}
+
+static int
+parse_cpu(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
+{
+	struct tc_cpu sel;
+	int argc = *argc_p;
+	char **argv = *argv_p;
+	struct rtattr *tail;
+
+	memset(&sel, 0, sizeof(sel));
+	sel.action = TC_ACT_STOLEN;
+
+	if (argc <= 0) {
+		explain();
+		return -1;
+	}
+
+	if (matches(*argv, "cpu") == 0) {
+		NEXT_ARG();
+	} else {
+		fprintf(stderr, "cpu bad arguments %s\n", *argv);
+		return -1;
+	}
+
+	if (matches(*argv, "help") == 0)
+		usage();
+	if (parse_cpu_args(&argc, &argv, &sel)) {
+		fprintf(stderr, "Illegal cpu construct (%s) \n", *argv);
+		explain();
+		return -1;
+	}
+
+	while (argc > 0) {
+		if (matches(*argv, "drop") == 0 ||
+		    matches(*argv, "shot") == 0) {
+		    	/* I have set it above */
+			argc--;
+			argv++;
+			continue;
+		} else if (matches(*argv, "index") == 0) {
+			NEXT_ARG();
+			if (get_u32(&sel.index, *argv, 10)) {
+				fprintf(stderr, "Cpu: Illegal \"index\"\n");
+				return -1;
+			}
+			argc--;
+			argv++;
+		} else {
+			fprintf(stderr, "Invalid option: %s\n", *argv);
+			usage();
+		}
+	}
+
+	tail = NLMSG_TAIL(n);
+	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
+	addattr_l(n, MAX_MSG, TCA_CPU_PARMS, &sel, sizeof(sel));
+	tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
+
+	*argc_p = argc;
+	*argv_p = argv;
+	return 0;
+}
+
+static int
+print_cpu(struct action_util *au,FILE * f, struct rtattr *arg)
+{
+	struct tc_cpu *sel;
+	struct rtattr *tb[TCA_CPU_MAX + 1];
+	char buf[12];
+	const static char *type_str[] = {
+		[TCA_CPU_TYPE_MAP] = "map",
+		[TCA_CPU_TYPE_CPUID] = "cpuid",
+		[TCA_CPU_TYPE_SOCKET] = "socket"
+	};
+
+	if (arg == NULL)
+		return -1;
+
+	parse_rtattr_nested(tb, TCA_CPU_MAX, arg);
+
+	if (tb[TCA_CPU_PARMS] == NULL) {
+		fprintf(f, "[NULL cpu parameters]");
+		return -1;
+	}
+	sel = RTA_DATA(tb[TCA_CPU_PARMS]);
+
+	if (sel->type != TCA_CPU_TYPE_SOCKET)
+		sprintf(buf, "%u", sel->value);
+	else
+		buf[0] = '\0';
+
+	fprintf(f, " cpu %s%s%s", type_str[sel->type],
+		sel->type == TCA_CPU_TYPE_SOCKET ? "" : " ", buf);
+
+	if (show_stats) {
+		if (tb[TCA_CPU_TM]) {
+			struct tcf_t *tm = RTA_DATA(tb[TCA_CPU_TM]);
+			print_tm(f,tm);
+		}
+	}
+
+	return 0;
+}
+
+struct action_util cpu_action_util = {
+	.id		= "cpu",
+	.parse_aopt	= parse_cpu,
+	.print_aopt	= print_cpu,
+};

^ permalink raw reply

* Re: [PATCH] tproxy: nf_tproxy_assign_sock() can handle tw sockets
From: Eric Dumazet @ 2010-07-14  3:21 UTC (permalink / raw)
  To: Felipe W Damasio
  Cc: Avi Kivity, David Miller, Patrick McHardy, linux-kernel, netdev
In-Reply-To: <AANLkTilgxvDPpBJvwbw3PHZfXDaa2_6-TbJ8lujz5y3V@mail.gmail.com>

Le mardi 13 juillet 2010 à 17:55 -0300, Felipe W Damasio a écrit :
> Hi Mr. Dumazet,
> 
> I used the patched kernel on the production machine and squid frooze again.
> 
> This is the dmesg message:
> 
> 
> general protection fault: 0000 [#1] SMP
> last sysfs file: /sys/devices/pci0000:00/0000:00:1f.3/i2c-0/name
> CPU 1
> Modules linked in:
> 
> Pid: 5533, comm: squid Not tainted 2.6.34 #6 DX58SO/
> RIP: 0010:[<ffffffff81369b2a>]  [<ffffffff81369b2a>] sock_rfree+0x26/0x37
> RSP: 0018:ffff88042287fc20  EFLAGS: 00010206
> RAX: 66c86f938964c696 RBX: ffff88034e8f9a00 RCX: 0000000000000720
> RDX: ffff8803f0ce05c0 RSI: ffff8803d441960c RDI: ffff88034e8f9a00
> RBP: ffff8803f0ee05c0 R08: ffffea000dcb9998 R09: 0000000000000000
> R10: 000000000003d830 R11: ffff8803f0ee05c0 R12: 00000000000005a8
> R13: 00000000000005a8 R14: 0000000000004378 R15: 0000000000000000
> FS:  00007f4cf33ee710(0000) GS:ffff880001840000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00000000021d5fd0 CR3: 0000000422872000 CR4: 00000000000006e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> Process squid (pid: 5533, threadinfo ffff88042287e000, task ffff88042eb61a40)
> Stack:
>  ffffffff8136ecda ffff88034e8f9a00 ffffffff8136ea8c ffff88034e8f9a00
> <0> ffffffff813ab142 00000000000000d0 ffffffff8136f9f9 000000000eec60e2
> <0> ffff88042eb61a40 ffff88042eb61a40 ffff88042eb61a40 00000000edca7300
> Call Trace:
>  [<ffffffff8136ecda>] ? skb_release_head_state+0x6d/0xb7
>  [<ffffffff8136ea8c>] ? __kfree_skb+0x9/0x7d
>  [<ffffffff813ab142>] ? tcp_recvmsg+0x6a3/0x89a
>  [<ffffffff8136f9f9>] ? __alloc_skb+0x5e/0x14e
>  [<ffffffff81369dde>] ? sock_common_recvmsg+0x30/0x45
>  [<ffffffff81367b0f>] ? sock_aio_read+0xdd/0xf1
>  [<ffffffff813b6c97>] ? tcp_write_xmit+0x93e/0x96c
>  [<ffffffff810ac500>] ? do_sync_read+0xb0/0xf2
>  [<ffffffff810acf32>] ? vfs_read+0xb9/0xff
>  [<ffffffff810ad034>] ? sys_read+0x45/0x6e
>  [<ffffffff8100292b>] ? system_call_fastpath+0x16/0x1b
> Code: ff ff ff ff c3 48 8b 57 18 8b 87 d8 00 00 00 48 8d 8a ac 00 00
> 00 f0 29 82 ac 00 00 00 48 8b 57 18 8b 8f d8 00 00 00 48 8b 42 38 <48>
> 83 b8 b0 00 00 00 00 74 06 01 8a f4 00 00 00 c3 41 57 41 89
> RIP  [<ffffffff81369b2a>] sock_rfree+0x26/0x37
>  RSP <ffff88042287fc20>
> ---[ end trace 22e6ca9ef825c0e6 ]---
> 
> 
> Seems to be the same issue, right?
> 

Exactly the same. Only RAX value is different, its another chain.

BTW, 0x720 is not skb->len like I said earlier, but skb->truesize, and
0x720 is OK on a 64 bit machine for a regular packet.

48 8b 57 18             mov    0x18(%rdi),%rdx     skb->sk
8b 87 d8 00 00 00       mov    0xd8(%rdi),%eax     skb->truesize
48 8d 8a ac 00 00 00    lea 0xac(%rdx),%rcx
f0 29 82 ac 00 00 00    lock sub %eax,0xac(%rdx)
48 8b 57 18             mov    0x18(%rdi),%rdx     skb->sk
8b 8f d8 00 00 00       mov    0xd8(%rdi),%ecx     skb->truesize
48 8b 42 38                  mov    0x38(%rdx),%rax  sk->sk_prot
<48> 83 b8 b0 00 00 00 00    cmpq   $0x0,0xb0(%rax)
74 06 					     je     .+6
01 8a fa 00 00 00       add    %ecx,0xfa(%rdx)


One thing to notice are the RDX and RBP values:

RDX: ffff8803f0ce05c0 
RBP: ffff8803f0ee05c0

RDX being the sk pointer (and sk+0x38 contains the corrupted "sk_prot" value)
, we notice RBP contains same "sk" value + 0x200000  (2 Mbytes).

(same remark on your initial bug report)

Could you enable CONFIG_FRAME_POINTER=y in your config ?

^ permalink raw reply

* [PATCH RFC] act_cpu: packet distributing
From: Changli Gao @ 2010-07-14  3:17 UTC (permalink / raw)
  To: Jamal Hadi Salim
  Cc: David S. Miller, Patrick McHardy, Tom Herbert, Eric Dumazet,
	netdev, Changli Gao

I want to know if I can assign the sk to skb as nf_tproxy_core does to avoid
the duplicate search later. Thanks.

act_cpu: packet distributing

This TC action can be used to redirect packets to the CPU:
 * specified by the cpuid option
 * specified by the class minor ID obtained previously
 * on which the corresponding application runs

It supports the similar functions of RPS and RFS, but is more flexible.

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
----
 include/linux/netdevice.h     |    2 
 include/linux/tc_act/tc_cpu.h |   31 +++++
 include/net/sock.h            |   24 +++
 include/net/tc_act/tc_cpu.h   |   18 ++
 net/core/dev.c                |    4 
 net/core/sock.c               |    1 
 net/sched/Kconfig             |   12 +
 net/sched/Makefile            |    1 
 net/sched/act_cpu.c           |  260 ++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 350 insertions(+), 3 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c4fedf0..318d422 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1435,6 +1435,8 @@ static inline void input_queue_tail_incr_save(struct softnet_data *sd,
 
 DECLARE_PER_CPU_ALIGNED(struct softnet_data, softnet_data);
 
+int enqueue_to_backlog(struct sk_buff *skb, int cpu, unsigned int *qtail);
+
 #define HAVE_NETIF_QUEUE
 
 extern void __netif_schedule(struct Qdisc *q);
diff --git a/include/linux/tc_act/tc_cpu.h b/include/linux/tc_act/tc_cpu.h
new file mode 100644
index 0000000..2704607
--- /dev/null
+++ b/include/linux/tc_act/tc_cpu.h
@@ -0,0 +1,31 @@
+#ifndef __LINUX_TC_CPU_H
+#define __LINUX_TC_CPU_H
+
+#include <linux/pkt_cls.h>
+#include <linux/types.h>
+
+#define TCA_ACT_CPU 12
+
+enum {
+	TCA_CPU_UNSPEC,
+	TCA_CPU_PARMS,
+	TCA_CPU_TM,
+	__TCA_CPU_MAX
+};
+#define TCA_CPU_MAX (__TCA_CPU_MAX - 1)
+
+enum {
+	TCA_CPU_TYPE_MAP,
+	TCA_CPU_TYPE_CPUID,
+	TCA_CPU_TYPE_SOCKET,
+	__TCA_CPU_TYPE_MAX
+};
+#define TCA_CPU_TYPE_MAX (__TCA_CPU_TYPE_MAX - 1)
+
+struct tc_cpu {
+	tc_gen;
+	__u32		type;
+	__u32		value;
+};
+
+#endif /* __LINUX_TC_CPU_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index 3100e71..7913158 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -200,6 +200,7 @@ struct sock_common {
   *	@sk_rcvtimeo: %SO_RCVTIMEO setting
   *	@sk_sndtimeo: %SO_SNDTIMEO setting
   *	@sk_rxhash: flow hash received from netif layer
+  *	@sk_cpu: the CPU on which the corresponding process works.
   *	@sk_filter: socket filtering instructions
   *	@sk_protinfo: private area, net family specific, when not using slab
   *	@sk_timer: sock cleanup timer
@@ -284,6 +285,9 @@ struct sock {
 #ifdef CONFIG_RPS
 	__u32			sk_rxhash;
 #endif
+#if defined(CONFIG_NET_ACT_CPU) || defined(CONFIG_NET_ACT_CPU_MODULE)
+	int			sk_cpu;
+#endif
 	unsigned long 		sk_flags;
 	unsigned long	        sk_lingertime;
 	struct sk_buff_head	sk_error_queue;
@@ -639,7 +643,24 @@ static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 	return sk->sk_backlog_rcv(sk, skb);
 }
 
-static inline void sock_rps_record_flow(const struct sock *sk)
+static inline void sock_reset_cpu(struct sock *sk)
+{
+#if defined(CONFIG_NET_ACT_CPU) || defined(CONFIG_NET_ACT_CPU_MODULE)
+	sk->sk_cpu = nr_cpumask_bits;
+#endif
+}
+
+static inline void sock_save_cpu(struct sock *sk)
+{
+#if defined(CONFIG_NET_ACT_CPU) || defined(CONFIG_NET_ACT_CPU_MODULE)
+	int cpu = get_cpu();
+	if (sk->sk_cpu != cpu)
+		sk->sk_cpu = cpu;
+	put_cpu();
+#endif
+}
+
+static inline void sock_rps_record_flow(struct sock *sk)
 {
 #ifdef CONFIG_RPS
 	struct rps_sock_flow_table *sock_flow_table;
@@ -649,6 +670,7 @@ static inline void sock_rps_record_flow(const struct sock *sk)
 	rps_record_sock_flow(sock_flow_table, sk->sk_rxhash);
 	rcu_read_unlock();
 #endif
+	sock_save_cpu(sk);
 }
 
 static inline void sock_rps_reset_flow(const struct sock *sk)
diff --git a/include/net/tc_act/tc_cpu.h b/include/net/tc_act/tc_cpu.h
new file mode 100644
index 0000000..0504bf0
--- /dev/null
+++ b/include/net/tc_act/tc_cpu.h
@@ -0,0 +1,18 @@
+#ifndef __NET_TC_CPU_H
+#define __NET_TC_CPU_H
+
+#include <linux/types.h>
+#include <net/act_api.h>
+
+struct tcf_cpu {
+	struct tcf_common	common;
+	u32			type;
+	u32			value;
+};
+
+static inline struct tcf_cpu *to_tcf_cpu(struct tcf_common *pc)
+{
+	return container_of(pc, struct tcf_cpu, common);
+}
+
+#endif /* __NET_TC_CPU_H */
diff --git a/net/core/dev.c b/net/core/dev.c
index e2b9fa2..45e8a21 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2443,8 +2443,7 @@ static int rps_ipi_queued(struct softnet_data *sd)
  * enqueue_to_backlog is called to queue an skb to a per CPU backlog
  * queue (may be a remote CPU queue).
  */
-static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
-			      unsigned int *qtail)
+int enqueue_to_backlog(struct sk_buff *skb, int cpu, unsigned int *qtail)
 {
 	struct softnet_data *sd;
 	unsigned long flags;
@@ -2482,6 +2481,7 @@ enqueue:
 	kfree_skb(skb);
 	return NET_RX_DROP;
 }
+EXPORT_SYMBOL(enqueue_to_backlog);
 
 /**
  *	netif_rx	-	post buffer to the network code
diff --git a/net/core/sock.c b/net/core/sock.c
index 363bc26..7a71e76 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1045,6 +1045,7 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
 		if (!try_module_get(prot->owner))
 			goto out_free_sec;
 		sk_tx_queue_clear(sk);
+		sock_reset_cpu(sk);
 	}
 
 	return sk;
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 2f691fb..a826758 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -427,6 +427,18 @@ config NET_CLS_ACT
 	  A recent version of the iproute2 package is required to use
 	  extended matches.
 
+config NET_ACT_CPU
+        tristate "Packet distributing"
+        depends on NET_CLS_ACT
+        depends on RPS
+        ---help---
+	  Say Y here to do packets distributing. With it, you can distribute
+	  the packets among the CPUs on the system in any way as you like. It
+	  only works in ingress.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called act_cpu.
+
 config NET_ACT_POLICE
 	tristate "Traffic Policing"
         depends on NET_CLS_ACT 
diff --git a/net/sched/Makefile b/net/sched/Makefile
index f14e71b..a9e0b96 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -7,6 +7,7 @@ obj-y	:= sch_generic.o sch_mq.o
 obj-$(CONFIG_NET_SCHED)		+= sch_api.o sch_blackhole.o
 obj-$(CONFIG_NET_CLS)		+= cls_api.o
 obj-$(CONFIG_NET_CLS_ACT)	+= act_api.o
+obj-$(CONFIG_NET_ACT_CPU)	+= act_cpu.o
 obj-$(CONFIG_NET_ACT_POLICE)	+= act_police.o
 obj-$(CONFIG_NET_ACT_GACT)	+= act_gact.o
 obj-$(CONFIG_NET_ACT_MIRRED)	+= act_mirred.o
diff --git a/net/sched/act_cpu.c b/net/sched/act_cpu.c
new file mode 100644
index 0000000..6b7d7fc
--- /dev/null
+++ b/net/sched/act_cpu.c
@@ -0,0 +1,260 @@
+/*
+ * Packet distributing actions
+ *
+ * Copyright (c) 2010- Changli Gao <xiaosuo@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <net/net_namespace.h>
+#include <net/netlink.h>
+#include <net/pkt_sched.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <linux/tc_act/tc_cpu.h>
+#include <net/tc_act/tc_cpu.h>
+
+#define CPU_TAB_MASK     15
+static struct tcf_common *tcf_cpu_ht[CPU_TAB_MASK + 1];
+static u32 cpu_idx_gen;
+static DEFINE_RWLOCK(cpu_lock);
+
+static struct tcf_hashinfo cpu_hash_info = {
+	.htab	= tcf_cpu_ht,
+	.hmask	= CPU_TAB_MASK,
+	.lock	= &cpu_lock
+};
+
+static const struct nla_policy cpu_policy[TCA_CPU_MAX + 1] = {
+	[TCA_CPU_PARMS]	= { .len = sizeof(struct tc_cpu) },
+};
+
+static int tcf_cpu_init(struct nlattr *nla, struct nlattr *est,
+			struct tc_action *a, int ovr, int bind)
+{
+	struct nlattr *tb[TCA_CPU_MAX + 1];
+	struct tc_cpu *parm;
+	struct tcf_cpu *p;
+	struct tcf_common *pc;
+	int ret;
+
+	if (nla == NULL)
+		return -EINVAL;
+	ret = nla_parse_nested(tb, TCA_CPU_MAX, nla, cpu_policy);
+	if (ret < 0)
+		return ret;
+	if (tb[TCA_CPU_PARMS] == NULL)
+		return -EINVAL;
+	parm = nla_data(tb[TCA_CPU_PARMS]);
+	if (parm->type > TCA_CPU_TYPE_MAX || parm->action != TC_ACT_STOLEN)
+		return -EINVAL;
+
+	pc = tcf_hash_check(parm->index, a, bind, &cpu_hash_info);
+	if (!pc) {
+		pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind,
+				     &cpu_idx_gen, &cpu_hash_info);
+		if (IS_ERR(pc))
+			return PTR_ERR(pc);
+		ret = ACT_P_CREATED;
+	} else {
+		if (!ovr) {
+			tcf_hash_release(pc, bind, &cpu_hash_info);
+			return -EEXIST;
+		}
+		ret = 0;
+	}
+	p = to_tcf_cpu(pc);
+
+	spin_lock_bh(&p->tcf_lock);
+	p->type = parm->type;
+	p->value = parm->value;
+	p->tcf_action = parm->action;
+	spin_unlock_bh(&p->tcf_lock);
+
+	if (ret == ACT_P_CREATED)
+		tcf_hash_insert(pc, &cpu_hash_info);
+
+	return ret;
+}
+
+static int tcf_cpu_cleanup(struct tc_action *a, int bind)
+{
+	struct tcf_cpu *p = a->priv;
+
+	return tcf_hash_release(&p->common, bind, &cpu_hash_info);
+}
+
+static int tcf_cpu_from_sock(struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	struct sock *sk;
+	struct {
+		__be16 source, dest;
+	} *ports;
+	int cpu;
+
+	if (skb->dev == NULL || skb->protocol != __constant_htons(ETH_P_IP))
+		goto err;
+	if (!pskb_may_pull(skb, sizeof(*iph)))
+		goto err;
+	iph = (struct iphdr *) skb->data;
+	if (!pskb_may_pull(skb, iph->ihl * 4 + 4))
+		goto err;
+	ports = (void *) (skb->data + iph->ihl * 4);
+	switch (iph->protocol) {
+	case IPPROTO_TCP:
+		sk = __inet_lookup(dev_net(skb->dev), &tcp_hashinfo, iph->saddr,
+				   ports->source, iph->daddr, ports->dest,
+				   skb->dev->ifindex);
+		break;
+	case IPPROTO_UDP:
+		sk = udp4_lib_lookup(dev_net(skb->dev), iph->saddr,
+				     ports->source, iph->daddr, ports->dest,
+				     skb->dev->ifindex);
+		break;
+	default:
+		goto err;
+	}
+
+	if (!sk)
+		goto err;
+	cpu = sk->sk_cpu;
+	if (sk->sk_protocol == IPPROTO_TCP && sk->sk_state == TCP_TIME_WAIT)
+		inet_twsk_put(inet_twsk(sk));
+	else
+		sock_put(sk);
+
+	return cpu;
+
+err:
+	return smp_processor_id();
+}
+
+static int tcf_cpu(struct sk_buff *skb, struct tc_action *a,
+		   struct tcf_result *res)
+{
+	struct tcf_cpu *p = a->priv;
+	u32 type;
+	u32 value;
+	int cpu, action;
+	struct sk_buff *nskb;
+	unsigned int qtail;
+
+	spin_lock(&p->tcf_lock);
+	p->tcf_tm.lastuse = jiffies;
+	p->tcf_bstats.bytes += qdisc_pkt_len(skb);
+	p->tcf_bstats.packets++;
+	type = p->type;
+	value = p->value;
+	action = p->tcf_action;
+	spin_unlock(&p->tcf_lock);
+
+	if (G_TC_AT(skb->tc_verd) & AT_EGRESS) {
+		if (net_ratelimit())
+			pr_notice("act_cpu only works in ingress!\n");
+		goto drop;
+	}
+
+	nskb = skb_act_clone(skb, GFP_ATOMIC, action);
+	if (nskb == NULL)
+		goto drop;
+	nskb->tc_verd = 0;
+	nskb->tc_verd = SET_TC_NCLS(nskb->tc_verd);
+
+	switch (type) {
+	case TCA_CPU_TYPE_MAP:
+		cpu = TC_H_MIN(res->classid) - value;
+		break;
+	case TCA_CPU_TYPE_CPUID:
+		cpu = value;
+		break;
+	case TCA_CPU_TYPE_SOCKET:
+		cpu = tcf_cpu_from_sock(nskb);
+		break;
+	default:
+		kfree_skb(nskb);
+		goto drop;
+	}
+	if (cpu >= nr_cpumask_bits || !cpu_online(cpu))
+		cpu = smp_processor_id();
+
+	if (enqueue_to_backlog(nskb, cpu, &qtail) != NET_RX_SUCCESS)
+		goto drop;
+
+	return action;
+
+drop:
+	spin_lock(&p->tcf_lock);
+	p->tcf_qstats.drops++;
+	spin_unlock(&p->tcf_lock);
+	return TC_ACT_SHOT;
+}
+
+static int tcf_cpu_dump(struct sk_buff *skb, struct tc_action *a, int bind,
+			int ref)
+{
+	unsigned char *b = skb_tail_pointer(skb);
+	struct tcf_cpu *p = a->priv;
+	struct tc_cpu opt;
+	struct tcf_t t;
+
+	opt.index = p->tcf_index;
+	opt.action = p->tcf_action;
+	opt.refcnt = p->tcf_refcnt - ref;
+	opt.bindcnt = p->tcf_bindcnt - bind;
+	opt.type = p->type;
+	opt.value = p->value;
+	NLA_PUT(skb, TCA_CPU_PARMS, sizeof(opt), &opt);
+	t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install);
+	t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse);
+	t.expires = jiffies_to_clock_t(p->tcf_tm.expires);
+	NLA_PUT(skb, TCA_CPU_TM, sizeof(t), &t);
+	return skb->len;
+
+nla_put_failure:
+	nlmsg_trim(skb, b);
+	return -1;
+}
+
+static struct tc_action_ops act_cpu_ops = {
+	.kind		=	"cpu",
+	.hinfo		=	&cpu_hash_info,
+	.type		=	TCA_ACT_CPU,
+	.capab		=	TCA_CAP_NONE,
+	.owner		=	THIS_MODULE,
+	.act		=	tcf_cpu,
+	.dump		=	tcf_cpu_dump,
+	.cleanup	=	tcf_cpu_cleanup,
+	.lookup		=	tcf_hash_search,
+	.init		=	tcf_cpu_init,
+	.walk		=	tcf_generic_walker
+};
+
+MODULE_AUTHOR("Changli Gao <xiaosuo@gmail.com>");
+MODULE_DESCRIPTION("Packet distributing actions");
+MODULE_LICENSE("GPL");
+
+static int __init cpu_init_module(void)
+{
+	return tcf_register_action(&act_cpu_ops);
+}
+
+static void __exit cpu_cleanup_module(void)
+{
+	tcf_unregister_action(&act_cpu_ops);
+}
+
+module_init(cpu_init_module);
+module_exit(cpu_cleanup_module);

^ permalink raw reply related

* [PATCH 2.6.35-rc1] net-next: vmxnet3 fixes [5/5] Respect the interrupt type in VM configuration
From: Shreyas Bhatewara @ 2010-07-14  0:51 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel, pv-drivers
In-Reply-To: <alpine.LRH.2.00.1007070232300.5939@localhost.localdomain>


Do not ignore interrupt type in VM configuration

When interrupt type is not auto, do not ignore the interrupt type set from
VM configuration.
Driver may not always respect the interrupt type in configuration but it 
will certainly try to. Eg: if MSIx is configured and enabling MSIx fails 
in driver, it fall back on MSI and then on INTx.

Signed-off-by: Shreyas Bhatewara <sbhatewara@vmware.com>

---

 drivers/net/vmxnet3/vmxnet3_drv.c     |   13 ++++++++++---
 drivers/net/vmxnet3/vmxnet3_ethtool.c |    2 +-
 drivers/net/vmxnet3/vmxnet3_int.h     |    6 +++---
 3 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index ffd6a9b..74fe3f0 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2355,9 +2355,13 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
 	adapter->intr.mask_mode = (cfg >> 2) & 0x3;
 
 	if (adapter->intr.type == VMXNET3_IT_AUTO) {
-		int err;
+		adapter->intr.type = VMXNET3_IT_MSIX;
+	}
 
 #ifdef CONFIG_PCI_MSI
+	if (adapter->intr.type == VMXNET3_IT_MSIX) {
+		int err;
+
 		adapter->intr.msix_entries[0].entry = 0;
 		err = pci_enable_msix(adapter->pdev, adapter->intr.msix_entries,
 				      VMXNET3_LINUX_MAX_MSIX_VECT);
@@ -2366,15 +2370,18 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
 			adapter->intr.type = VMXNET3_IT_MSIX;
 			return;
 		}
-#endif
+		adapter->intr.type = VMXNET3_IT_MSI;
+	}
 
+	if (adapter->intr.type == VMXNET3_IT_MSI) {
+		int err;
 		err = pci_enable_msi(adapter->pdev);
 		if (!err) {
 			adapter->intr.num_intrs = 1;
-			adapter->intr.type = VMXNET3_IT_MSI;
 			return;
 		}
 	}
+#endif /* CONFIG_PCI_MSI */
 
 	adapter->intr.type = VMXNET3_IT_INTX;
 
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index de1ba14..52128c7 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -291,7 +291,7 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data)
 
 		/* update harware LRO capability accordingly */
 		if (lro_requested)
-			adapter->shared->devRead.misc.uptFeatures &= UPT1_F_LRO;
+			adapter->shared->devRead.misc.uptFeatures |= UPT1_F_LRO;
 		else
 			adapter->shared->devRead.misc.uptFeatures &=
 								~UPT1_F_LRO;
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index bbed330..d17fae6 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -68,10 +68,10 @@
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.0.5.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.0.13.0-k"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01000500
+#define VMXNET3_DRIVER_VERSION_NUM      0x01000B00
 
 
 /*
@@ -150,7 +150,7 @@ vmxnet3_cmd_ring_desc_avail(struct vmxnet3_cmd_ring *ring)
 }
 
 static inline bool
-vmxnet3_cmd_ring_desc_empty(struct vmxnet3_cmd_ring *ring)
+vmxnet3_cmd_ring_desc_empty(const struct vmxnet3_cmd_ring *ring)
 {
 	return (ring->next2comp == ring->next2fill);
 }


^ permalink raw reply related

* [PATCH 2.6.35-rc1] net-next: vmxnet3 fixes [4/5] Do not reset when the device is not opened
From: Shreyas Bhatewara @ 2010-07-14  0:49 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel, pv-drivers, ronghua, matthieu
In-Reply-To: <alpine.LRH.2.00.1007070229030.5939@localhost.localdomain>


Do not reset when the device is not opened

If a reset is scheduled, and the device goes thru close and open, it
may happen that reset and open may run in parallel.
The reset code now bails out if the device is not opened.
 
Signed-off-by: Ronghua Zang <ronghua@vmware.com>
Signed-off-by: Matthieu Bucchianeri <matthieu@vmware.com>
Signed-off-by: Shreyas Bhatewara <sbhatewara@vmware.com>

---

 drivers/net/vmxnet3/vmxnet3_drv.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 1e31d40..ffd6a9b 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2417,8 +2417,9 @@ vmxnet3_reset_work(struct work_struct *data)
 	if (test_and_set_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))
 		return;
 
-	/* if the device is closed, we must leave it alone */
-	if (netif_running(adapter->netdev)) {
+	/* if the device is closed or is being opened, we must leave it alone */
+	if (netif_running(adapter->netdev) &&
+	    (adapter->netdev->flags & IFF_UP)) {
 		printk(KERN_INFO "%s: resetting\n", adapter->netdev->name);
 		vmxnet3_quiesce_dev(adapter);
 		vmxnet3_reset_dev(adapter);

^ permalink raw reply related

* [PATCH 2.6.35-rc1] net-next: vmxnet3 fixes [3/5] Initialize link state at probe time
From: Shreyas Bhatewara @ 2010-07-14  0:48 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel, pv-drivers
In-Reply-To: <alpine.LRH.2.00.1007070202080.5939@localhost.localdomain>


Initialize vmxnet3 link state at probe time

This change initializes the state of link at the time when driver is
loaded. The ethtool output for 'link detected' and 'link speed'
is thus valid even before the interface is brought up.

Signed-off-by: Shreyas Bhatewara <sbhatewara@vmware.com>

---
 drivers/net/vmxnet3/vmxnet3_drv.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 7792a44..1e31d40 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -130,7 +130,7 @@ vmxnet3_tq_stop(struct vmxnet3_tx_queue *tq, struct vmxnet3_adapter *adapter)
  * Check the link state. This may start or stop the tx queue.
  */
 static void
-vmxnet3_check_link(struct vmxnet3_adapter *adapter)
+vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue)
 {
 	u32 ret;
 
@@ -143,14 +143,16 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter)
 		if (!netif_carrier_ok(adapter->netdev))
 			netif_carrier_on(adapter->netdev);
 
-		vmxnet3_tq_start(&adapter->tx_queue, adapter);
+		if (affectTxQueue)
+			vmxnet3_tq_start(&adapter->tx_queue, adapter);
 	} else {
 		printk(KERN_INFO "%s: NIC Link is Down\n",
 		       adapter->netdev->name);
 		if (netif_carrier_ok(adapter->netdev))
 			netif_carrier_off(adapter->netdev);
 
-		vmxnet3_tq_stop(&adapter->tx_queue, adapter);
+		if (affectTxQueue)
+			vmxnet3_tq_stop(&adapter->tx_queue, adapter);
 	}
 }
 
@@ -165,7 +167,7 @@ vmxnet3_process_events(struct vmxnet3_adapter *adapter)
 
 	/* Check if link state has changed */
 	if (events & VMXNET3_ECR_LINK)
-		vmxnet3_check_link(adapter);
+		vmxnet3_check_link(adapter, true);
 
 	/* Check if there is an error on xmit/recv queues */
 	if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) {
@@ -1947,7 +1949,7 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
 	 * Check link state when first activating device. It will start the
 	 * tx queue if the link is up.
 	 */
-	vmxnet3_check_link(adapter);
+	vmxnet3_check_link(adapter, true);
 
 	napi_enable(&adapter->napi);
 	vmxnet3_enable_all_intrs(adapter);
@@ -2549,6 +2551,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 	}
 
 	set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
+	vmxnet3_check_link(adapter, false);
 	atomic_inc(&devices_found);
 	return 0;

^ permalink raw reply related

* [PATCH 2.6.35-rc1] net-next: vmxnet3 fixes [2/5] Interrupt control bitmap
From: Shreyas Bhatewara @ 2010-07-14  0:48 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel, pv-drivers, ronghua
In-Reply-To: <alpine.LRH.2.00.1007070222110.6105@localhost.localdomain>


A new bit map 'intrCtrl' is introduced in the DriverShared area. The driver
should update VMXNET3_IC_DISABLE_ALL bit before writing IMR.

Signed-off-by: Ronghua Zang <ronghua@vmware.com>
Signed-off-by: Shreyas Bhatewara <sbhatewara@vmware.com>

---

 drivers/net/vmxnet3/vmxnet3_defs.h |    6 +++++-
 drivers/net/vmxnet3/vmxnet3_drv.c  |    3 +++
 2 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/drivers/net/vmxnet3/vmxnet3_defs.h b/drivers/net/vmxnet3/vmxnet3_defs.h
index b4889e6..ca7727b 100644
--- a/drivers/net/vmxnet3/vmxnet3_defs.h
+++ b/drivers/net/vmxnet3/vmxnet3_defs.h
@@ -464,6 +464,9 @@ enum vmxnet3_intr_type {
 /* addition 1 for events */
 #define VMXNET3_MAX_INTRS      25
 
+/* value of intrCtrl */
+#define VMXNET3_IC_DISABLE_ALL  0x1   /* bit 0 */
+
 
 struct Vmxnet3_IntrConf {
 	bool		autoMask;
@@ -471,7 +474,8 @@ struct Vmxnet3_IntrConf {
 	u8		eventIntrIdx;
 	u8		modLevels[VMXNET3_MAX_INTRS];	/* moderation level for
 							 * each intr */
-	__le32		reserved[3];
+	__le32		intrCtrl;
+	__le32		reserved[2];
 };
 
 /* one bit per VLAN ID, the size is in the units of u32	*/
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 5a50d10..7792a44 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -72,6 +72,7 @@ vmxnet3_enable_all_intrs(struct vmxnet3_adapter *adapter)
 
 	for (i = 0; i < adapter->intr.num_intrs; i++)
 		vmxnet3_enable_intr(adapter, i);
+	adapter->shared->devRead.intrConf.intrCtrl &= ~VMXNET3_IC_DISABLE_ALL;
 }
 
 
@@ -80,6 +81,7 @@ vmxnet3_disable_all_intrs(struct vmxnet3_adapter *adapter)
 {
 	int i;
 
+	adapter->shared->devRead.intrConf.intrCtrl |= VMXNET3_IC_DISABLE_ALL;
 	for (i = 0; i < adapter->intr.num_intrs; i++)
 		vmxnet3_disable_intr(adapter, i);
 }
@@ -1880,6 +1882,7 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter)
 		devRead->intrConf.modLevels[i] = adapter->intr.mod_levels[i];
 
 	devRead->intrConf.eventIntrIdx = adapter->intr.event_intr_idx;
+	devRead->intrConf.intrCtrl |= VMXNET3_IC_DISABLE_ALL;
 
 	/* rx filter settings */
 	devRead->rxFilterConf.rxMode = 0;

^ permalink raw reply related

* [PATCH 2.6.35-rc1] net-next: vmxnet3 fixes [1/5] Spare skb to avoid starvation
From: Shreyas Bhatewara @ 2010-07-14  0:46 UTC (permalink / raw)
  To: netdev, davidm; +Cc: pv-drivers
In-Reply-To: <alpine.LRH.2.00.1007070214400.6105@localhost.localdomain>


skb_alloc() failure can cause the ring to loose all packet reception. Avoid
this by introducing a spare buffer. The spare skb is only used when the ring
is "empty" and an skb allocation failure would cause the ring to starve. It is
never handed up to netif_rx(), and instead, when the rx_interrupt occurs, the
skb is shuffled back to reuse. Further use the incoming receive packet
interrupts as events to poll for skb allocation.


Signed-off-by: Michael Stolarchuk <stolarchuk@vmware.com>
Signed-off-by: Shreyas Bhatewara <sbhatewara@vmware.com>

---
 drivers/net/vmxnet3/vmxnet3_drv.c |   61 +++++++++++++++++++++++++++++++++++--
 drivers/net/vmxnet3/vmxnet3_int.h |   12 ++++++-
 2 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 989b742..5a50d10 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -541,7 +541,12 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx,
 							 NET_IP_ALIGN);
 				if (unlikely(rbi->skb == NULL)) {
 					rq->stats.rx_buf_alloc_failure++;
-					break;
+					/* starvation prevention */
+					if (vmxnet3_cmd_ring_desc_empty(
+							rq->rx_ring + ring_idx))
+						rbi->skb = rq->spare_skb;
+					else
+						break;
 				}
 				rbi->skb->dev = adapter->netdev;
 
@@ -611,6 +616,29 @@ vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd,
 }
 
 
+/*
+ * Free any pages which were attached to the frags of the spare skb.  This can
+ * happen when the spare skb is attached to the rx ring to prevent starvation,
+ * but there was no issue with page allocation.
+ */
+
+static void
+vmxnet3_rx_spare_skb_free_frags(struct vmxnet3_adapter *adapter)
+{
+	struct sk_buff *skb = adapter->rx_queue.spare_skb;
+	int i;
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+		BUG_ON(frag->page != 0);
+		put_page(frag->page);
+		frag->page = 0;
+		frag->size = 0;
+	}
+	skb_shinfo(skb)->nr_frags = 0;
+	skb->data_len = 0;
+}
+
+
 static void
 vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
 		struct vmxnet3_tx_queue *tq, struct pci_dev *pdev,
@@ -1060,8 +1088,12 @@ vmxnet3_rx_error(struct vmxnet3_rx_queue *rq, struct Vmxnet3_RxCompDesc *rcd,
 	 * ctx->skb may be NULL if this is the first and the only one
 	 * desc for the pkt
 	 */
-	if (ctx->skb)
-		dev_kfree_skb_irq(ctx->skb);
+	if (ctx->skb) {
+		if (ctx->skb == rq->spare_skb)
+			vmxnet3_rx_spare_skb_free_frags(adapter);
+		else
+			dev_kfree_skb_irq(ctx->skb);
+	}
 
 	ctx->skb = NULL;
 }
@@ -1159,6 +1191,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
 
 		skb = ctx->skb;
 		if (rcd->eop) {
+			if (skb == rq->spare_skb) {
+				rq->stats.drop_total++;
+				vmxnet3_rx_spare_skb_free_frags(adapter);
+				ctx->skb = NULL;
+				goto rcd_done;
+			}
 			skb->len += skb->data_len;
 			skb->truesize += skb->data_len;
 
@@ -1244,6 +1282,14 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_queue *rq,
 		rq->uncommitted[ring_idx] = 0;
 	}
 
+	/* free starvation prevention skb if allocated */
+	if (rq->spare_skb) {
+		vmxnet3_rx_spare_skb_free_frags(adapter);
+		dev_kfree_skb(rq->spare_skb);
+		rq->spare_skb = NULL;
+	}
+
+
 	rq->comp_ring.gen = VMXNET3_INIT_GEN;
 	rq->comp_ring.next2proc = 0;
 }
@@ -1325,6 +1371,15 @@ vmxnet3_rq_init(struct vmxnet3_rx_queue *rq,
 	}
 	vmxnet3_rq_alloc_rx_buf(rq, 1, rq->rx_ring[1].size - 1, adapter);
 
+	/* allocate ring starvation protection */
+	rq->spare_skb = dev_alloc_skb(PAGE_SIZE);
+	if (rq->spare_skb == NULL) {
+		vmxnet3_rq_cleanup(rq, adapter);
+		return -ENOMEM;
+	}
+
+
+
 	/* reset the comp ring */
 	rq->comp_ring.next2proc = 0;
 	memset(rq->comp_ring.base, 0, rq->comp_ring.size *
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 34f392f..bbed330 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -149,6 +149,13 @@ vmxnet3_cmd_ring_desc_avail(struct vmxnet3_cmd_ring *ring)
 		ring->next2comp - ring->next2fill - 1;
 }
 
+static inline bool
+vmxnet3_cmd_ring_desc_empty(struct vmxnet3_cmd_ring *ring)
+{
+	return (ring->next2comp == ring->next2fill);
+}
+
+
 struct vmxnet3_comp_ring {
 	union Vmxnet3_GenericDesc *base;
 	u32               size;
@@ -266,9 +273,10 @@ struct vmxnet3_rx_queue {
 	u32 qid2;           /* rqID in RCD for buffer from 2nd ring */
 	u32 uncommitted[2]; /* # of buffers allocated since last RXPROD
 				* update */
-	struct vmxnet3_rx_buf_info     *buf_info[2];
-	struct Vmxnet3_RxQueueCtrl            *shared;
+	struct vmxnet3_rx_buf_info	*buf_info[2];
+	struct Vmxnet3_RxQueueCtrl	*shared;
 	struct vmxnet3_rq_driver_stats  stats;
+	struct sk_buff			*spare_skb;      /* starvation skb */
 } __attribute__((__aligned__(SMP_CACHE_BYTES)));
 
 #define VMXNET3_LINUX_MAX_MSIX_VECT     1


^ permalink raw reply related

* Re: [Pv-drivers] RFC: Network Plugin Architecture (NPA) for vmxnet3
From: Stephen Hemminger @ 2010-07-14  0:31 UTC (permalink / raw)
  To: Shreyas Bhatewara
  Cc: Christoph Hellwig, Pankaj Thakkar, pv-drivers@vmware.com,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	virtualization@lists.linux-foundation.org
In-Reply-To: <1278990388.32650.22.camel@eng-rhel5-64>

On Mon, 12 Jul 2010 20:06:28 -0700
Shreyas Bhatewara <sbhatewara@vmware.com> wrote:

> 
> On Thu, 2010-05-06 at 13:21 -0700, Christoph Hellwig wrote:
> > On Wed, May 05, 2010 at 10:52:53AM -0700, Stephen Hemminger wrote:
> > > Let me put it bluntly. Any design that allows external code to run
> > > in the kernel is not going to be accepted.  Out of tree kernel modules are enough
> > > of a pain already, why do you expect the developers to add another
> > > interface.
> > 
> > Exactly.  Until our friends at VMware get this basic fact it's useless
> > to continue arguing.
> > 
> > Pankaj and Dmitry: you're fine to waste your time on this, but it's not
> > going to go anywhere until you address that fundamental problem.  The
> > first thing you need to fix in your archicture is to integrate the VF
> > function code into the kernel tree, and we can work from there.
> > 
> > Please post patches doing this if you want to resume the discussion.
> > 
> > _______________________________________________
> > Pv-drivers mailing list
> > Pv-drivers@vmware.com
> > http://mailman2.vmware.com/mailman/listinfo/pv-drivers
> 
> 
> As discussed, following is the patch to give you an idea
> about implementation of NPA for vmxnet3 driver. Although the
> patch is big, I have verified it with checkpatch.pl. It gave
> 0 errors / warnings.
> 
> Signed-off-by: Matthieu Bucchaineri <matthieu@vmware.com>
> Signed-off-by: Shreyas Bhatewara <sbhatewara@vmware.com>
> ---

I am surprised, the code seems to use lots of mixed case in places
that don't really follow current kernel practice.


^ permalink raw reply

* Re: pull request: wireless-next-2.6 2010-07-13
From: David Miller @ 2010-07-13 21:36 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev
In-Reply-To: <20100713203639.GE3835@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Tue, 13 Jul 2010 16:36:40 -0400

> Here is the latest batch of wireless LAN goodies intended for 2.6.36.
> It is more-or-less the usual batch of driver updates, including ath9k,
> iwlwifi, rt2x00, and wl1271.  The usual flurry of mac80211 updates is
> missing, due mostly to Johannes attending to a personal obligation of a
> happy nature. :-)
> 
> Please let me know if there are problems!

Pulled, but please be on the lookout for things that add uses
of "attribute ((packed))" instead of "__packed".

Eric Dumazet converted all of drivers/net and I've been endlessly
seeing partial reverts and new additions of the explicit attribute in
wireless commits.

For example, see the things that got added to iwlwifi this time around.

Please fix them up, all of them, for the next pull request I see from
you.

Thanks!

^ permalink raw reply

* Re: [PATCH] tc35815: fix iomap leak
From: David Miller @ 2010-07-13 21:24 UTC (permalink / raw)
  To: anemo; +Cc: segooon, kernel-janitors, jpirko, eric.dumazet, adobriyan, netdev
In-Reply-To: <20100713.221428.74744945.anemo@mba.ocn.ne.jp>

From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Tue, 13 Jul 2010 22:14:28 +0900 (JST)

> On Sat, 10 Jul 2010 14:03:18 +0400, Kulikov Vasiliy <segooon@gmail.com> wrote:
>> If tc35815_init_one() fails we must unmap mapped regions.
>> 
>> Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
>> ---
>>  drivers/net/tc35815.c |    4 +++-
>>  1 files changed, 3 insertions(+), 1 deletions(-)
> 
> No, pcim_xxx APIs are _managed_ interfaces.  These resources are
> released automatically.  Actually currently nobody in kernel call
> pcim_iounmap_regions() now.
> 
> And _if_ there is any reason to call pcim_iounmap_regions()
> explicitly, it should be called in tc35815_remove_one() too.
> 
> So, NAK.

I've reverted this patch, thanks.

Can someone go over the other similar patches I applied already to
net-next-2.6 to see if they have the same problem?  If so I'll revert
them too.

BTW, I think from one perspective the pcim_*() APIs make it harder to
audit a driver because resource management is magic and implicit
rather than explicit.  It adds an extra step to the audit, and I
don't see any effort being made to do a mass conversion of all
drivers to pcim_xxx which would be the only way in my mind for this
to truly make it easier to audit drivers for resource leak problems.

If both driver types (pcim_xxx and non-pcim_xxx) exist, it just means
more work for auditors as they have oen more thing to check for
instead of less things.

^ permalink raw reply

* Re: [PATCH] tproxy: nf_tproxy_assign_sock() can handle tw sockets
From: Felipe W Damasio @ 2010-07-13 21:06 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Avi Kivity, David Miller, Patrick McHardy, linux-kernel, netdev
In-Reply-To: <AANLkTilgxvDPpBJvwbw3PHZfXDaa2_6-TbJ8lujz5y3V@mail.gmail.com>

Hi,

2010/7/13 Felipe W Damasio <felipewd@gmail.com>:
> This is the dmesg message:

This error happened at 17:19:59.

A few seconds earlier, I have these on squid's logs:

2010/07/13 17:19:50| clientTryParseRequest: FD 1690
(189.113.65.55:52681) Invalid Request
2010/07/13 17:19:50| clientTryParseRequest: FD 5056
(189.113.74.101:2420) Invalid Request
2010/07/13 17:19:52| clientTryParseRequest: FD 26923
(189.113.74.101:2419) Invalid Request
2010/07/13 17:19:57| parseHttpRequest: Unsupported method 'PASS'
2010/07/13 17:19:57| clientTryParseRequest: FD 17786
(189.113.69.194:2422) Invalid Request
2010/07/13 17:19:57| parseHttpRequest: Unsupported method '<D2>Yk'
2010/07/13 17:19:57| clientTryParseRequest: FD 22554
(189.113.79.151:4225) Invalid Request
2010/07/13 17:19:59| httpReadReply: Excess data from "GET
http://webcs.msg.yahoo.com/crossdomain.xml"

 Maybe with these two errors we can create some kind of trigger
program to help us duplicate this on the lab setup?

 Cheers,

Felipe Damasio

^ permalink raw reply

* Re: [PATCH] tproxy: nf_tproxy_assign_sock() can handle tw sockets
From: Felipe W Damasio @ 2010-07-13 20:55 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Avi Kivity, David Miller, Patrick McHardy, linux-kernel, netdev
In-Reply-To: <1279036193.2634.468.camel@edumazet-laptop>

Hi Mr. Dumazet,

I used the patched kernel on the production machine and squid frooze again.

This is the dmesg message:


general protection fault: 0000 [#1] SMP
last sysfs file: /sys/devices/pci0000:00/0000:00:1f.3/i2c-0/name
CPU 1
Modules linked in:

Pid: 5533, comm: squid Not tainted 2.6.34 #6 DX58SO/
RIP: 0010:[<ffffffff81369b2a>]  [<ffffffff81369b2a>] sock_rfree+0x26/0x37
RSP: 0018:ffff88042287fc20  EFLAGS: 00010206
RAX: 66c86f938964c696 RBX: ffff88034e8f9a00 RCX: 0000000000000720
RDX: ffff8803f0ce05c0 RSI: ffff8803d441960c RDI: ffff88034e8f9a00
RBP: ffff8803f0ee05c0 R08: ffffea000dcb9998 R09: 0000000000000000
R10: 000000000003d830 R11: ffff8803f0ee05c0 R12: 00000000000005a8
R13: 00000000000005a8 R14: 0000000000004378 R15: 0000000000000000
FS:  00007f4cf33ee710(0000) GS:ffff880001840000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000021d5fd0 CR3: 0000000422872000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process squid (pid: 5533, threadinfo ffff88042287e000, task ffff88042eb61a40)
Stack:
 ffffffff8136ecda ffff88034e8f9a00 ffffffff8136ea8c ffff88034e8f9a00
<0> ffffffff813ab142 00000000000000d0 ffffffff8136f9f9 000000000eec60e2
<0> ffff88042eb61a40 ffff88042eb61a40 ffff88042eb61a40 00000000edca7300
Call Trace:
 [<ffffffff8136ecda>] ? skb_release_head_state+0x6d/0xb7
 [<ffffffff8136ea8c>] ? __kfree_skb+0x9/0x7d
 [<ffffffff813ab142>] ? tcp_recvmsg+0x6a3/0x89a
 [<ffffffff8136f9f9>] ? __alloc_skb+0x5e/0x14e
 [<ffffffff81369dde>] ? sock_common_recvmsg+0x30/0x45
 [<ffffffff81367b0f>] ? sock_aio_read+0xdd/0xf1
 [<ffffffff813b6c97>] ? tcp_write_xmit+0x93e/0x96c
 [<ffffffff810ac500>] ? do_sync_read+0xb0/0xf2
 [<ffffffff810acf32>] ? vfs_read+0xb9/0xff
 [<ffffffff810ad034>] ? sys_read+0x45/0x6e
 [<ffffffff8100292b>] ? system_call_fastpath+0x16/0x1b
Code: ff ff ff ff c3 48 8b 57 18 8b 87 d8 00 00 00 48 8d 8a ac 00 00
00 f0 29 82 ac 00 00 00 48 8b 57 18 8b 8f d8 00 00 00 48 8b 42 38 <48>
83 b8 b0 00 00 00 00 74 06 01 8a f4 00 00 00 c3 41 57 41 89
RIP  [<ffffffff81369b2a>] sock_rfree+0x26/0x37
 RSP <ffff88042287fc20>
---[ end trace 22e6ca9ef825c0e6 ]---


Seems to be the same issue, right?

Cheers,

Felipe Damasio





2010/7/13 Eric Dumazet <eric.dumazet@gmail.com>:
> Le mardi 13 juillet 2010 à 11:49 -0300, Felipe W Damasio a écrit :
>> Hi Mr. Dumazet,
>>
>> 2010/7/13 Eric Dumazet <eric.dumazet@gmail.com>:
>> > I currently have no fresh ideas. If you want this problem to be solved,
>> > its important to setup in your lab a workload to trigger again and again
>> > the bug, in order to provide us more crash information.
>>
>>  Right. I've been running non-stop since the first bug happened, but
>> so far the problem hasn't surfaced again :-(
>>
>>  I've been using the kernel with the patch that you provided me
>> (nf_tproxy.c). Is there a chance that patch fixed the problem?
>
> This is a real bug, but I dont think it can fix your problem.
>
> Looking again at your crash, we see RCX=0x720, decimal 1824
>
> As its skb->len, we are freeing an skb that was collapsed or something
> like that, since 1824 > 1460 (the normal MSS on ethernet)
>
> GRO is off on your machine.
>
> But coincidently 0x0720 is also a blank char for VGA screen...
> (0x20 : ASCII space, 0x07 : default attribute)
>
> So maybe you hit a corruption outside of network stack.
>
>
>
>

^ permalink raw reply

* pull request: wireless-next-2.6 2010-07-13
From: John W. Linville @ 2010-07-13 20:36 UTC (permalink / raw)
  To: davem; +Cc: linux-wireless, netdev

Dave,

Here is the latest batch of wireless LAN goodies intended for 2.6.36.
It is more-or-less the usual batch of driver updates, including ath9k,
iwlwifi, rt2x00, and wl1271.  The usual flurry of mac80211 updates is
missing, due mostly to Johannes attending to a personal obligation of a
happy nature. :-)

Please let me know if there are problems!

Thanks,

John

---

The following changes since commit 242647bcf8464860f173f3d4d4ab3490d3558518:

  hso: remove driver version (2010-07-12 21:21:27 -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

Ameya Palande (1):
      wl12xx: Use MODULE_ALIAS macro at correct postion for SPI bus

Amitkumar Karwar (1):
      libertas: Added support for host sleep feature

Christian Lamparter (1):
      p54: update MAINTAINERS

Dan Carpenter (2):
      prism54: call BUG_ON() earlier
      hostap: fixup strlen() math

Emmanuel Grumbach (1):
      iwlagn: fix the bit mask of a FH register in stop Tx DMA flow

Felix Fietkau (16):
      ath9k_hw: fix a few inconsistencies in initval array names
      ath9k_hw: reformat the ar5008, ar9001 and ar9002 initvals to match ar9003
      ath9k_hw: sync initvals for ar9001 and ar9002 with Atheros
      ath9k_hw: sanitize noise floor values properly on all chips
      ath9k_hw: clean up the noise floor calibration code to reduce code duplication
      ath9k: fix false positives in the baseband hang check
      ath9k: fix crash with WEP in ad-hoc mode
      ath9k: fix a potential buffer leak in the STA teardown path
      ath9k: fix a buffer leak in A-MPDU completion
      ath9k_hw: fix antenna diversity on AR9285
      ath9k_hw: fix a sign error in the IQ calibration code
      ath9k_hw: fix an off-by-one error in the PDADC boundaries calculation
      ath9k_hw: prevent a fast channel change after a rx DMA stuck issue
      ath9k_hw: report the TID in the tx status on AR5008-AR9002
      ath9k: validate the TID in the tx status information
      ath9k: merge noisefloor load implementations

Helmut Schaa (9):
      rt2x00: Limit txpower by eeprom values
      rt2x00: Convert rt2x00 to use threaded interrupts
      rt2x00: Allow beacon update without scheduling a work
      rt2x00: Implement broad- and multicast buffering
      rt2x00: Use pretbtt irq for fetching beacons on rt2800pci
      rt2x00: Use separate mac80211_ops for rt2800pci and rt2800usb
      rt2x00: Remove set_tim callback from PCI drivers
      rt2x00: Don't initialize beacon interval to 0 on rt2800 devices
      rt2x00: Add missing TSF sync mode for AP operation

Ivo van Doorn (8):
      rt2x00: Convert AGC value from descriptor to RSSI (dBm)
      rt2x00: Rename CONFIG_DISABLE_LINK_TUNING
      rt2x00: Disable link tuning while scanning
      rt2x00: Fix vgc_level_reg handling
      rt2x00: Implement watchdog monitoring
      rt2x00: Make rt2800_write_beacon only export to GPL
      rt2x00: Move common firmware loading into rt2800lib
      rt2x00: Move driver callback functions into the ops structure

Jay Sternberg (1):
      iwlwifi: correct descriptions of advanced ucode errors

Jiri Slaby (1):
      NET: nl80211, fix lock imbalance and netdev referencing

Johannes Berg (1):
      cfg80211: ignore spurious deauth

John W. Linville (5):
      Merge branch 'wireless-next-2.6' of git://git.kernel.org/.../iwlwifi/iwlwifi-2.6
      mac80211: remove wep dependency
      MAINTAINERS: mark adm8211 as an orphan
      Merge branch 'master' of git://git.kernel.org/.../linville/wireless-2.6
      Merge branch 'master' of git://git.kernel.org/.../linville/wireless-next-2.6 into for-davem

Juuso Oikarinen (9):
      wl1271: Remove calibration from join command
      wl1271: Add TSF handling
      wl1271: Use the ARP configuration function from mac80211
      wl1271: Use all basic rates for ps-poll, instead of just the slowest
      wl1271: Work around AP's with broken ps-poll functionality
      wl1271: Update hardware ARP filtering configuration handling
      wl1271: Disable dynamic PS based on BT co-ext sense events
      wl1271: Fix warning when disconnecting and ad-hoc network
      wl1271: Update interface to temporarily disable dynamic PS

Kulikov Vasiliy (1):
      adm8211: fix memory leak

Luciano Coelho (5):
      wl1271: read fem manufacturer value from nvs
      wl1271: moved scan operations to a separate file
      wl1271: rewritten scanning code
      wl1271: use per-channel max tx power passed by mac80211 when scanning
      wl1271: use __packed annotation

Ming Lei (2):
      minstrel_ht: fix updating rate with best probability
      minstrel_ht: fix check for downgrading of top2 rate

Rajkumar Manoharan (1):
      ath9k_htc: fix memory leak in ath9k_hif_usb_alloc_urbs

Reinette Chatre (1):
      iwlwifi: remove key information during device restart

Shanyu Zhao (1):
      iwlwifi: enable 6050 series Gen2 devices

Wey-Yi Guy (9):
      iwlwifi: fix fw_restart module parameter
      iwlwifi: add debug print for parsing firmware TLV
      iwlwifi: tx fifo queue flush command
      iwlwifi: add mac80211 flush callback support
      iwlwifi: add support for device tx flush request
      iwlwifi: debugfs file for txfifo command testing
      iwlwifi: generic parameter define for _agn device
      iwlwifi: adding enhance sensitivity table entries
      iwlagn: more generic description for iwlagn devices

 MAINTAINERS                                      |    9 +-
 drivers/net/wireless/adm8211.c                   |    5 +-
 drivers/net/wireless/ath/ath9k/ar5008_initvals.h | 1319 ++--
 drivers/net/wireless/ath/ath9k/ar5008_phy.c      |  129 +-
 drivers/net/wireless/ath/ath9k/ar9001_initvals.h | 2479 +++---
 drivers/net/wireless/ath/ath9k/ar9002_calib.c    |    2 +-
 drivers/net/wireless/ath/ath9k/ar9002_hw.c       |   12 +-
 drivers/net/wireless/ath/ath9k/ar9002_initvals.h |10152 +++++++++++-----------
 drivers/net/wireless/ath/ath9k/ar9002_mac.c      |    1 +
 drivers/net/wireless/ath/ath9k/ar9002_phy.c      |   69 +-
 drivers/net/wireless/ath/ath9k/ar9002_phy.h      |   26 +
 drivers/net/wireless/ath/ath9k/ar9003_eeprom.c   |    2 +-
 drivers/net/wireless/ath/ath9k/ar9003_mac.h      |    3 -
 drivers/net/wireless/ath/ath9k/ar9003_phy.c      |  213 +-
 drivers/net/wireless/ath/ath9k/ath9k.h           |    2 +
 drivers/net/wireless/ath/ath9k/calib.c           |  153 +-
 drivers/net/wireless/ath/ath9k/calib.h           |    7 +-
 drivers/net/wireless/ath/ath9k/common.c          |    4 +
 drivers/net/wireless/ath/ath9k/eeprom.h          |    2 +-
 drivers/net/wireless/ath/ath9k/eeprom_4k.c       |    4 +-
 drivers/net/wireless/ath/ath9k/eeprom_9287.c     |    4 +-
 drivers/net/wireless/ath/ath9k/eeprom_def.c      |    6 +-
 drivers/net/wireless/ath/ath9k/hif_usb.c         |    8 +-
 drivers/net/wireless/ath/ath9k/hw-ops.h          |    6 -
 drivers/net/wireless/ath/ath9k/hw.c              |    7 +-
 drivers/net/wireless/ath/ath9k/hw.h              |   23 +-
 drivers/net/wireless/ath/ath9k/init.c            |    1 +
 drivers/net/wireless/ath/ath9k/mac.h             |    3 +
 drivers/net/wireless/ath/ath9k/main.c            |   27 +-
 drivers/net/wireless/ath/ath9k/xmit.c            |   65 +-
 drivers/net/wireless/hostap/hostap_main.c        |    2 +-
 drivers/net/wireless/iwlwifi/Kconfig             |    9 +-
 drivers/net/wireless/iwlwifi/iwl-1000.c          |    6 +-
 drivers/net/wireless/iwlwifi/iwl-5000.c          |   12 +-
 drivers/net/wireless/iwlwifi/iwl-6000.c          |   44 +-
 drivers/net/wireless/iwlwifi/iwl-agn-calib.c     |  133 +-
 drivers/net/wireless/iwlwifi/iwl-agn-lib.c       |   82 +-
 drivers/net/wireless/iwlwifi/iwl-agn-tx.c        |    7 +-
 drivers/net/wireless/iwlwifi/iwl-agn.c           |  209 +-
 drivers/net/wireless/iwlwifi/iwl-agn.h           |    4 +
 drivers/net/wireless/iwlwifi/iwl-commands.h      |   85 +-
 drivers/net/wireless/iwlwifi/iwl-core.c          |   31 +-
 drivers/net/wireless/iwlwifi/iwl-core.h          |    5 +-
 drivers/net/wireless/iwlwifi/iwl-csr.h           |    1 +
 drivers/net/wireless/iwlwifi/iwl-debugfs.c       |   29 +-
 drivers/net/wireless/iwlwifi/iwl-dev.h           |    4 +
 drivers/net/wireless/iwlwifi/iwl-eeprom.h        |    4 +
 drivers/net/wireless/iwlwifi/iwl-fh.h            |    7 +-
 drivers/net/wireless/iwlwifi/iwl-hcmd.c          |    1 +
 drivers/net/wireless/iwlwifi/iwl-rx.c            |    4 +-
 drivers/net/wireless/iwlwifi/iwl-sta.h           |   11 +
 drivers/net/wireless/libertas/README             |   12 +
 drivers/net/wireless/libertas/cmd.c              |   61 +-
 drivers/net/wireless/libertas/cmd.h              |    2 +
 drivers/net/wireless/libertas/debugfs.c          |   66 +
 drivers/net/wireless/libertas/main.c             |   34 +-
 drivers/net/wireless/prism54/isl_ioctl.c         |    2 +-
 drivers/net/wireless/rt2x00/rt2400pci.c          |   69 +-
 drivers/net/wireless/rt2x00/rt2500pci.c          |   71 +-
 drivers/net/wireless/rt2x00/rt2500usb.c          |   14 +-
 drivers/net/wireless/rt2x00/rt2800.h             |   30 +-
 drivers/net/wireless/rt2x00/rt2800lib.c          |  434 +-
 drivers/net/wireless/rt2x00/rt2800lib.h          |   43 +-
 drivers/net/wireless/rt2x00/rt2800pci.c          |  229 +-
 drivers/net/wireless/rt2x00/rt2800usb.c          |  178 +-
 drivers/net/wireless/rt2x00/rt2x00.h             |   25 +-
 drivers/net/wireless/rt2x00/rt2x00config.c       |    4 +-
 drivers/net/wireless/rt2x00/rt2x00dev.c          |   96 +-
 drivers/net/wireless/rt2x00/rt2x00lib.h          |   26 +-
 drivers/net/wireless/rt2x00/rt2x00link.c         |   65 +-
 drivers/net/wireless/rt2x00/rt2x00mac.c          |   50 +-
 drivers/net/wireless/rt2x00/rt2x00pci.c          |    6 +-
 drivers/net/wireless/rt2x00/rt2x00queue.c        |    4 +
 drivers/net/wireless/rt2x00/rt2x00queue.h        |   11 +
 drivers/net/wireless/rt2x00/rt2x00reg.h          |    5 +-
 drivers/net/wireless/rt2x00/rt2x00usb.c          |   50 +
 drivers/net/wireless/rt2x00/rt2x00usb.h          |   10 +
 drivers/net/wireless/rt2x00/rt61pci.c            |   68 +-
 drivers/net/wireless/rt2x00/rt73usb.c            |    7 +
 drivers/net/wireless/wl12xx/Makefile             |    2 +-
 drivers/net/wireless/wl12xx/wl1251_main.c        |    1 -
 drivers/net/wireless/wl12xx/wl1251_spi.c         |    1 +
 drivers/net/wireless/wl12xx/wl1271.h             |   24 +-
 drivers/net/wireless/wl12xx/wl1271_acx.c         |   41 +-
 drivers/net/wireless/wl12xx/wl1271_acx.h         |   15 +-
 drivers/net/wireless/wl12xx/wl1271_boot.c        |    4 +-
 drivers/net/wireless/wl12xx/wl1271_cmd.c         |  248 +-
 drivers/net/wireless/wl12xx/wl1271_cmd.h         |   68 -
 drivers/net/wireless/wl12xx/wl1271_conf.h        |   16 +-
 drivers/net/wireless/wl12xx/wl1271_event.c       |   99 +-
 drivers/net/wireless/wl12xx/wl1271_event.h       |    1 +
 drivers/net/wireless/wl12xx/wl1271_main.c        |  174 +-
 drivers/net/wireless/wl12xx/wl1271_rx.c          |    6 -
 drivers/net/wireless/wl12xx/wl1271_scan.c        |  257 +
 drivers/net/wireless/wl12xx/wl1271_scan.h        |  109 +
 drivers/net/wireless/wl12xx/wl1271_spi.c         |    1 +
 net/mac80211/cfg.c                               |    5 +
 net/mac80211/main.c                              |    5 +-
 net/mac80211/rc80211_minstrel_ht.c               |    6 +-
 net/mac80211/tkip.c                              |    8 +-
 net/mac80211/tkip.h                              |    2 +-
 net/mac80211/wep.c                               |   24 +-
 net/mac80211/wep.h                               |    2 +-
 net/mac80211/wpa.c                               |    5 +-
 net/wireless/mlme.c                              |    8 +-
 net/wireless/nl80211.c                           |    2 +-
 106 files changed, 9722 insertions(+), 8517 deletions(-)
 create mode 100644 drivers/net/wireless/wl12xx/wl1271_scan.c
 create mode 100644 drivers/net/wireless/wl12xx/wl1271_scan.h

Omnibus patch is available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-next-2.6-2010-07-13.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: [PATCH -mmotm 05/30] mm: sl[au]b: add knowledge of reserve pages
From: Pekka Enberg @ 2010-07-13 20:33 UTC (permalink / raw)
  To: Xiaotian Feng
  Cc: linux-mm-Bw31MaZKKs3YtjvyW6yDsg, linux-nfs-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, riel-H+wXaHxf7aLQT0dZR+AlfA,
	cl-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	a.p.zijlstra-/NLkJaSkS4VmR6Xm/wNWPw,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, lwang-H+wXaHxf7aLQT0dZR+AlfA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <20100713101747.2835.45722.sendpatchset-bd3XojVv5Xrm7B5McmCzzQ@public.gmane.org>

Hi Xiaotian!

I would actually prefer that the SLAB, SLOB, and SLUB changes were in
separate patches to make reviewing easier.

Looking at SLUB:

On Tue, Jul 13, 2010 at 1:17 PM, Xiaotian Feng <dfeng-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> diff --git a/mm/slub.c b/mm/slub.c
> index 7bb7940..7a5d6dc 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -27,6 +27,8 @@
>  #include <linux/memory.h>
>  #include <linux/math64.h>
>  #include <linux/fault-inject.h>
> +#include "internal.h"
> +
>
>  /*
>  * Lock order:
> @@ -1139,7 +1141,8 @@ static void setup_object(struct kmem_cache *s, struct page *page,
>                s->ctor(object);
>  }
>
> -static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
> +static
> +struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node, int *reserve)
>  {
>        struct page *page;
>        void *start;
> @@ -1153,6 +1156,8 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
>        if (!page)
>                goto out;
>
> +       *reserve = page->reserve;
> +
>        inc_slabs_node(s, page_to_nid(page), page->objects);
>        page->slab = s;
>        page->flags |= 1 << PG_slab;
> @@ -1606,10 +1611,20 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
>  {
>        void **object;
>        struct page *new;
> +       int reserve;
>
>        /* We handle __GFP_ZERO in the caller */
>        gfpflags &= ~__GFP_ZERO;
>
> +       if (unlikely(c->reserve)) {
> +               /*
> +                * If the current slab is a reserve slab and the current
> +                * allocation context does not allow access to the reserves we
> +                * must force an allocation to test the current levels.
> +                */
> +               if (!(gfp_to_alloc_flags(gfpflags) & ALLOC_NO_WATERMARKS))
> +                       goto grow_slab;

OK, so assume that:

  (1) c->reserve is set to one

  (2) GFP flags don't allow dipping into the reserves

  (3) we've managed to free enough pages so normal
       allocations are fine

  (4) the page from reserves is not yet empty

we will call flush_slab() and put the "emergency page" on partial list
and clear c->reserve. This effectively means that now some other
allocation can fetch the partial page and start to use it. Is this OK?
Who makes sure the emergency reserves are large enough for the next
out-of-memory condition where we swap over NFS?

> +       }
>        if (!c->page)
>                goto new_slab;
>
> @@ -1623,8 +1638,8 @@ load_freelist:
>        object = c->page->freelist;
>        if (unlikely(!object))
>                goto another_slab;
> -       if (unlikely(SLABDEBUG && PageSlubDebug(c->page)))
> -               goto debug;
> +       if (unlikely(SLABDEBUG && PageSlubDebug(c->page) || c->reserve))
> +               goto slow_path;
>
>        c->freelist = get_freepointer(s, object);
>        c->page->inuse = c->page->objects;
> @@ -1646,16 +1661,18 @@ new_slab:
>                goto load_freelist;
>        }
>
> +grow_slab:
>        if (gfpflags & __GFP_WAIT)
>                local_irq_enable();
>
> -       new = new_slab(s, gfpflags, node);
> +       new = new_slab(s, gfpflags, node, &reserve);
>
>        if (gfpflags & __GFP_WAIT)
>                local_irq_disable();
>
>        if (new) {
>                c = __this_cpu_ptr(s->cpu_slab);
> +               c->reserve = reserve;
>                stat(s, ALLOC_SLAB);
>                if (c->page)
>                        flush_slab(s, c);
> @@ -1667,10 +1684,20 @@ new_slab:
>        if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit())
>                slab_out_of_memory(s, gfpflags, node);
>        return NULL;
> -debug:
> -       if (!alloc_debug_processing(s, c->page, object, addr))
> +
> +slow_path:
> +       if (!c->reserve && !alloc_debug_processing(s, c->page, object, addr))
>                goto another_slab;
>
> +       /*
> +        * Avoid the slub fast path in slab_alloc() by not setting
> +        * c->freelist and the fast path in slab_free() by making
> +        * node_match() fail by setting c->node to -1.
> +        *
> +        * We use this for for debug and reserve checks which need
> +        * to be done for each allocation.
> +        */
> +
>        c->page->inuse++;
>        c->page->freelist = get_freepointer(s, object);
>        c->node = -1;
> @@ -2095,10 +2122,11 @@ static void early_kmem_cache_node_alloc(gfp_t gfpflags, int node)
>        struct page *page;
>        struct kmem_cache_node *n;
>        unsigned long flags;
> +       int reserve;
>
>        BUG_ON(kmalloc_caches->size < sizeof(struct kmem_cache_node));
>
> -       page = new_slab(kmalloc_caches, gfpflags, node);
> +       page = new_slab(kmalloc_caches, gfpflags, node, &reserve);
>
>        BUG_ON(!page);
>        if (page_to_nid(page) != node) {
> --
> 1.7.1.1
>
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo-Bw31MaZKKs0EbZ0PF+XxCw@public.gmane.org  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org"> email-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org </a>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v2] eth16i: fix memory leak
From: Kulikov Vasiliy @ 2010-07-13 19:49 UTC (permalink / raw)
  To: kernel-janitors
  Cc: Mika Kuoppala, David S. Miller, Stephen Hemminger, Eric Dumazet,
	Tejun Heo, Jiri Pirko, netdev
In-Reply-To: <20100713114347.GK5658@bicker>

Free allocated netdev if no probe is expected.

Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
---
 drivers/net/eth16i.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index 874973f..10e39f2 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -1442,8 +1442,10 @@ int __init init_module(void)
 		dev->if_port = eth16i_parse_mediatype(mediatype[this_dev]);
 
 		if(io[this_dev] == 0) {
-			if(this_dev != 0) /* Only autoprobe 1st one */
+			if (this_dev != 0) { /* Only autoprobe 1st one */
+				free_netdev(dev);
 				break;
+			}
 
 			printk(KERN_NOTICE "eth16i.c: Presently autoprobing (not recommended) for a single card.\n");
 		}
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH] eth16i: fix memory leak
From: Kulikov Vasiliy @ 2010-07-13 19:48 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: kernel-janitors, Mika Kuoppala, David S. Miller,
	Stephen Hemminger, Eric Dumazet, Tejun Heo, Jiri Pirko, netdev
In-Reply-To: <20100713114347.GK5658@bicker>

On Tue, Jul 13, 2010 at 13:43 +0200, Dan Carpenter wrote:
> On Tue, Jul 13, 2010 at 03:22:18PM +0400, Kulikov Vasiliy wrote:
> > Free allocated netdev if no probe is expected.
> > 
> > Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
> > ---
> >  drivers/net/eth16i.c |    4 +++-
> >  1 files changed, 3 insertions(+), 1 deletions(-)
> > 
> > diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
> > index 874973f..2bdd394 100644
> > --- a/drivers/net/eth16i.c
> > +++ b/drivers/net/eth16i.c
> > @@ -1442,8 +1442,10 @@ int __init init_module(void)
> >  		dev->if_port = eth16i_parse_mediatype(mediatype[this_dev]);
> >  
> >  		if(io[this_dev] == 0) {
> > -			if(this_dev != 0) /* Only autoprobe 1st one */
> > +			if (this_dev != 0) { /* Only autoprobe 1st one */
> > +				free_netdev(def);
> 					    ^^^
> 				free_netdev(dev);
Heh, this function is surrounded with #ifdef MODULE #endif, so this typo
was not detected at my test nonmoduled compilation. Thanks.

Patch v2 is comming.

> 
> regards,
> dan carpenter
> 
> >  				break;
> > +			}
> >  
> >  			printk(KERN_NOTICE "eth16i.c: Presently autoprobing (not recommended) for a single card.\n");
> >  		}
> > -- 
> 

^ permalink raw reply

* Re: [PATCH] bnx2: Enable MSI-X even if the amount of vectors is smaller than BNX2_MAX_MSIX_VEC
From: Michael Chan @ 2010-07-13 19:40 UTC (permalink / raw)
  To: leitao@linux.vnet.ibm.com; +Cc: netdev@vger.kernel.org
In-Reply-To: <1279053766-8079-1-git-send-email-leitao@linux.vnet.ibm.com>


On Tue, 2010-07-13 at 13:42 -0700, leitao@linux.vnet.ibm.com wrote:
> First of all, the function bnx2_enable_msix() has the msix_vecs parameter,
> but it's not used to request the amount of vectors. Currently the drivers is
> always requesting BNX2_MAX_MSIX_VEC vectors, even when the msix_vecs is
> different from it.

The chip was originally designed to work in MSI-X mode only if all
vectors have been configured, that's why it was coded this way.
However, there is a register (BNX2_HC_MSIX_BIT_VECTOR) that we program
to make the chip think that all vectors are configured.  We always
program 0x1ff instead of the actual number of vectors, so it should work
with any number of vectors.  I'd like to do more testing first.

We need to at least allocate one more vector for the cnic driver.  I'll
fix that and send a revised and tested patch.

Thanks.

> 
> Also, if the amount of available vectors are smaller than BNX2_MAX_MSIX_VEC,
> the MSI-X is disabled, which is something bad.
> 
> So, this patch tries to fix both issues. Now if the available amount of vectors
> is smaller than the requested amount, the driver re-request the current available
> amount and proceed with these vectors.
> 
> Signed-off-by: Breno Leitão <leitao@linux.vnet.ibm.com>
> ---
>  drivers/net/bnx2.c |   16 +++++++++-------
>  1 files changed, 9 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
> index 1174322..70ee664 100644
> --- a/drivers/net/bnx2.c
> +++ b/drivers/net/bnx2.c
> @@ -860,7 +860,7 @@ bnx2_alloc_mem(struct bnx2 *bp)
>  	bnapi->hw_rx_cons_ptr =
>  		&bnapi->status_blk.msi->status_rx_quick_consumer_index0;
>  	if (bp->flags & BNX2_FLAG_MSIX_CAP) {
> -		for (i = 1; i < BNX2_MAX_MSIX_VEC; i++) {
> +		for (i = 1; i < bp->irq_nvecs; i++) {
>  			struct status_block_msix *sblk;
>  
>  			bnapi = &bp->bnx2_napi[i];
> @@ -4886,7 +4886,7 @@ bnx2_init_chip(struct bnx2 *bp)
>  	bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG3, BNX2_RBUF_CONFIG3_VAL(mtu));
>  
>  	memset(bp->bnx2_napi[0].status_blk.msi, 0, bp->status_stats_size);
> -	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++)
> +	for (i = 0; i < bp->irq_nvecs; i++)
>  		bp->bnx2_napi[i].last_status_idx = 0;
>  
>  	bp->idle_chk_status_idx = 0xffff;
> @@ -5007,7 +5007,7 @@ bnx2_clear_ring_states(struct bnx2 *bp)
>  	struct bnx2_rx_ring_info *rxr;
>  	int i;
>  
> -	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
> +	for (i = 0; i < bp->irq_nvecs; i++) {
>  		bnapi = &bp->bnx2_napi[i];
>  		txr = &bnapi->tx_ring;
>  		rxr = &bnapi->rx_ring;
> @@ -6148,13 +6148,15 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
>  		msix_ent[i].vector = 0;
>  	}
>  
> -	rc = pci_enable_msix(bp->pdev, msix_ent, BNX2_MAX_MSIX_VEC);
> -	if (rc != 0)
> -		return;
> +	do {
> +		rc = pci_enable_msix(bp->pdev, msix_ent, msix_vecs);
> +		if (rc > 0)
> +			msix_vecs = rc;
> +	} while (rc > 0);
>  
>  	bp->irq_nvecs = msix_vecs;
>  	bp->flags |= BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI;
> -	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
> +	for (i = 0; i < msix_vecs; i++) {
>  		bp->irq_tbl[i].vector = msix_ent[i].vector;
>  		snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i);
>  		bp->irq_tbl[i].handler = bnx2_msi_1shot;



^ permalink raw reply

* [PATCH] bnx2: Enable MSI-X even if the amount of vectors is smaller than BNX2_MAX_MSIX_VEC
From: leitao @ 2010-07-13 20:42 UTC (permalink / raw)
  To: mchan; +Cc: netdev, Breno Leitão

First of all, the function bnx2_enable_msix() has the msix_vecs parameter,
but it's not used to request the amount of vectors. Currently the drivers is
always requesting BNX2_MAX_MSIX_VEC vectors, even when the msix_vecs is
different from it.

Also, if the amount of available vectors are smaller than BNX2_MAX_MSIX_VEC,
the MSI-X is disabled, which is something bad.

So, this patch tries to fix both issues. Now if the available amount of vectors
is smaller than the requested amount, the driver re-request the current available
amount and proceed with these vectors.

Signed-off-by: Breno Leitão <leitao@linux.vnet.ibm.com>
---
 drivers/net/bnx2.c |   16 +++++++++-------
 1 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 1174322..70ee664 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -860,7 +860,7 @@ bnx2_alloc_mem(struct bnx2 *bp)
 	bnapi->hw_rx_cons_ptr =
 		&bnapi->status_blk.msi->status_rx_quick_consumer_index0;
 	if (bp->flags & BNX2_FLAG_MSIX_CAP) {
-		for (i = 1; i < BNX2_MAX_MSIX_VEC; i++) {
+		for (i = 1; i < bp->irq_nvecs; i++) {
 			struct status_block_msix *sblk;
 
 			bnapi = &bp->bnx2_napi[i];
@@ -4886,7 +4886,7 @@ bnx2_init_chip(struct bnx2 *bp)
 	bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG3, BNX2_RBUF_CONFIG3_VAL(mtu));
 
 	memset(bp->bnx2_napi[0].status_blk.msi, 0, bp->status_stats_size);
-	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++)
+	for (i = 0; i < bp->irq_nvecs; i++)
 		bp->bnx2_napi[i].last_status_idx = 0;
 
 	bp->idle_chk_status_idx = 0xffff;
@@ -5007,7 +5007,7 @@ bnx2_clear_ring_states(struct bnx2 *bp)
 	struct bnx2_rx_ring_info *rxr;
 	int i;
 
-	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
+	for (i = 0; i < bp->irq_nvecs; i++) {
 		bnapi = &bp->bnx2_napi[i];
 		txr = &bnapi->tx_ring;
 		rxr = &bnapi->rx_ring;
@@ -6148,13 +6148,15 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
 		msix_ent[i].vector = 0;
 	}
 
-	rc = pci_enable_msix(bp->pdev, msix_ent, BNX2_MAX_MSIX_VEC);
-	if (rc != 0)
-		return;
+	do {
+		rc = pci_enable_msix(bp->pdev, msix_ent, msix_vecs);
+		if (rc > 0)
+			msix_vecs = rc;
+	} while (rc > 0);
 
 	bp->irq_nvecs = msix_vecs;
 	bp->flags |= BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI;
-	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
+	for (i = 0; i < msix_vecs; i++) {
 		bp->irq_tbl[i].vector = msix_ent[i].vector;
 		snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i);
 		bp->irq_tbl[i].handler = bnx2_msi_1shot;
-- 
1.6.0.2


^ permalink raw reply related

* Re: [PATCH v4 2.6.35-rc3] drivers/net: ks8842 driver
From: David Miller @ 2010-07-13 17:14 UTC (permalink / raw)
  To: David.Choi; +Cc: netdev, Charles.Li, horms
In-Reply-To: <C43529A246480145B0A6D0234BDB0F0D0212A7@MELANITE.micrel.com>

From: "Choi, David" <David.Choi@Micrel.Com>
Date: Tue, 13 Jul 2010 08:42:41 -0700

> From: David J. Choi <david.choi@micrel.com>
> 
> Body of the explanation: 
>    -support 16bit and 32bit bus width.
>    -add device reset for ks8842/8841 Micrel device.
>    -set 100Mbps as a default for Micrel device.
>    -set MAC address in both MAC/Switch layer with different sequence for Micrel
>     device, as mentioned in data sheet.
>    -use private data to set options both 16/32bit bus width and Micrel device/
>     Timberdale(FPGA).
>    -update Kconfig in order to put more information about ks8842 device.
> 
> Signed-off-by: David J. Choi <david.choi@micrel.com>

This patch doesn't apply to net-next-2.6 because the bank select I/O
write has been removed from the reset function, and the driver now
uses netdev_*() instead of dev_*() logging functions.

Also, your patch subject line should be more descriptive, it doesn't
say what this patch is doing, it just says "ks8842 driver", well this
driver already supports ks8842 chips just not "Micrel KS8842/8841"
ones.  So I changed the subject line to describe what this patch is
actually doing.

Also, when you want to make side-commentary to us which is not meant
to go into the commit, place it after the commit message (not before),
seperated from the commit message with "---" on a line by itself.

I fixed all of this up and applied your patch as follows:

--------------------
>From 28bd620c7a1244e59459d6293ca11f162e0a67b9 Mon Sep 17 00:00:00 2001
From: David J. Choi <david.choi@micrel.com>
Date: Tue, 13 Jul 2010 10:09:19 -0700
Subject: [PATCH] drivers/net: Add Micrel KS8841/42 support to ks8842 driver

Body of the explanation:
   -support 16bit and 32bit bus width.
   -add device reset for ks8842/8841 Micrel device.
   -set 100Mbps as a default for Micrel device.
   -set MAC address in both MAC/Switch layer with different sequence for Micrel
    device, as mentioned in data sheet.
   -use private data to set options both 16/32bit bus width and Micrel device/
    Timberdale(FPGA).
   -update Kconfig in order to put more information about ks8842 device.

Signed-off-by: David J. Choi <david.choi@micrel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/net/Kconfig  |    7 +-
 drivers/net/ks8842.c |  174 +++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 133 insertions(+), 48 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f65857e..8829476 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1750,11 +1750,12 @@ config TLAN
 	  Please email feedback to <torben.mathiasen@compaq.com>.
 
 config KS8842
-	tristate "Micrel KSZ8842"
+	tristate "Micrel KSZ8841/42 with generic bus interface"
 	depends on HAS_IOMEM
 	help
-	  This platform driver is for Micrel KSZ8842 / KS8842
-	  2-port ethernet switch chip (managed, VLAN, QoS).
+	 This platform driver is for KSZ8841(1-port) / KS8842(2-port)
+	 ethernet switch chip (managed, VLAN, QoS) from Micrel or
+	 Timberdale(FPGA).
 
 config KS8851
        tristate "Micrel KS8851 SPI"
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c
index 0be9261..ee69dea 100644
--- a/drivers/net/ks8842.c
+++ b/drivers/net/ks8842.c
@@ -18,6 +18,7 @@
 
 /* Supports:
  * The Micrel KS8842 behind the timberdale FPGA
+ * The genuine Micrel KS8841/42 device with ISA 16/32bit bus interface
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -114,9 +115,14 @@
 #define REG_P1CR4		0x02
 #define REG_P1SR		0x04
 
+/* flags passed by platform_device for configuration */
+#define	MICREL_KS884X		0x01	/* 0=Timeberdale(FPGA), 1=Micrel */
+#define	KS884X_16BIT		0x02	/*  1=16bit, 0=32bit */
+
 struct ks8842_adapter {
 	void __iomem	*hw_addr;
 	int		irq;
+	unsigned long	conf_flags;	/* copy of platform_device config */
 	struct tasklet_struct	tasklet;
 	spinlock_t	lock; /* spinlock to be interrupt safe */
 	struct work_struct timeout_work;
@@ -192,15 +198,21 @@ static inline u32 ks8842_read32(struct ks8842_adapter *adapter, u16 bank,
 
 static void ks8842_reset(struct ks8842_adapter *adapter)
 {
-	/* The KS8842 goes haywire when doing softare reset
-	 * a work around in the timberdale IP is implemented to
-	 * do a hardware reset instead
-	ks8842_write16(adapter, 3, 1, REG_GRR);
-	msleep(10);
-	iowrite16(0, adapter->hw_addr + REG_GRR);
-	*/
-	iowrite32(0x1, adapter->hw_addr + REG_TIMB_RST);
-	msleep(20);
+	if (adapter->conf_flags & MICREL_KS884X) {
+		ks8842_write16(adapter, 3, 1, REG_GRR);
+		msleep(10);
+		iowrite16(0, adapter->hw_addr + REG_GRR);
+	} else {
+		/* The KS8842 goes haywire when doing softare reset
+		* a work around in the timberdale IP is implemented to
+		* do a hardware reset instead
+		ks8842_write16(adapter, 3, 1, REG_GRR);
+		msleep(10);
+		iowrite16(0, adapter->hw_addr + REG_GRR);
+		*/
+		iowrite32(0x1, adapter->hw_addr + REG_TIMB_RST);
+		msleep(20);
+	}
 }
 
 static void ks8842_update_link_status(struct net_device *netdev,
@@ -269,8 +281,10 @@ static void ks8842_reset_hw(struct ks8842_adapter *adapter)
 
 	/* restart port auto-negotiation */
 	ks8842_enable_bits(adapter, 49, 1 << 13, REG_P1CR4);
-	/* only advertise 10Mbps */
-	ks8842_clear_bits(adapter, 49, 3 << 2, REG_P1CR4);
+
+	if (!(adapter->conf_flags & MICREL_KS884X))
+		/* only advertise 10Mbps */
+		ks8842_clear_bits(adapter, 49, 3 << 2, REG_P1CR4);
 
 	/* Enable the transmitter */
 	ks8842_enable_tx(adapter);
@@ -296,13 +310,28 @@ static void ks8842_read_mac_addr(struct ks8842_adapter *adapter, u8 *dest)
 	for (i = 0; i < ETH_ALEN; i++)
 		dest[ETH_ALEN - i - 1] = ks8842_read8(adapter, 2, REG_MARL + i);
 
-	/* make sure the switch port uses the same MAC as the QMU */
-	mac = ks8842_read16(adapter, 2, REG_MARL);
-	ks8842_write16(adapter, 39, mac, REG_MACAR1);
-	mac = ks8842_read16(adapter, 2, REG_MARM);
-	ks8842_write16(adapter, 39, mac, REG_MACAR2);
-	mac = ks8842_read16(adapter, 2, REG_MARH);
-	ks8842_write16(adapter, 39, mac, REG_MACAR3);
+	if (adapter->conf_flags & MICREL_KS884X) {
+		/*
+		the sequence of saving mac addr between MAC and Switch is
+		different.
+		*/
+
+		mac = ks8842_read16(adapter, 2, REG_MARL);
+		ks8842_write16(adapter, 39, mac, REG_MACAR3);
+		mac = ks8842_read16(adapter, 2, REG_MARM);
+		ks8842_write16(adapter, 39, mac, REG_MACAR2);
+		mac = ks8842_read16(adapter, 2, REG_MARH);
+		ks8842_write16(adapter, 39, mac, REG_MACAR1);
+	} else {
+
+		/* make sure the switch port uses the same MAC as the QMU */
+		mac = ks8842_read16(adapter, 2, REG_MARL);
+		ks8842_write16(adapter, 39, mac, REG_MACAR1);
+		mac = ks8842_read16(adapter, 2, REG_MARM);
+		ks8842_write16(adapter, 39, mac, REG_MACAR2);
+		mac = ks8842_read16(adapter, 2, REG_MARH);
+		ks8842_write16(adapter, 39, mac, REG_MACAR3);
+	}
 }
 
 static void ks8842_write_mac_addr(struct ks8842_adapter *adapter, u8 *mac)
@@ -313,8 +342,25 @@ static void ks8842_write_mac_addr(struct ks8842_adapter *adapter, u8 *mac)
 	spin_lock_irqsave(&adapter->lock, flags);
 	for (i = 0; i < ETH_ALEN; i++) {
 		ks8842_write8(adapter, 2, mac[ETH_ALEN - i - 1], REG_MARL + i);
-		ks8842_write8(adapter, 39, mac[ETH_ALEN - i - 1],
-			REG_MACAR1 + i);
+		if (!(adapter->conf_flags & MICREL_KS884X))
+			ks8842_write8(adapter, 39, mac[ETH_ALEN - i - 1],
+				REG_MACAR1 + i);
+	}
+
+	if (adapter->conf_flags & MICREL_KS884X) {
+		/*
+		the sequence of saving mac addr between MAC and Switch is
+		different.
+		*/
+
+		u16 mac;
+
+		mac = ks8842_read16(adapter, 2, REG_MARL);
+		ks8842_write16(adapter, 39, mac, REG_MACAR3);
+		mac = ks8842_read16(adapter, 2, REG_MARM);
+		ks8842_write16(adapter, 39, mac, REG_MACAR2);
+		mac = ks8842_read16(adapter, 2, REG_MARH);
+		ks8842_write16(adapter, 39, mac, REG_MACAR1);
 	}
 	spin_unlock_irqrestore(&adapter->lock, flags);
 }
@@ -328,8 +374,6 @@ static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct ks8842_adapter *adapter = netdev_priv(netdev);
 	int len = skb->len;
-	u32 *ptr = (u32 *)skb->data;
-	u32 ctrl;
 
 	netdev_dbg(netdev, "%s: len %u head %p data %p tail %p end %p\n",
 		__func__, skb->len, skb->head, skb->data,
@@ -339,17 +383,34 @@ static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
 	if (ks8842_tx_fifo_space(adapter) < len + 8)
 		return NETDEV_TX_BUSY;
 
-	/* the control word, enable IRQ, port 1 and the length */
-	ctrl = 0x8000 | 0x100 | (len << 16);
-	ks8842_write32(adapter, 17, ctrl, REG_QMU_DATA_LO);
+	if (adapter->conf_flags & KS884X_16BIT) {
+		u16 *ptr16 = (u16 *)skb->data;
+		ks8842_write16(adapter, 17, 0x8000 | 0x100, REG_QMU_DATA_LO);
+		ks8842_write16(adapter, 17, (u16)len, REG_QMU_DATA_HI);
+		netdev->stats.tx_bytes += len;
+
+		/* copy buffer */
+		while (len > 0) {
+			iowrite16(*ptr16++, adapter->hw_addr + REG_QMU_DATA_LO);
+			iowrite16(*ptr16++, adapter->hw_addr + REG_QMU_DATA_HI);
+			len -= sizeof(u32);
+		}
+	} else {
+
+		u32 *ptr = (u32 *)skb->data;
+		u32 ctrl;
+		/* the control word, enable IRQ, port 1 and the length */
+		ctrl = 0x8000 | 0x100 | (len << 16);
+		ks8842_write32(adapter, 17, ctrl, REG_QMU_DATA_LO);
 
-	netdev->stats.tx_bytes += len;
+		netdev->stats.tx_bytes += len;
 
-	/* copy buffer */
-	while (len > 0) {
-		iowrite32(*ptr, adapter->hw_addr + REG_QMU_DATA_LO);
-		len -= sizeof(u32);
-		ptr++;
+		/* copy buffer */
+		while (len > 0) {
+			iowrite32(*ptr, adapter->hw_addr + REG_QMU_DATA_LO);
+			len -= sizeof(u32);
+			ptr++;
+		}
 	}
 
 	/* enqueue packet */
@@ -363,12 +424,23 @@ static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
 static void ks8842_rx_frame(struct net_device *netdev,
 	struct ks8842_adapter *adapter)
 {
-	u32 status = ks8842_read32(adapter, 17, REG_QMU_DATA_LO);
-	int len = (status >> 16) & 0x7ff;
+	u16 status16;
+	u32 status;
+	int len;
 
-	status &= 0xffff;
-
-	netdev_dbg(netdev, "%s - rx_data: status: %x\n", __func__, status);
+	if (adapter->conf_flags & KS884X_16BIT) {
+		status16 = ks8842_read16(adapter, 17, REG_QMU_DATA_LO);
+		len  = (int)ks8842_read16(adapter, 17, REG_QMU_DATA_HI);
+		len &= 0xffff;
+		netdev_dbg(netdev, "%s - rx_data: status: %x\n",
+			   __func__, status16);
+	} else {
+		status = ks8842_read32(adapter, 17, REG_QMU_DATA_LO);
+		len = (status >> 16) & 0x7ff;
+		status &= 0xffff;
+		netdev_dbg(netdev, "%s - rx_data: status: %x\n",
+			   __func__, status);
+	}
 
 	/* check the status */
 	if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) {
@@ -376,22 +448,32 @@ static void ks8842_rx_frame(struct net_device *netdev,
 
 		netdev_dbg(netdev, "%s, got package, len: %d\n", __func__, len);
 		if (skb) {
-			u32 *data;
 
 			netdev->stats.rx_packets++;
 			netdev->stats.rx_bytes += len;
 			if (status & RXSR_MULTICAST)
 				netdev->stats.multicast++;
 
-			data = (u32 *)skb_put(skb, len);
-
-			ks8842_select_bank(adapter, 17);
-			while (len > 0) {
-				*data++ = ioread32(adapter->hw_addr +
-					REG_QMU_DATA_LO);
-				len -= sizeof(u32);
+			if (adapter->conf_flags & KS884X_16BIT) {
+				u16 *data16 = (u16 *)skb_put(skb, len);
+				ks8842_select_bank(adapter, 17);
+				while (len > 0) {
+					*data16++ = ioread16(adapter->hw_addr +
+						REG_QMU_DATA_LO);
+					*data16++ = ioread16(adapter->hw_addr +
+						REG_QMU_DATA_HI);
+					len -= sizeof(u32);
+				}
+			} else {
+				u32 *data = (u32 *)skb_put(skb, len);
+
+				ks8842_select_bank(adapter, 17);
+				while (len > 0) {
+					*data++ = ioread32(adapter->hw_addr +
+						REG_QMU_DATA_LO);
+					len -= sizeof(u32);
+				}
 			}
-
 			skb->protocol = eth_type_trans(skb, netdev);
 			netif_rx(skb);
 		} else
@@ -669,6 +751,8 @@ static int __devinit ks8842_probe(struct platform_device *pdev)
 	adapter->netdev = netdev;
 	INIT_WORK(&adapter->timeout_work, ks8842_tx_timeout_work);
 	adapter->hw_addr = ioremap(iomem->start, resource_size(iomem));
+	adapter->conf_flags = iomem->flags;
+
 	if (!adapter->hw_addr)
 		goto err_ioremap;
 
-- 
1.7.1.1


^ permalink raw reply related

* Re: [PATCH net-next-2.6]  macvtap: Return error when macvlan drops the packet
From: Shirley Ma @ 2010-07-13 16:42 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: sri, netdev, davem
In-Reply-To: <201007121244.04499.arnd@arndb.de>

Hello Arnd,

I am working on macvtap zero-copy patch. I found that the packet was
silently dropped and packet out of order when using zero-copy. That was
a reason I submitted this patch to switch to copy mode when that
happens. I think I might need more time to debug why first.

Thanks
Shirley


^ permalink raw reply

* Re: [PATCH] netfilter: xtables: userspace notification target
From: Pablo Neira Ayuso @ 2010-07-13 16:38 UTC (permalink / raw)
  To: Luciano Coelho
  Cc: Changli Gao, Samuel Ortiz, Patrick McHardy, David S. Miller,
	netdev@vger.kernel.org, netfilter-devel@vger.kernel.org
In-Reply-To: <1279016596.12673.11.camel@chilepepper>

On 13/07/10 12:23, Luciano Coelho wrote:
> On Tue, 2010-07-13 at 10:50 +0200, ext Pablo Neira Ayuso wrote:
>> On 13/07/10 08:18, Changli Gao wrote:
>>> On Tue, Jul 13, 2010 at 8:11 AM, Samuel Ortiz<sameo@linux.intel.com>  wrote:
>>>>
>>>> The userspace notification Xtables target sends a netlink notification
>>>> whenever a packet hits the target. Notifications have a label attribute
>>>> for userspace to match it against a previously set rule. The rules also
>>>> take a --all option to switch between sending a notification for all
>>>> packets or for the first one only.
>>>> Userspace can also send a netlink message to toggle this switch while the
>>>> target is in place. This target uses the nefilter netlink framework.
>>>>
>>>> This target combined with various matches (quota, rateest, etc..) allows
>>>> userspace to make decisions on interfaces handling. One could for example
>>>> decide to switch between power saving modes depending on estimated rate
>>>> thresholds.
>>>>
>>>
>>> It much like the following iptables rules.
>>>
>>> iptables -N log_and_drop
>>> iptables -A log_and_drop -j NFLOG --nflog-group 1 --nflog-prefix "log_and_drop"
>>> iptables -A log_and_drop -j DROP
>>>
>>> ...
>>> iptables ... -m quota --quota-bytes 20000 -j log_and_drop
>>> ...
>>
>> Indeed, this looks to me like something that you can do with NFLOG and
>> some combination of matches.
>
> Is it possible to have the NFLOG send only one notification to the
> userspace?

Not possible, but you could easily extend NFLOG to implement this 
feature if it's not possible to do what you need with the existing 
matches/targets. This NOTIF infrastructure is redundant and it looks 
like a subset of NFLOG.

There's a padding field in xt_NFLOG that is currently unused, it could 
be used for this.

Or we could add some 'count' match to store the number of packets that 
have matched a rule (although not sure if this is generic enough to be 
useful for others).

> In the example above, once the quota exceeds, the userspace
> will be notified of every packet arriving, won't it?  That would cause
> unnecessary processing in the userspace.
>
> The userspace could remove the rule when it gets the first notification
> and only add it again when it needs to get the information again (as a
> "toggle" functionality), but I think that would take too long and there
> would be several packets going through before the rule could be removed.

You can do that with libnetfilter_log to handle the log messages 
received and the minor change for xt_NFLOG that I proposed.

^ permalink raw reply

* Re: [patch] net/sched: potential data corruption
From: jamal @ 2010-07-13 15:58 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: David S. Miller, Stephen Hemminger, netdev, kernel-janitors,
	matthew
In-Reply-To: <20100713132152.GL5658@bicker>

On Tue, 2010-07-13 at 15:21 +0200, Dan Carpenter wrote:
> The reset_policy() does:
>         memset(d->tcfd_defdata, 0, SIMP_MAX_DATA);
>         strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
> 
> In the original code, the size of d->tcfd_defdata wasn't fixed and if
> strlen(defdata) was less than 31, reset_policy() would cause memory
> corruption.
> 
> Please Note:  The original alloc_defdata() assumes defdata is 32
> characters and a NUL terminator while reset_policy() assumes defdata is
> 31 characters and a NUL.  This patch updates alloc_defdata() to match
> reset_policy() (ie a shorter string).  I'm not very familiar with this
> code so please review carefully.
> 
> Signed-off-by: Dan Carpenter <error27@gmail.com>


Acked-by: Jamal Hadi Salim <hadi@cyberus.ca>


cheers,
jamal


^ permalink raw reply

* Re: [PATCH] tproxy: nf_tproxy_assign_sock() can handle tw sockets
From: Eric Dumazet @ 2010-07-13 15:49 UTC (permalink / raw)
  To: Felipe W Damasio
  Cc: Avi Kivity, David Miller, Patrick McHardy, linux-kernel, netdev
In-Reply-To: <AANLkTilrIByt4xAHhsBsKo3nDfv0_c3sF-dCiTiYiPnu@mail.gmail.com>

Le mardi 13 juillet 2010 à 11:49 -0300, Felipe W Damasio a écrit :
> Hi Mr. Dumazet,
> 
> 2010/7/13 Eric Dumazet <eric.dumazet@gmail.com>:
> > I currently have no fresh ideas. If you want this problem to be solved,
> > its important to setup in your lab a workload to trigger again and again
> > the bug, in order to provide us more crash information.
> 
>  Right. I've been running non-stop since the first bug happened, but
> so far the problem hasn't surfaced again :-(
> 
>  I've been using the kernel with the patch that you provided me
> (nf_tproxy.c). Is there a chance that patch fixed the problem?

This is a real bug, but I dont think it can fix your problem.

Looking again at your crash, we see RCX=0x720, decimal 1824

As its skb->len, we are freeing an skb that was collapsed or something
like that, since 1824 > 1460 (the normal MSS on ethernet)

GRO is off on your machine.

But coincidently 0x0720 is also a blank char for VGA screen...
(0x20 : ASCII space, 0x07 : default attribute)

So maybe you hit a corruption outside of network stack.

^ 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