* Re: [PATCH 1/1] ipvs: kernel oops - do_ip_vs_get_ctl
From: Hans Schillstrom @ 2012-04-25 9:36 UTC (permalink / raw)
To: Jesper Dangaard Brouer
Cc: horms@verge.net.au, ja@ssi.bg, wensong@linux-vs.org,
lvs-devel@vger.kernel.org, netdev@vger.kernel.org,
netfilter-devel@vger.kernel.org, hans@schillstrom.com
In-Reply-To: <1335344761.6337.42.camel@t520>
On Wednesday 25 April 2012 11:06:01 Jesper Dangaard Brouer wrote:
> Hi Hans,
>
> Thank you for your work.
> Just some whitespace nitpicks below.
OK thanks I forgott to run checkpatch ...
I'll send a new patch
> I have not been able to reproduce the bug in:
> https://bugzilla.redhat.com/show_bug.cgi?id=806704
>
> Can you recommend a (better) way to reproduce this bug?
> I just want to be able to verify that this fixes the bug in question.
I think you need two threads or procs.
Start a modprobe in thread one then issue a ipvs ioctl in the other.
The timing is not that easy here :-)
>
>
> On Wed, 2012-04-25 at 09:44 +0200, Hans Schillstrom wrote:
> > Change order of init so netns init is ready
> > when register ioctl and netlink.
> >
> > Reported-by: "Ryan O'Hara" <rohara@redhat.com>
> > Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
> > ---
> > include/net/ip_vs.h | 2 +
> > net/netfilter/ipvs/ip_vs_core.c | 9 ++++++
> > net/netfilter/ipvs/ip_vs_ctl.c | 52 ++++++++++++++++++++++----------------
> > 3 files changed, 41 insertions(+), 22 deletions(-)
> >
> > diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
> > index f967395..93b81aa 100644
> > --- a/include/net/ip_vs.h
> > +++ b/include/net/ip_vs.h
> > @@ -1201,6 +1201,8 @@ ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol,
> >
> > extern int ip_vs_use_count_inc(void);
> > extern void ip_vs_use_count_dec(void);
> > +extern int ip_vs_register_nl_ioctl(void);
> > +extern void ip_vs_unregister_nl_ioctl(void);
> > extern int ip_vs_control_init(void);
> > extern void ip_vs_control_cleanup(void);
> > extern struct ip_vs_dest *
> > diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
> > index d8b1d30..c8f36b9 100644
> > --- a/net/netfilter/ipvs/ip_vs_core.c
> > +++ b/net/netfilter/ipvs/ip_vs_core.c
> > @@ -1995,10 +1995,18 @@ static int __init ip_vs_init(void)
> > goto cleanup_dev;
> > }
> >
> > + ret = ip_vs_register_nl_ioctl();
> > + if (ret < 0) {
> > + pr_err("can't register netlink/ioctl.\n");
> > + goto cleanup_hooks;
> > + }
> > +
> > pr_info("ipvs loaded.\n");
> >
> > return ret;
> >
> > +cleanup_hooks:
> > + nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
> > cleanup_dev:
> > unregister_pernet_device(&ipvs_core_dev_ops);
> > cleanup_sub:
> > @@ -2014,6 +2022,7 @@ exit:
> >
> > static void __exit ip_vs_cleanup(void)
> > {
> > + ip_vs_unregister_nl_ioctl();
> > nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
> > unregister_pernet_device(&ipvs_core_dev_ops);
> > unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
> > diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
> > index 7131417..efaf484 100644
> > --- a/net/netfilter/ipvs/ip_vs_ctl.c
> > +++ b/net/netfilter/ipvs/ip_vs_ctl.c
> > @@ -3750,21 +3750,10 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net)
> > free_percpu(ipvs->tot_stats.cpustats);
> > }
> >
> > -int __init ip_vs_control_init(void)
> > +int ip_vs_register_nl_ioctl(void)
> > {
> > - int idx;
> > int ret;
> >
> > - EnterFunction(2);
> > -
> > - /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
> > - for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
> > - INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
> > - INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
> > - }
> > -
> > - smp_wmb(); /* Do we really need it now ? */
> > -
> > ret = nf_register_sockopt(&ip_vs_sockopts);
> > if (ret) {
> > pr_err("cannot register sockopt.\n");
> > @@ -3776,28 +3765,47 @@ int __init ip_vs_control_init(void)
> > pr_err("cannot register Generic Netlink interface.\n");
> > goto err_genl;
> > }
> > -
> > - ret = register_netdevice_notifier(&ip_vs_dst_notifier);
> > - if (ret < 0)
> > - goto err_notf;
> > -
> > - LeaveFunction(2);
> > return 0;
> >
> > -err_notf:
> > - ip_vs_genl_unregister();
> > err_genl:
> > nf_unregister_sockopt(&ip_vs_sockopts);
> > err_sock:
> > return ret;
> > }
> >
> > +void ip_vs_unregister_nl_ioctl(void)
>
> There is a extra trailing whitespace behind
> ip_vs_unregister_nl_ioctl(void)
>
>
> > +{
> > + ip_vs_genl_unregister();
> > + nf_unregister_sockopt(&ip_vs_sockopts);
> > +}
> > +
> > +int __init ip_vs_control_init(void)
> > +{
> > + int idx;
> > + int ret;
> > +
> > + EnterFunction(2);
> > +
> > + /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
> > + for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
>
> The for loop is funny spaced...
>
>
> > + INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
> > + INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
> > + }
> > +
> > + smp_wmb(); /* Do we really need it now ? */
> > +
> > + ret = register_netdevice_notifier(&ip_vs_dst_notifier);
> > + if (ret < 0)
> > + return ret;
> > +
> > + LeaveFunction(2);
> > + return 0;
> > +}
> > +
> >
> > void ip_vs_control_cleanup(void)
> > {
> > EnterFunction(2);
> > unregister_netdevice_notifier(&ip_vs_dst_notifier);
> > - ip_vs_genl_unregister();
> > - nf_unregister_sockopt(&ip_vs_sockopts);
> > LeaveFunction(2);
> > }
>
--
Regards
Hans Schillstrom <hans.schillstrom@ericsson.com>
^ permalink raw reply
* Re: [PATCH 2/2] ipvs: fix crash in ip_vs_control_net_cleanup on unload
From: Pablo Neira Ayuso @ 2012-04-25 9:15 UTC (permalink / raw)
To: Simon Horman
Cc: lvs-devel, netdev, netfilter-devel, Wensong Zhang,
Julian Anastasov, Sasha Levin, stable, Hans Schillstrom
In-Reply-To: <1335186732-16002-3-git-send-email-horms@verge.net.au>
On Mon, Apr 23, 2012 at 10:12:12PM +0900, Simon Horman wrote:
> From: Julian Anastasov <ja@ssi.bg>
>
> commit 14e405461e664b777e2a5636e10b2ebf36a686ec (2.6.39)
> ("Add __ip_vs_control_{init,cleanup}_sysctl()")
> introduced regression due to wrong __net_init for
> __ip_vs_control_cleanup_sysctl. This leads to crash when
> the ip_vs module is unloaded.
>
> Fix it by changing __net_init to __net_exit for
> the function that is already renamed to ip_vs_control_net_cleanup_sysctl.
>
> Cc: stable@vger.kernel.org
Removed this above.
> Signed-off-by: Julian Anastasov <ja@ssi.bg>
> Signed-off-by: Hans Schillstrom <hans@schillstrom.com>
> Signed-off-by: Simon Horman <horms@verge.net.au>
And applied, thanks Simon.
^ permalink raw reply
* Re: [PATCH 1/2] netfilter: ipvs: Verify that IP_VS protocol has been registered
From: Pablo Neira Ayuso @ 2012-04-25 9:14 UTC (permalink / raw)
To: Simon Horman
Cc: lvs-devel, netdev, netfilter-devel, Wensong Zhang,
Julian Anastasov, Sasha Levin
In-Reply-To: <1335186732-16002-2-git-send-email-horms@verge.net.au>
On Mon, Apr 23, 2012 at 10:12:11PM +0900, Simon Horman wrote:
> From: Sasha Levin <levinsasha928@gmail.com>
>
> The registration of a protocol might fail, there were no checks
> and all registrations were assumed to be correct. This lead to
> NULL ptr dereferences when apps tried registering.
>
> For example:
>
> [ 1293.226051] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
> [ 1293.227038] IP: [<ffffffff822aacb0>] tcp_register_app+0x60/0xb0
> [ 1293.227038] PGD 391de067 PUD 6c20b067 PMD 0
> [ 1293.227038] Oops: 0000 [#1] PREEMPT SMP
> [ 1293.227038] CPU 1
> [ 1293.227038] Pid: 19609, comm: trinity Tainted: G W 3.4.0-rc1-next-20120405-sasha-dirty #57
> [ 1293.227038] RIP: 0010:[<ffffffff822aacb0>] [<ffffffff822aacb0>] tcp_register_app+0x60/0xb0
> [ 1293.227038] RSP: 0018:ffff880038c1dd18 EFLAGS: 00010286
> [ 1293.227038] RAX: ffffffffffffffc0 RBX: 0000000000001500 RCX: 0000000000010000
> [ 1293.227038] RDX: 0000000000000000 RSI: ffff88003a2d5888 RDI: 0000000000000282
> [ 1293.227038] RBP: ffff880038c1dd48 R08: 0000000000000000 R09: 0000000000000000
> [ 1293.227038] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88003a2d5668
> [ 1293.227038] R13: ffff88003a2d5988 R14: ffff8800696a8ff8 R15: 0000000000000000
> [ 1293.227038] FS: 00007f01930d9700(0000) GS:ffff88007ce00000(0000) knlGS:0000000000000000
> [ 1293.227038] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
> [ 1293.227038] CR2: 0000000000000018 CR3: 0000000065dfc000 CR4: 00000000000406e0
> [ 1293.227038] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [ 1293.227038] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> [ 1293.227038] Process trinity (pid: 19609, threadinfo ffff880038c1c000, task ffff88002dc73000)
> [ 1293.227038] Stack:
> [ 1293.227038] ffff880038c1dd48 00000000fffffff4 ffff8800696aada0 ffff8800694f5580
> [ 1293.227038] ffffffff8369f1e0 0000000000001500 ffff880038c1dd98 ffffffff822a716b
> [ 1293.227038] 0000000000000000 ffff8800696a8ff8 0000000000000015 ffff8800694f5580
> [ 1293.227038] Call Trace:
> [ 1293.227038] [<ffffffff822a716b>] ip_vs_app_inc_new+0xdb/0x180
> [ 1293.227038] [<ffffffff822a7258>] register_ip_vs_app_inc+0x48/0x70
> [ 1293.227038] [<ffffffff822b2fea>] __ip_vs_ftp_init+0xba/0x140
> [ 1293.227038] [<ffffffff821c9060>] ops_init+0x80/0x90
> [ 1293.227038] [<ffffffff821c90cb>] setup_net+0x5b/0xe0
> [ 1293.227038] [<ffffffff821c9416>] copy_net_ns+0x76/0x100
> [ 1293.227038] [<ffffffff810dc92b>] create_new_namespaces+0xfb/0x190
> [ 1293.227038] [<ffffffff810dca21>] unshare_nsproxy_namespaces+0x61/0x80
> [ 1293.227038] [<ffffffff810afd1f>] sys_unshare+0xff/0x290
> [ 1293.227038] [<ffffffff8187622e>] ? trace_hardirqs_on_thunk+0x3a/0x3f
> [ 1293.227038] [<ffffffff82665539>] system_call_fastpath+0x16/0x1b
> [ 1293.227038] Code: 89 c7 e8 34 91 3b 00 89 de 66 c1 ee 04 31 de 83 e6 0f 48 83 c6 22 48 c1 e6 04 4a 8b 14 26 49 8d 34 34 48 8d 42 c0 48 39 d6 74 13 <66> 39 58 58 74 22 48 8b 48 40 48 8d 41 c0 48 39 ce 75 ed 49 8d
> [ 1293.227038] RIP [<ffffffff822aacb0>] tcp_register_app+0x60/0xb0
> [ 1293.227038] RSP <ffff880038c1dd18>
> [ 1293.227038] CR2: 0000000000000018
> [ 1293.379284] ---[ end trace 364ab40c7011a009 ]---
> [ 1293.381182] Kernel panic - not syncing: Fatal exception in interrupt
>
> Cc: stable@vger.kernel.org
I've removed this above from the patch. I prefer not to add confusing
information (this means you'll have to rebase, sorry).
> Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> Acked-by: Julian Anastasov <ja@ssi.bg>
> Signed-off-by: Simon Horman <horms@verge.net.au>
Applied. Thanks.
BTW, did you consider using an array for ipvs->ip_vs_proto_table?
I think a hash table for only 5 protocols is overkill. I know, we'll
consume more memory but lookups will definitely be faster, but it will
consume a bit more memory (the space-time tradeoff again).
^ permalink raw reply
* Re: My e1000e GBE card is eating all port 623 pks
From: Joakim Tjernlund @ 2012-04-25 9:06 UTC (permalink / raw)
To: Jesse Brandeburg; +Cc: netdev
In-Reply-To: <20120424145128.000070a8@unknown>
Jesse Brandeburg <jesse.brandeburg@intel.com> wrote on 2012/04/24 23:51:28:
>
> On Sat, 21 Apr 2012 15:31:09 +0200
> Joakim Tjernlund <joakim.tjernlund@transmode.se> wrote:
>
> > Looks like port 623 is some mgmt protocol and our e1000e boards are eating these
> > pkgs and this trips NIS, finger and yptest hangs for a long time before timing out and
> > moving on.
> >
> > Is there a way to tell the network stack not to eat port 623 pkgs or
> > have NIS not to use port 623?
>
> I think you might be looking for something like portreserve
> (see man portreserve)
Seen portreserve on the web(gentoo does not have it) but it seems like a workaround.
Should not eating port 623 be something one should turn on? Now it is default on
and I cannot find a way to turn it off.
Jocke
^ permalink raw reply
* Re: [PATCH 1/1] ipvs: kernel oops - do_ip_vs_get_ctl
From: Jesper Dangaard Brouer @ 2012-04-25 9:06 UTC (permalink / raw)
To: Hans Schillstrom
Cc: horms, ja, wensong, lvs-devel, netdev, netfilter-devel, hans
In-Reply-To: <1335339884-29825-1-git-send-email-hans.schillstrom@ericsson.com>
Hi Hans,
Thank you for your work.
Just some whitespace nitpicks below.
I have not been able to reproduce the bug in:
https://bugzilla.redhat.com/show_bug.cgi?id=806704
Can you recommend a (better) way to reproduce this bug?
I just want to be able to verify that this fixes the bug in question.
On Wed, 2012-04-25 at 09:44 +0200, Hans Schillstrom wrote:
> Change order of init so netns init is ready
> when register ioctl and netlink.
>
> Reported-by: "Ryan O'Hara" <rohara@redhat.com>
> Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
> ---
> include/net/ip_vs.h | 2 +
> net/netfilter/ipvs/ip_vs_core.c | 9 ++++++
> net/netfilter/ipvs/ip_vs_ctl.c | 52 ++++++++++++++++++++++----------------
> 3 files changed, 41 insertions(+), 22 deletions(-)
>
> diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
> index f967395..93b81aa 100644
> --- a/include/net/ip_vs.h
> +++ b/include/net/ip_vs.h
> @@ -1201,6 +1201,8 @@ ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol,
>
> extern int ip_vs_use_count_inc(void);
> extern void ip_vs_use_count_dec(void);
> +extern int ip_vs_register_nl_ioctl(void);
> +extern void ip_vs_unregister_nl_ioctl(void);
> extern int ip_vs_control_init(void);
> extern void ip_vs_control_cleanup(void);
> extern struct ip_vs_dest *
> diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
> index d8b1d30..c8f36b9 100644
> --- a/net/netfilter/ipvs/ip_vs_core.c
> +++ b/net/netfilter/ipvs/ip_vs_core.c
> @@ -1995,10 +1995,18 @@ static int __init ip_vs_init(void)
> goto cleanup_dev;
> }
>
> + ret = ip_vs_register_nl_ioctl();
> + if (ret < 0) {
> + pr_err("can't register netlink/ioctl.\n");
> + goto cleanup_hooks;
> + }
> +
> pr_info("ipvs loaded.\n");
>
> return ret;
>
> +cleanup_hooks:
> + nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
> cleanup_dev:
> unregister_pernet_device(&ipvs_core_dev_ops);
> cleanup_sub:
> @@ -2014,6 +2022,7 @@ exit:
>
> static void __exit ip_vs_cleanup(void)
> {
> + ip_vs_unregister_nl_ioctl();
> nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
> unregister_pernet_device(&ipvs_core_dev_ops);
> unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
> diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
> index 7131417..efaf484 100644
> --- a/net/netfilter/ipvs/ip_vs_ctl.c
> +++ b/net/netfilter/ipvs/ip_vs_ctl.c
> @@ -3750,21 +3750,10 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net)
> free_percpu(ipvs->tot_stats.cpustats);
> }
>
> -int __init ip_vs_control_init(void)
> +int ip_vs_register_nl_ioctl(void)
> {
> - int idx;
> int ret;
>
> - EnterFunction(2);
> -
> - /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
> - for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
> - INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
> - INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
> - }
> -
> - smp_wmb(); /* Do we really need it now ? */
> -
> ret = nf_register_sockopt(&ip_vs_sockopts);
> if (ret) {
> pr_err("cannot register sockopt.\n");
> @@ -3776,28 +3765,47 @@ int __init ip_vs_control_init(void)
> pr_err("cannot register Generic Netlink interface.\n");
> goto err_genl;
> }
> -
> - ret = register_netdevice_notifier(&ip_vs_dst_notifier);
> - if (ret < 0)
> - goto err_notf;
> -
> - LeaveFunction(2);
> return 0;
>
> -err_notf:
> - ip_vs_genl_unregister();
> err_genl:
> nf_unregister_sockopt(&ip_vs_sockopts);
> err_sock:
> return ret;
> }
>
> +void ip_vs_unregister_nl_ioctl(void)
There is a extra trailing whitespace behind
ip_vs_unregister_nl_ioctl(void)
> +{
> + ip_vs_genl_unregister();
> + nf_unregister_sockopt(&ip_vs_sockopts);
> +}
> +
> +int __init ip_vs_control_init(void)
> +{
> + int idx;
> + int ret;
> +
> + EnterFunction(2);
> +
> + /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
> + for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
The for loop is funny spaced...
> + INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
> + INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
> + }
> +
> + smp_wmb(); /* Do we really need it now ? */
> +
> + ret = register_netdevice_notifier(&ip_vs_dst_notifier);
> + if (ret < 0)
> + return ret;
> +
> + LeaveFunction(2);
> + return 0;
> +}
> +
>
> void ip_vs_control_cleanup(void)
> {
> EnterFunction(2);
> unregister_netdevice_notifier(&ip_vs_dst_notifier);
> - ip_vs_genl_unregister();
> - nf_unregister_sockopt(&ip_vs_sockopts);
> LeaveFunction(2);
> }
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Sr. Network Kernel Developer at Red Hat
Author of http://www.iptv-analyzer.org
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* Re: [PATCH 1/1] ipvs: kernel oops - do_ip_vs_get_ctl
From: Julian Anastasov @ 2012-04-25 8:56 UTC (permalink / raw)
To: Hans Schillstrom; +Cc: horms, wensong, lvs-devel, netdev, netfilter-devel, hans
In-Reply-To: <1335339884-29825-1-git-send-email-hans.schillstrom@ericsson.com>
Hello,
On Wed, 25 Apr 2012, Hans Schillstrom wrote:
> Change order of init so netns init is ready
> when register ioctl and netlink.
>
> Reported-by: "Ryan O'Hara" <rohara@redhat.com>
> Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
> ---
> include/net/ip_vs.h | 2 +
> net/netfilter/ipvs/ip_vs_core.c | 9 ++++++
> net/netfilter/ipvs/ip_vs_ctl.c | 52 ++++++++++++++++++++++----------------
> 3 files changed, 41 insertions(+), 22 deletions(-)
>
> diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
> index 7131417..efaf484 100644
> --- a/net/netfilter/ipvs/ip_vs_ctl.c
> +++ b/net/netfilter/ipvs/ip_vs_ctl.c
> @@ -3750,21 +3750,10 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net)
> free_percpu(ipvs->tot_stats.cpustats);
> }
>
> -int __init ip_vs_control_init(void)
> +int ip_vs_register_nl_ioctl(void)
Can we add __init here. Everything else looks good.
Regards
--
Julian Anastasov <ja@ssi.bg>
^ permalink raw reply
* re: wireless: mwifiex: initial commit for Marvell mwifiex driver
From: Dan Carpenter @ 2012-04-25 8:44 UTC (permalink / raw)
To: bzhao; +Cc: netdev
Hi Bing,
The patch 5e6e3a92b9a4: "wireless: mwifiex: initial commit for
Marvell mwifiex driver" from Mar 21, 2011, leads to the following
static checker warning:
drivers/net/wireless/mwifiex/sta_ioctl.c:1410
mwifiex_set_gen_ie_helper()
error: memcmp() 'pvendor_ie->oui' too small (3 vs 4)
1390 mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
1391 u16 ie_len)
1392 {
1393 int ret = 0;
1394 struct ieee_types_vendor_header *pvendor_ie;
1395 const u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 };
^^^^^^^^^^^^^^^^^^^^^^^^^^
4 byte array.
1396 const u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 };
1397
1398 /* If the passed length is zero, reset the buffer */
1399 if (!ie_len) {
1400 priv->gen_ie_buf_len = 0;
1401 priv->wps.session_enable = false;
1402
1403 return 0;
1404 } else if (!ie_data_ptr) {
1405 return -1;
1406 }
1407 pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
1408 /* Test to see if it is a WPA IE, if not, then it is a gen IE */
1409 if (((pvendor_ie->element_id == WLAN_EID_WPA) &&
1410 (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
^^^^^^^^^^^^^^^
->oui is only a 3 byte array so we're reading past the end for this
comparison.
1411 (pvendor_ie->element_id == WLAN_EID_RSN)) {
There are a couple other similar warnings as well:
drivers/net/wireless/mwifiex/sta_ioctl.c:1435 mwifiex_set_gen_ie_helper()
error: memcmp() 'pvendor_ie->oui' too small (3 vs 4)
drivers/net/wireless/mwifiex/scan.c:1177 mwifiex_update_bss_desc_with_ie()
error: memcmp() 'vendor_ie->vend_hdr.oui' too small (3 vs 4)
drivers/net/wireless/mwifiex/scan.c:1185 mwifiex_update_bss_desc_with_ie()
error: memcmp() 'vendor_ie->vend_hdr.oui' too small (3 vs 4)
regards,
dan carpenter
^ permalink raw reply
* Re: [RFC v4] Add TCP encap_rcv hook (repost)
From: Simon Horman @ 2012-04-25 8:39 UTC (permalink / raw)
To: Kyle Mestery (kmestery)
Cc: dev-yBygre7rU0TnMu66kgdUjQ, eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA, jhs-jkUAjuhPggJWk0Htik3J/w,
stephen.hemminger-ZtmgI6mnKB3QT0dZR+AlfA,
shemminger-ZtmgI6mnKB3QT0dZR+AlfA, David Miller
In-Reply-To: <807AC914-2F33-46C7-99DC-E2F8F0F97531-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>
On Tue, Apr 24, 2012 at 04:02:41PM +0000, Kyle Mestery (kmestery) wrote:
> On Apr 23, 2012, at 9:25 PM, Simon Horman wrote:
> > On Mon, Apr 23, 2012 at 03:59:24PM -0700, Jesse Gross wrote:
> >> On Mon, Apr 23, 2012 at 3:32 PM, Simon Horman <horms-/R6kz+dDXgpPR4JQBCEnsQ@public.gmane.org> wrote:
> >>> On Mon, Apr 23, 2012 at 02:38:07PM -0700, Jesse Gross wrote:
> >>>> On Mon, Apr 23, 2012 at 2:08 PM, David Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org> wrote:
> >>>>> From: Jesse Gross <jesse-l0M0P4e3n4LQT0dZR+AlfA@public.gmane.org>
> >>>>> Date: Mon, 23 Apr 2012 13:53:42 -0700
> >>>>>
> >>>>>> On Mon, Apr 23, 2012 at 1:13 PM, David Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org> wrote:
> >>>>>>> From: Jesse Gross <jesse-l0M0P4e3n4LQT0dZR+AlfA@public.gmane.org>
> >>>>>>> Date: Mon, 23 Apr 2012 13:08:49 -0700
> >>>>>>>
> >>>>>>>> Assuming that the TCP stack generates large TSO frames on transmit
> >>>>>>>> (which could be the local stack; something sent by a VM; or packets
> >>>>>>>> received, coalesced by GRO and then encapsulated by STT) then you can
> >>>>>>>> just prepend the STT header (possibly slightly adjusting things like
> >>>>>>>> requested MSS, number of segments, etc. slightly). After that it's
> >>>>>>>> possible to just output the resulting frame through the IP stack like
> >>>>>>>> all tunnels do today.
> >>>>>>>
> >>>>>>> Which seems to potentially suggest a stronger intergration of the STT
> >>>>>>> tunnel transmit path into our IP stack rather than the approach Simon
> >>>>>>> is taking
> >>>>>>
> >>>>>> Did you have something in mind?
> >>>>>
> >>>>> A normal bonafide tunnel netdevice driver like GRE instead of the
> >>>>> openvswitch approach Simon is using.
> >>>>
> >>>> Ahh, yes, that I agree with. Independent of this, there's work being
> >>>> done to make it so that OVS can use the normal in-tree tunneling code
> >>>> and not need its own. Once that's done I expect that STT will follow
> >>>> the same model.
> >>>
> >>> Hi Jesse,
> >>>
> >>> I am wondering how firm the plans to on allowing OVS to use in-tree tunnel
> >>> code are. I'm happy to move my efforts over to an in-tree STT implementation
> >>> but ultimately I would like to get STT running in conjunction with OVS.
> >>
> >> I would say that it's a firm goal but the implementation probably
> >> still has a ways to go. Kyle Mestery (CC'ed) has volunteered to work
> >> on this in support of adding VXLAN, which needs some additional
> >> flexibility that this approach would also provide. You might want to
> >> talk to him to see if there are ways that you guys can work together
> >> on it if you are interested. Having better integration with upstream
> >> tunneling is definitely a step that OVS needs to make and sooner would
> >> be better than later.
> >
> > Hi Jesse, Hi Kyle,
> >
> > that sounds like an excellent plan.
> >
> > Kyle, do you have any thoughts on how we might best work together on this?
> > Perhaps there are some patches floating around that I could take a look at?
> >
>
> Hi Simon:
>
> The VXLAN work has been slow going for me at this point. What I have works, but is far from complete. It's available here:
>
> https://github.com/mestery/ovs-vxlan/tree/vxlan
>
> This is based on a fairly recent version of OVS. I'm currently working to allow tunnels to be flow-based rather than port-based, as they currently exist.
> As Jesse may have mentioned, doing this allows us to move most tunnel state into user space. The outer header can now be part of the flow lookup and can
> be passed to user space, so things like multicast learning for VXLAN become possible.
>
> With regards to working together, ping me off-list and we can work something out, I'm very much in favor of this!
Hi Kyle,
the component that is of most interest to me is enabling OVS to use in-tree
tunnelling code - as it seems that makes most sense for an implementation
of STT. I have taken a brief look over your vxlan work and it isn't clear
to me if it is moving towards being an in-tree implementation. Moreover,
I'm a rather unclear on what changes need to be made to OVS in order for
in-tree tunneling to be used.
My recollection is that OVS did make use of in-tree tunnelling code
but this was removed in favour of the current implementation for various
reasons (performance being one IIRC). I gather that revisiting in-tree
tunnelling won't revisit the previous set of problems. But I'm unclear how.
Jesse, is it possible for you to describe that in a little detail
or point me to some information?
^ permalink raw reply
* Re: [PATCH 2/4] ipvs: take care of return value from protocol init_netns
From: Julian Anastasov @ 2012-04-25 8:35 UTC (permalink / raw)
To: Hans Schillstrom; +Cc: horms, wensong, lvs-devel, netdev, netfilter-devel, hans
In-Reply-To: <1335339821-29684-3-git-send-email-hans.schillstrom@ericsson.com>
Hello,
On Wed, 25 Apr 2012, Hans Schillstrom wrote:
> ip_vs_create_timeout_table() can return NULL
> All functions protocol init_netns is affected of this patch.
>
> Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
> ---
> diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
> index 6a8d176..0b74795 100644
> --- a/net/netfilter/ipvs/ip_vs_proto.c
> +++ b/net/netfilter/ipvs/ip_vs_proto.c
> @@ -79,7 +79,7 @@ register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp)
> atomic_set(&pd->appcnt, 0); /* Init app counter */
>
> if (pp->init_netns != NULL)
> - pp->init_netns(net, pd);
> + return pp->init_netns(net, pd);
May be it is better to unlink and free the pd here
if init_netns fails. Currently, protocols attach only
allocated pointer (pd->timeout_table) and it is not a
big problem to call exit_netns on failure but lets do
it safely, every init handler should release its data on
failure and then we should not call exit_netns.
Patch 1 looks ok and I'll ack it next time.
Regards
--
Julian Anastasov <ja@ssi.bg>
^ permalink raw reply
* Re: [PATCH v2 4/5] don't take cgroup_mutex in destroy()
From: Li Zefan @ 2012-04-25 8:01 UTC (permalink / raw)
To: Glauber Costa
Cc: KAMEZAWA Hiroyuki, Tejun Heo, netdev-u79uwXL29TY76Z2rM5mHXA,
cgroups-u79uwXL29TY76Z2rM5mHXA, David Miller,
devel-GEFAQzZX7r8dnm+yROfE0A, Vivek Goyal
In-Reply-To: <4F9691A8.1070106-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
Glauber Costa wrote:
> On 04/23/2012 11:31 PM, KAMEZAWA Hiroyuki wrote:
>> (2012/04/24 4:37), Glauber Costa wrote:
>>
>>> Most of the destroy functions are only doing very simple things
>>> like freeing memory.
>>>
>>> The ones who goes through lists and such, already use its own
>>> locking for those.
>>>
>>> * The cgroup itself won't go away until we free it, (after destroy)
>>> * The parent won't go away because we hold a reference count
>>> * There are no more tasks in the cgroup, and the cgroup is declared
>>> dead (cgroup_is_removed() == true)
>>>
>>> [v2: don't cgroup_lock the freezer and blkcg ]
>>>
>>> Signed-off-by: Glauber Costa<glommer-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
>>> CC: Tejun Heo<tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>>> CC: Li Zefan<lizefan-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
>>> CC: Kamezawa Hiroyuki<kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
>>> CC: Vivek Goyal<vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>>> ---
>>> kernel/cgroup.c | 9 ++++-----
>>> 1 files changed, 4 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/kernel/cgroup.c b/kernel/cgroup.c
>>> index 932c318..976d332 100644
>>> --- a/kernel/cgroup.c
>>> +++ b/kernel/cgroup.c
>>> @@ -869,13 +869,13 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
>>> * agent */
>>> synchronize_rcu();
>>>
>>> - mutex_lock(&cgroup_mutex);
>>> /*
>>> * Release the subsystem state objects.
>>> */
>>> for_each_subsys(cgrp->root, ss)
>>> ss->destroy(cgrp);
>>>
>>> + mutex_lock(&cgroup_mutex);
>>> cgrp->root->number_of_cgroups--;
>>> mutex_unlock(&cgroup_mutex);
>>>
>>> @@ -3994,13 +3994,12 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
>>>
>>> err_destroy:
>>>
>>> + mutex_unlock(&cgroup_mutex);
>>> for_each_subsys(root, ss) {
>>> if (cgrp->subsys[ss->subsys_id])
>>> ss->destroy(cgrp);
>>> }
>>>
>>> - mutex_unlock(&cgroup_mutex);
>>> -
>>> /* Release the reference count that we took on the superblock */
>>> deactivate_super(sb);
>>>
>>> @@ -4349,9 +4348,9 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
>>> int ret = cgroup_init_idr(ss, css);
>>> if (ret) {
>>> dummytop->subsys[ss->subsys_id] = NULL;
>>> + mutex_unlock(&cgroup_mutex);
>>> ss->destroy(dummytop);
>>> subsys[i] = NULL;
>>> - mutex_unlock(&cgroup_mutex);
>>> return ret;
>>> }
>>> }
>>> @@ -4447,10 +4446,10 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
>>> * pointer to find their state. note that this also takes care of
>>> * freeing the css_id.
>>> */
>>> + mutex_unlock(&cgroup_mutex);
>>> ss->destroy(dummytop);
>>> dummytop->subsys[ss->subsys_id] = NULL;
>>>
>>
>> I'm not fully sure but...dummytop->subsys[] update can be done without locking ?
>>
> I don't see a reason why updates to subsys[] after destruction shouldn't
> be safe. But maybe I am wrong.
>
> Tejun? Li?
>
It's safe for dummpytop->subsys[], but it makes the code a bit subtle.
The worst part is, it's not safe to NULLify subsys[i] without cgroup_mutex. It should be
ok to do that before calling ->destroy(), but again the code becomes a bit subtler.
^ permalink raw reply
* [PATCH 1/1] ipvs: kernel oops - do_ip_vs_get_ctl
From: Hans Schillstrom @ 2012-04-25 7:44 UTC (permalink / raw)
To: horms, ja, wensong, lvs-devel, netdev, netfilter-devel
Cc: hans, Hans Schillstrom
Change order of init so netns init is ready
when register ioctl and netlink.
Reported-by: "Ryan O'Hara" <rohara@redhat.com>
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
---
include/net/ip_vs.h | 2 +
net/netfilter/ipvs/ip_vs_core.c | 9 ++++++
net/netfilter/ipvs/ip_vs_ctl.c | 52 ++++++++++++++++++++++----------------
3 files changed, 41 insertions(+), 22 deletions(-)
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index f967395..93b81aa 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -1201,6 +1201,8 @@ ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol,
extern int ip_vs_use_count_inc(void);
extern void ip_vs_use_count_dec(void);
+extern int ip_vs_register_nl_ioctl(void);
+extern void ip_vs_unregister_nl_ioctl(void);
extern int ip_vs_control_init(void);
extern void ip_vs_control_cleanup(void);
extern struct ip_vs_dest *
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index d8b1d30..c8f36b9 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1995,10 +1995,18 @@ static int __init ip_vs_init(void)
goto cleanup_dev;
}
+ ret = ip_vs_register_nl_ioctl();
+ if (ret < 0) {
+ pr_err("can't register netlink/ioctl.\n");
+ goto cleanup_hooks;
+ }
+
pr_info("ipvs loaded.\n");
return ret;
+cleanup_hooks:
+ nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
cleanup_dev:
unregister_pernet_device(&ipvs_core_dev_ops);
cleanup_sub:
@@ -2014,6 +2022,7 @@ exit:
static void __exit ip_vs_cleanup(void)
{
+ ip_vs_unregister_nl_ioctl();
nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
unregister_pernet_device(&ipvs_core_dev_ops);
unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 7131417..efaf484 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3750,21 +3750,10 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net)
free_percpu(ipvs->tot_stats.cpustats);
}
-int __init ip_vs_control_init(void)
+int ip_vs_register_nl_ioctl(void)
{
- int idx;
int ret;
- EnterFunction(2);
-
- /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
- for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
- INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
- INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
- }
-
- smp_wmb(); /* Do we really need it now ? */
-
ret = nf_register_sockopt(&ip_vs_sockopts);
if (ret) {
pr_err("cannot register sockopt.\n");
@@ -3776,28 +3765,47 @@ int __init ip_vs_control_init(void)
pr_err("cannot register Generic Netlink interface.\n");
goto err_genl;
}
-
- ret = register_netdevice_notifier(&ip_vs_dst_notifier);
- if (ret < 0)
- goto err_notf;
-
- LeaveFunction(2);
return 0;
-err_notf:
- ip_vs_genl_unregister();
err_genl:
nf_unregister_sockopt(&ip_vs_sockopts);
err_sock:
return ret;
}
+void ip_vs_unregister_nl_ioctl(void)
+{
+ ip_vs_genl_unregister();
+ nf_unregister_sockopt(&ip_vs_sockopts);
+}
+
+int __init ip_vs_control_init(void)
+{
+ int idx;
+ int ret;
+
+ EnterFunction(2);
+
+ /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
+ for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
+ INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
+ INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
+ }
+
+ smp_wmb(); /* Do we really need it now ? */
+
+ ret = register_netdevice_notifier(&ip_vs_dst_notifier);
+ if (ret < 0)
+ return ret;
+
+ LeaveFunction(2);
+ return 0;
+}
+
void ip_vs_control_cleanup(void)
{
EnterFunction(2);
unregister_netdevice_notifier(&ip_vs_dst_notifier);
- ip_vs_genl_unregister();
- nf_unregister_sockopt(&ip_vs_sockopts);
LeaveFunction(2);
}
--
1.7.2.3
^ permalink raw reply related
* [PATCH 1/2] ipvs: null check of net->ipvs in lblc(r) shedulers
From: Hans Schillstrom @ 2012-04-25 7:43 UTC (permalink / raw)
To: horms, ja, wensong, lvs-devel, netdev, netfilter-devel
Cc: hans, Hans Schillstrom
In-Reply-To: <1335339821-29684-1-git-send-email-hans.schillstrom@ericsson.com>
Avoid crash when registering shedulers after
the IPVS core initialization for netns fails. Do this by
checking for present core (net->ipvs).
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
---
net/netfilter/ipvs/ip_vs_lblc.c | 3 +++
net/netfilter/ipvs/ip_vs_lblcr.c | 3 +++
2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index 222b6cb..df646cc 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -551,6 +551,9 @@ static int __net_init __ip_vs_lblc_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
+ if (!ipvs)
+ return -ENOENT;
+
if (!net_eq(net, &init_net)) {
ipvs->lblc_ctl_table = kmemdup(vs_vars_table,
sizeof(vs_vars_table),
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index 30c476f..570e31e 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -745,6 +745,9 @@ static int __net_init __ip_vs_lblcr_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
+ if (!ipvs)
+ return -ENOENT;
+
if (!net_eq(net, &init_net)) {
ipvs->lblcr_ctl_table = kmemdup(vs_vars_table,
sizeof(vs_vars_table),
--
1.7.2.3
^ permalink raw reply related
* [PATCH 0/2] ipvs: netns avoid crash at netns init
From: Hans Schillstrom @ 2012-04-25 7:43 UTC (permalink / raw)
To: horms, ja, wensong, lvs-devel, netdev, netfilter-devel
Cc: hans, Hans Schillstrom
Two simple patches that avoid crashes for no memory at netns init.
- Check return value of protocoll init.
- Null check of net-ipvs in shedulers.
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
--
1.7.2.3
^ permalink raw reply
* [PATCH 2/4] ipvs: take care of return value from protocol init_netns
From: Hans Schillstrom @ 2012-04-25 7:43 UTC (permalink / raw)
To: horms, ja, wensong, lvs-devel, netdev, netfilter-devel
Cc: hans, Hans Schillstrom
In-Reply-To: <1335339821-29684-1-git-send-email-hans.schillstrom@ericsson.com>
ip_vs_create_timeout_table() can return NULL
All functions protocol init_netns is affected of this patch.
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
---
include/net/ip_vs.h | 2 +-
net/netfilter/ipvs/ip_vs_proto.c | 2 +-
net/netfilter/ipvs/ip_vs_proto_sctp.c | 5 ++++-
net/netfilter/ipvs/ip_vs_proto_tcp.c | 5 ++++-
net/netfilter/ipvs/ip_vs_proto_udp.c | 5 ++++-
5 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 990216d..f967395 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -392,7 +392,7 @@ struct ip_vs_protocol {
void (*exit)(struct ip_vs_protocol *pp);
- void (*init_netns)(struct net *net, struct ip_vs_proto_data *pd);
+ int (*init_netns)(struct net *net, struct ip_vs_proto_data *pd);
void (*exit_netns)(struct net *net, struct ip_vs_proto_data *pd);
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index 6a8d176..0b74795 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -79,7 +79,7 @@ register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp)
atomic_set(&pd->appcnt, 0); /* Init app counter */
if (pp->init_netns != NULL)
- pp->init_netns(net, pd);
+ return pp->init_netns(net, pd);
return 0;
}
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index 1fbf7a2..9f3fb75 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -1090,7 +1090,7 @@ out:
* timeouts is netns related now.
* ---------------------------------------------
*/
-static void __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd)
+static int __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -1098,6 +1098,9 @@ static void __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd)
spin_lock_init(&ipvs->sctp_app_lock);
pd->timeout_table = ip_vs_create_timeout_table((int *)sctp_timeouts,
sizeof(sctp_timeouts));
+ if (!pd->timeout_table)
+ return -ENOMEM;
+ return 0;
}
static void __ip_vs_sctp_exit(struct net *net, struct ip_vs_proto_data *pd)
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index ef8641f..cd609cc 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -677,7 +677,7 @@ void ip_vs_tcp_conn_listen(struct net *net, struct ip_vs_conn *cp)
* timeouts is netns related now.
* ---------------------------------------------
*/
-static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
+static int __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -685,7 +685,10 @@ static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
spin_lock_init(&ipvs->tcp_app_lock);
pd->timeout_table = ip_vs_create_timeout_table((int *)tcp_timeouts,
sizeof(tcp_timeouts));
+ if (!pd->timeout_table)
+ return -ENOMEM;
pd->tcp_state_table = tcp_states;
+ return 0;
}
static void __ip_vs_tcp_exit(struct net *net, struct ip_vs_proto_data *pd)
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index f4b7262..2fedb2d 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -467,7 +467,7 @@ udp_state_transition(struct ip_vs_conn *cp, int direction,
cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL];
}
-static void __udp_init(struct net *net, struct ip_vs_proto_data *pd)
+static int __udp_init(struct net *net, struct ip_vs_proto_data *pd)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -475,6 +475,9 @@ static void __udp_init(struct net *net, struct ip_vs_proto_data *pd)
spin_lock_init(&ipvs->udp_app_lock);
pd->timeout_table = ip_vs_create_timeout_table((int *)udp_timeouts,
sizeof(udp_timeouts));
+ if (!pd->timeout_table)
+ return -ENOMEM;
+ return 0;
}
static void __udp_exit(struct net *net, struct ip_vs_proto_data *pd)
--
1.7.2.3
^ permalink raw reply related
* Re: [PATCH net-next] ipv6: RTAX_FEATURE_ALLFRAG causes inefficient TCP segment sizing
From: Maciej Żenczykowski @ 2012-04-25 7:34 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Tore Anderson, David Miller, netdev, Tom Herbert
In-Reply-To: <1335331960.5205.180.camel@edumazet-glaptop>
> But we chose to _not_ decrease mtu and adhere to the specs.
I get that we _choose_ to behave such, and I agree this adheres to specs.
But I'm not convinced that (even though this is allowed per RFC) this
is the right choice.
> Current linux chose to implement the allfragfeature, so match RFC 2460
> specs.
>
> If you want to reduce size of subsequent packets, its a lot more work in
> linux stack, for small gain, if any.
True, but this is work at the source host (and indeed might possibly
even be done by tso hardware or at least by gso),
which is reducing work at whatever the actual tunneling point is.
It's not actually affecting how much
work the receiver has to do (indeed it might even decrease it, imagine
sending 3840 bytes, getting that
fragmented into 6 packets: 1000, 280, 1000, 280, 1000, 280 instead of
just 4 packets: 1000, 1000,
1000, 840 [obviously would need to correct for header overhead, but
the basis stands])
[side note: indeed 1280 should never be split 1000 + 280, but should
rather be split into even pieces 640 + 640, to help prevent need for
further fragmentation further down the line]
Tunneling points are traditionally cpu starved.
Also note that IPv6 prefers to see fragmentation happen at the end
hosts, and not at the routers.
Although of course it doesn't treat a tunnel end point as a router.
Also packet loss is better handled by tcp losing segments than by the
tunnel losing a fragment and thus losing the entire packet.
I guess I simply think we're making the wrong trade off here.
> We only need to properly generate the fragment header, that means
> reducing the _payload_ by 8 bytes. Not reducing the _mtu_ that still is
> 1280, as allowed.
>
> IPv6 must cohabit with IPv4 for the next years, there is no hope
> thinking it can ignore tunnelings issues, since tunneling is part of the
> global IPv6 transition that is currently happening.
To be fair this probably isn't super-related to the vast majority of
IPv4, the vast majority of the IPv4 world out there has mtu's easily
in excess of 1280+tunneling overhead bytes.
I wonder if anyone has any statistics, but I'd guess 99.99% of the
IPv4 internet is 1400+ MTU.
^ permalink raw reply
* [PATCH 2/2] ss: implement -M option to get all memory information
From: Shan Wei @ 2012-04-25 7:15 UTC (permalink / raw)
To: Stephen Hemminger, xemul, NetDev
From: Shan Wei <davidshan@tencent.com>
INET_DIAG_SKMEMINFO is used to monitor socket memory information
which contains more information than INET_DIAG_MEMINFO.
-m option is retained for old kernel that don't surpport INET_DIAG_SKMEMINFO.
Signed-off-by: Shan Wei <davidshan@tencent.com>
---
misc/ss.c | 27 +++++++++++++++++++++++++--
1 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/misc/ss.c b/misc/ss.c
index 5f70a26..3c8befd 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -45,6 +45,7 @@ int show_options = 0;
int show_details = 0;
int show_users = 0;
int show_mem = 0;
+int show_skmem = 0;
int show_tcpinfo = 0;
int netid_width;
@@ -1410,6 +1411,19 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r)
printf(" rcv_space:%d", info->tcpi_rcv_space);
}
+
+ if (tb[INET_DIAG_SKMEMINFO]) {
+ const unsigned int *skmeminfo = RTA_DATA(tb[INET_DIAG_SKMEMINFO]);
+ printf(" skmem:(r%u,rb%u,t%u,tb%u,f%u,w%u,o%u)",
+ skmeminfo[SK_MEMINFO_RMEM_ALLOC],
+ skmeminfo[SK_MEMINFO_RCVBUF],
+ skmeminfo[SK_MEMINFO_WMEM_ALLOC],
+ skmeminfo[SK_MEMINFO_SNDBUF],
+ skmeminfo[SK_MEMINFO_FWD_ALLOC],
+ skmeminfo[SK_MEMINFO_WMEM_QUEUED],
+ skmeminfo[SK_MEMINFO_OPTMEM]);
+ }
+
}
static int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f)
@@ -1466,7 +1480,7 @@ static int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f)
printf("%08x", r->id.idiag_cookie[1]);
printf("%08x", r->id.idiag_cookie[0]);
}
- if (show_mem || show_tcpinfo) {
+ if (show_mem || show_tcpinfo || show_skmem) {
printf("\n\t");
tcp_show_info(nlh, r);
}
@@ -1508,6 +1522,9 @@ static int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype)
if (show_mem)
req.r.idiag_ext |= (1<<(INET_DIAG_MEMINFO-1));
+ if (show_skmem)
+ req.r.idiag_ext |= (1<<(INET_DIAG_SKMEMINFO-1));
+
if (show_tcpinfo) {
req.r.idiag_ext |= (1<<(INET_DIAG_INFO-1));
req.r.idiag_ext |= (1<<(INET_DIAG_VEGASINFO-1));
@@ -2581,6 +2598,8 @@ static void _usage(FILE *dest)
" -o, --options show timer information\n"
" -e, --extended show detailed socket information\n"
" -m, --memory show socket memory usage\n"
+" -M, --skmem show socket memory information.\n"
+" this option which will replace -m, is valid since Linux 3.3.\n"
" -p, --processes show process using socket\n"
" -i, --info show internal TCP information\n"
" -s, --summary show socket usage summary\n"
@@ -2652,6 +2671,7 @@ static const struct option long_opts[] = {
{ "options", 0, 0, 'o' },
{ "extended", 0, 0, 'e' },
{ "memory", 0, 0, 'm' },
+ { "skmem", 0, 0, 'M'}
{ "info", 0, 0, 'i' },
{ "processes", 0, 0, 'p' },
{ "dccp", 0, 0, 'd' },
@@ -2690,7 +2710,7 @@ int main(int argc, char *argv[])
current_filter.states = default_filter.states;
- while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spf:miA:D:F:vV",
+ while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spf:mMiA:D:F:vV",
long_opts, NULL)) != EOF) {
switch(ch) {
case 'n':
@@ -2709,6 +2729,9 @@ int main(int argc, char *argv[])
case 'm':
show_mem = 1;
break;
+ case 'M':
+ show_skmem = 1;
+ break;
case 'i':
show_tcpinfo = 1;
break;
--
1.7.1
^ permalink raw reply related
* [PATCH 1/2] ss: fix the incorrect value of total UNIX_DIAG_* number
From: Shan Wei @ 2012-04-25 7:15 UTC (permalink / raw)
To: xemul, Stephen Hemminger; +Cc: NetDev
From: Shan Wei <davidshan@tencent.com>
UNIX_DIAG_MAX is included in enum type.
It is equal to the total number of enum element.
But lots of enum MAX value is defined as the max enum element, e.g. INET_DIAG_MAX, XFRMA_MAX.
The right fixing way seems to define UNIX_DIAG_MAX as UNIX_DIAG_MEMINFO,
but this way will break other user application.
So, just fix it on user application.
Signed-off-by: Shan Wei <davidshan@tencent.com>
---
misc/ss.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/misc/ss.c b/misc/ss.c
index 4017918..5f70a26 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -2011,12 +2011,12 @@ void unix_list_print(struct unixstat *list, struct filter *f)
static int unix_show_sock(struct nlmsghdr *nlh, struct filter *f)
{
struct unix_diag_msg *r = NLMSG_DATA(nlh);
- struct rtattr *tb[UNIX_DIAG_MAX+1];
+ struct rtattr *tb[UNIX_DIAG_MAX];
char name[128];
int peer_ino;
int rqlen;
- parse_rtattr(tb, UNIX_DIAG_MAX, (struct rtattr*)(r+1),
+ parse_rtattr(tb, UNIX_DIAG_MAX-1, (struct rtattr*)(r+1),
nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
if (netid_width)
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] isdn/eicon: use standard __init,__exit function markup
From: Armin Schindler @ 2012-04-25 6:48 UTC (permalink / raw)
To: H Hartley Sweeten; +Cc: Linux Kernel, netdev, isdn
In-Reply-To: <201204241556.03516.hartleys@visionengravers.com>
What is the reason for this change?
Armin
On 04/25/2012 12:56 AM, H Hartley Sweeten wrote:
> Remove the custom DIVA_{INIT,EXIT}_FUNCTION defines and use
> the standard __init,__exit markup.
>
> Signed-off-by: H Hartley Sweeten<hsweeten@visionengravers.com>
> Cc: Armin Schindler<mac@melware.de>
> Cc: Karsten Keil<isdn@linux-pingi.de>
>
> ---
>
> diff --git a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c
> index a576f32..7a0bdbd 100644
> --- a/drivers/isdn/hardware/eicon/capifunc.c
> +++ b/drivers/isdn/hardware/eicon/capifunc.c
> @@ -1120,7 +1120,7 @@ int fax_head_line_time(char *buffer)
> /*
> * init (alloc) main structures
> */
> -static int DIVA_INIT_FUNCTION init_main_structs(void)
> +static int __init init_main_structs(void)
> {
> if (!(mapped_msg = (CAPI_MSG *) diva_os_malloc(0, MAX_MSG_SIZE))) {
> DBG_ERR(("init: failed alloc mapped_msg."))
> @@ -1181,7 +1181,7 @@ static void do_api_remove_start(void)
> /*
> * init
> */
> -int DIVA_INIT_FUNCTION init_capifunc(void)
> +int __init init_capifunc(void)
> {
> diva_os_initialize_spin_lock(&api_lock, "capifunc");
> memset(ControllerMap, 0, MAX_DESCRIPTORS + 1);
> @@ -1209,7 +1209,7 @@ int DIVA_INIT_FUNCTION init_capifunc(void)
> /*
> * finit
> */
> -void DIVA_EXIT_FUNCTION finit_capifunc(void)
> +void __exit finit_capifunc(void)
> {
> do_api_remove_start();
> divacapi_disconnect_didd();
> diff --git a/drivers/isdn/hardware/eicon/capimain.c b/drivers/isdn/hardware/eicon/capimain.c
> index eabe0fa..997d46a 100644
> --- a/drivers/isdn/hardware/eicon/capimain.c
> +++ b/drivers/isdn/hardware/eicon/capimain.c
> @@ -118,7 +118,7 @@ void diva_os_set_controller_struct(struct capi_ctr *ctrl)
> /*
> * module init
> */
> -static int DIVA_INIT_FUNCTION divacapi_init(void)
> +static int __init divacapi_init(void)
> {
> char tmprev[32];
> int ret = 0;
> @@ -144,7 +144,7 @@ static int DIVA_INIT_FUNCTION divacapi_init(void)
> /*
> * module exit
> */
> -static void DIVA_EXIT_FUNCTION divacapi_exit(void)
> +static void __exit divacapi_exit(void)
> {
> finit_capifunc();
> printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
> diff --git a/drivers/isdn/hardware/eicon/diddfunc.c b/drivers/isdn/hardware/eicon/diddfunc.c
> index c4c8220..b0b23ed 100644
> --- a/drivers/isdn/hardware/eicon/diddfunc.c
> +++ b/drivers/isdn/hardware/eicon/diddfunc.c
> @@ -47,7 +47,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
> /*
> * connect to didd
> */
> -static int DIVA_INIT_FUNCTION connect_didd(void)
> +static int __init connect_didd(void)
> {
> int x = 0;
> int dadapter = 0;
> @@ -79,7 +79,7 @@ static int DIVA_INIT_FUNCTION connect_didd(void)
> /*
> * disconnect from didd
> */
> -static void DIVA_EXIT_FUNCTION disconnect_didd(void)
> +static void __exit disconnect_didd(void)
> {
> IDI_SYNC_REQ req;
>
> @@ -92,7 +92,7 @@ static void DIVA_EXIT_FUNCTION disconnect_didd(void)
> /*
> * init
> */
> -int DIVA_INIT_FUNCTION diddfunc_init(void)
> +int __init diddfunc_init(void)
> {
> diva_didd_load_time_init();
>
> @@ -107,7 +107,7 @@ int DIVA_INIT_FUNCTION diddfunc_init(void)
> /*
> * finit
> */
> -void DIVA_EXIT_FUNCTION diddfunc_finit(void)
> +void __exit diddfunc_finit(void)
> {
> DbgDeregister();
> disconnect_didd();
> diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c
> index d1d3de0..fab6ccf 100644
> --- a/drivers/isdn/hardware/eicon/diva_didd.c
> +++ b/drivers/isdn/hardware/eicon/diva_didd.c
> @@ -91,7 +91,7 @@ static const struct file_operations divadidd_proc_fops = {
> .release = single_release,
> };
>
> -static int DIVA_INIT_FUNCTION create_proc(void)
> +static int __init create_proc(void)
> {
> proc_net_eicon = proc_mkdir("eicon", init_net.proc_net);
>
> @@ -109,7 +109,7 @@ static void remove_proc(void)
> remove_proc_entry("eicon", init_net.proc_net);
> }
>
> -static int DIVA_INIT_FUNCTION divadidd_init(void)
> +static int __init divadidd_init(void)
> {
> char tmprev[32];
> int ret = 0;
> @@ -141,7 +141,7 @@ out:
> return (ret);
> }
>
> -static void DIVA_EXIT_FUNCTION divadidd_exit(void)
> +static void __exit divadidd_exit(void)
> {
> diddfunc_finit();
> remove_proc();
> diff --git a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c
> index ffa0c31..48db08d 100644
> --- a/drivers/isdn/hardware/eicon/divamnt.c
> +++ b/drivers/isdn/hardware/eicon/divamnt.c
> @@ -184,7 +184,7 @@ static void divas_maint_unregister_chrdev(void)
> unregister_chrdev(major, DEVNAME);
> }
>
> -static int DIVA_INIT_FUNCTION divas_maint_register_chrdev(void)
> +static int __init divas_maint_register_chrdev(void)
> {
> if ((major = register_chrdev(0, DEVNAME,&divas_maint_fops))< 0)
> {
> @@ -207,7 +207,7 @@ void diva_maint_wakeup_read(void)
> /*
> * Driver Load
> */
> -static int DIVA_INIT_FUNCTION maint_init(void)
> +static int __init maint_init(void)
> {
> char tmprev[50];
> int ret = 0;
> @@ -245,7 +245,7 @@ out:
> /*
> ** Driver Unload
> */
> -static void DIVA_EXIT_FUNCTION maint_exit(void)
> +static void __exit maint_exit(void)
> {
> divas_maint_unregister_chrdev();
> mntfunc_finit();
> diff --git a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c
> index 60aaf95..4be5f88 100644
> --- a/drivers/isdn/hardware/eicon/divasfunc.c
> +++ b/drivers/isdn/hardware/eicon/divasfunc.c
> @@ -153,7 +153,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
> /*
> * connect to didd
> */
> -static int DIVA_INIT_FUNCTION connect_didd(void)
> +static int __init connect_didd(void)
> {
> int x = 0;
> int dadapter = 0;
> @@ -209,7 +209,7 @@ static void disconnect_didd(void)
> /*
> * init
> */
> -int DIVA_INIT_FUNCTION divasfunc_init(int dbgmask)
> +int __init divasfunc_init(int dbgmask)
> {
> char *version;
>
> diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c
> index a5c8f90..4103a8c 100644
> --- a/drivers/isdn/hardware/eicon/divasi.c
> +++ b/drivers/isdn/hardware/eicon/divasi.c
> @@ -114,7 +114,7 @@ static const struct file_operations um_idi_proc_fops = {
> .release = single_release,
> };
>
> -static int DIVA_INIT_FUNCTION create_um_idi_proc(void)
> +static int __init create_um_idi_proc(void)
> {
> um_idi_proc_entry = proc_create(DRIVERLNAME, S_IRUGO, proc_net_eicon,
> &um_idi_proc_fops);
> @@ -146,7 +146,7 @@ static void divas_idi_unregister_chrdev(void)
> unregister_chrdev(major, DEVNAME);
> }
>
> -static int DIVA_INIT_FUNCTION divas_idi_register_chrdev(void)
> +static int __init divas_idi_register_chrdev(void)
> {
> if ((major = register_chrdev(0, DEVNAME,&divas_idi_fops))< 0)
> {
> @@ -161,7 +161,7 @@ static int DIVA_INIT_FUNCTION divas_idi_register_chrdev(void)
> /*
> ** Driver Load
> */
> -static int DIVA_INIT_FUNCTION divasi_init(void)
> +static int __init divasi_init(void)
> {
> char tmprev[50];
> int ret = 0;
> @@ -202,7 +202,7 @@ out:
> /*
> ** Driver Unload
> */
> -static void DIVA_EXIT_FUNCTION divasi_exit(void)
> +static void __exit divasi_exit(void)
> {
> idifunc_finit();
> remove_um_idi_proc();
> diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
> index 7eaab06..ca6d276 100644
> --- a/drivers/isdn/hardware/eicon/divasmain.c
> +++ b/drivers/isdn/hardware/eicon/divasmain.c
> @@ -673,7 +673,7 @@ static void divas_unregister_chrdev(void)
> unregister_chrdev(major, DEVNAME);
> }
>
> -static int DIVA_INIT_FUNCTION divas_register_chrdev(void)
> +static int __init divas_register_chrdev(void)
> {
> if ((major = register_chrdev(0, DEVNAME,&divas_fops))< 0)
> {
> @@ -767,7 +767,7 @@ static void __devexit divas_remove_one(struct pci_dev *pdev)
> /* --------------------------------------------------------------------------
> Driver Load / Startup
> -------------------------------------------------------------------------- */
> -static int DIVA_INIT_FUNCTION divas_init(void)
> +static int __init divas_init(void)
> {
> char tmprev[50];
> int ret = 0;
> @@ -831,7 +831,7 @@ out:
> /* --------------------------------------------------------------------------
> Driver Unload
> -------------------------------------------------------------------------- */
> -static void DIVA_EXIT_FUNCTION divas_exit(void)
> +static void __exit divas_exit(void)
> {
> pci_unregister_driver(&diva_pci_driver);
> remove_divas_proc();
> diff --git a/drivers/isdn/hardware/eicon/idifunc.c b/drivers/isdn/hardware/eicon/idifunc.c
> index d153e3c..fef6586 100644
> --- a/drivers/isdn/hardware/eicon/idifunc.c
> +++ b/drivers/isdn/hardware/eicon/idifunc.c
> @@ -133,7 +133,7 @@ static void um_remove_card(DESCRIPTOR *d)
> /*
> * remove all adapter
> */
> -static void DIVA_EXIT_FUNCTION remove_all_idi_proc(void)
> +static void __exit remove_all_idi_proc(void)
> {
> udiva_card *card;
> diva_os_spin_lock_magic_t old_irql;
> @@ -181,7 +181,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
> /*
> * connect DIDD
> */
> -static int DIVA_INIT_FUNCTION connect_didd(void)
> +static int __init connect_didd(void)
> {
> int x = 0;
> int dadapter = 0;
> @@ -225,7 +225,7 @@ static int DIVA_INIT_FUNCTION connect_didd(void)
> /*
> * Disconnect from DIDD
> */
> -static void DIVA_EXIT_FUNCTION disconnect_didd(void)
> +static void __exit disconnect_didd(void)
> {
> IDI_SYNC_REQ req;
>
> @@ -240,7 +240,7 @@ static void DIVA_EXIT_FUNCTION disconnect_didd(void)
> /*
> * init
> */
> -int DIVA_INIT_FUNCTION idifunc_init(void)
> +int __init idifunc_init(void)
> {
> diva_os_initialize_spin_lock(&ll_lock, "idifunc");
>
> @@ -260,7 +260,7 @@ int DIVA_INIT_FUNCTION idifunc_init(void)
> /*
> * finit
> */
> -void DIVA_EXIT_FUNCTION idifunc_finit(void)
> +void __exit idifunc_finit(void)
> {
> diva_user_mode_idi_finit();
> disconnect_didd();
> diff --git a/drivers/isdn/hardware/eicon/mntfunc.c b/drivers/isdn/hardware/eicon/mntfunc.c
> index d607260..1cd9aff 100644
> --- a/drivers/isdn/hardware/eicon/mntfunc.c
> +++ b/drivers/isdn/hardware/eicon/mntfunc.c
> @@ -72,7 +72,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
> /*
> * connect to didd
> */
> -static int DIVA_INIT_FUNCTION connect_didd(void)
> +static int __init connect_didd(void)
> {
> int x = 0;
> int dadapter = 0;
> @@ -114,7 +114,7 @@ static int DIVA_INIT_FUNCTION connect_didd(void)
> /*
> * disconnect from didd
> */
> -static void DIVA_EXIT_FUNCTION disconnect_didd(void)
> +static void __exit disconnect_didd(void)
> {
> IDI_SYNC_REQ req;
>
> @@ -300,7 +300,7 @@ int maint_read_write(void __user *buf, int count)
> /*
> * init
> */
> -int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
> +int __init mntfunc_init(int *buffer_length, void **buffer,
> unsigned long diva_dbg_mem)
> {
> if (*buffer_length< 64) {
> @@ -348,7 +348,7 @@ int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
> /*
> * exit
> */
> -void DIVA_EXIT_FUNCTION mntfunc_finit(void)
> +void __exit mntfunc_finit(void)
> {
> void *buffer;
> int i = 100;
> diff --git a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h
> index 7331c3b..b2edb75 100644
> --- a/drivers/isdn/hardware/eicon/platform.h
> +++ b/drivers/isdn/hardware/eicon/platform.h
> @@ -38,9 +38,6 @@
> #define DIVA_NO_DEBUGLIB
> #endif
>
> -#define DIVA_INIT_FUNCTION __init
> -#define DIVA_EXIT_FUNCTION __exit
> -
> #define DIVA_USER_MODE_CARD_CONFIG 1
> #define USE_EXTENDED_DEBUGS 1
>
--
Mit freundlichen Grüßen / Best regards
Armin Schindler
Cytronics & Melware
Weinbergstrasse 39, 55296 Loerzweiler / Germany
Tel: +49 6138 99998-100
Fax: +49 6138 99998-109
VoIP: sip:info@melware.net
mailto:info@melware.de
http://www.melware.de
^ permalink raw reply
* [PATCH 2/4] mISDN: Using FLG_ACTIVE flag to determine if layer 1 is active or not.
From: Karsten Keil @ 2012-04-25 6:52 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Andreas Eversberg
In-Reply-To: <1335336734-25181-1-git-send-email-kkeil@linux-pingi.de>
From: Andreas Eversberg <andreas@eversberg.eu>
We already have the flag for L1 active, so we should use it.
L2 will be solved in a later patch.
Signed-off-by: Andreas Eversberg <andreas@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/hardware/mISDN/hfcmulti.c | 25 ++++++++++---------------
1 files changed, 10 insertions(+), 15 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index c4e7fda..cc978e8 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -1619,10 +1619,16 @@ hfcmulti_leds(struct hfc_multi *hc)
* 2 red steady: TE mode deactivate
* left green: L1 active
* left red: frame sync, but no L1
- * right green: L2 active
+ * todo right green: L2 active
*/
- if (hc->chan[hc->dslot].sync != 2) { /* no frame sync */
- if (hc->chan[hc->dslot].dch->dev.D.protocol
+ dch = hc->chan[hc->dslot].dch;
+ if (test_bit(FLG_ACTIVE, &dch->Flags)) {
+ led[0] = 0;
+ led[1] = 0;
+ led[2] = 0;
+ led[3] = 1;
+ } else {
+ if (dch->dev.D.protocol
!= ISDN_P_NT_E1) {
led[0] = 1;
led[1] = 1;
@@ -1635,12 +1641,6 @@ hfcmulti_leds(struct hfc_multi *hc)
}
led[2] = 0;
led[3] = 0;
- } else { /* with frame sync */
- /* TODO make it work */
- led[0] = 0;
- led[1] = 0;
- led[2] = 0;
- led[3] = 1;
}
leds = (led[0] | (led[1]<<2) | (led[2]<<1) | (led[3]<<3))^0xF;
/* leds are inverted */
@@ -4062,14 +4062,9 @@ open_dchannel(struct hfc_multi *hc, struct dchannel *dch,
hfcmulti_initmode(dch);
spin_unlock_irqrestore(&hc->lock, flags);
}
-
- if (((rq->protocol == ISDN_P_NT_S0) && (dch->state == 3)) ||
- ((rq->protocol == ISDN_P_TE_S0) && (dch->state == 7)) ||
- ((rq->protocol == ISDN_P_NT_E1) && (dch->state == 1)) ||
- ((rq->protocol == ISDN_P_TE_E1) && (dch->state == 1))) {
+ if (test_bit(FLG_ACTIVE, &dch->Flags))
_queue_data(&dch->dev.D, PH_ACTIVATE_IND, MISDN_ID_ANY,
0, NULL, GFP_KERNEL);
- }
rq->ch = &dch->dev.D;
if (!try_module_get(THIS_MODULE))
printk(KERN_WARNING "%s:cannot get module\n", __func__);
--
1.7.3.4
^ permalink raw reply related
* [PATCH 1/4] mISDN: Fixed false interruption of audio during bridging change.
From: Karsten Keil @ 2012-04-25 6:52 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Andreas Eversberg
In-Reply-To: <1335336734-25181-1-git-send-email-kkeil@linux-pingi.de>
From: Andreas Eversberg <jolly@eversberg.eu>
Transmitted audio data was interrupted if a bridge was enabled or disabled.
Now transmission seamlessly continues during that action.
Fix in hfcmulti.ko
Signed-off-by: Andreas Eversberg <jolly@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/hardware/mISDN/hfcmulti.c | 24 ++++++++++++++++--------
1 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index 0332231..c4e7fda 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -3018,8 +3018,10 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
HFC_outb(hc, A_CON_HDLC, 0x20 | V_HDLC_TRP | V_IFF);
HFC_outb(hc, A_SUBCH_CFG, 0);
HFC_outb(hc, A_IRQ_MSK, 0);
- HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
- HFC_wait(hc);
+ if (hc->chan[ch].protocol != protocol) {
+ HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+ HFC_wait(hc);
+ }
HFC_outb(hc, R_SLOT, ((((ch / 4) * 8) +
((ch % 4) * 4) + 1) << 1) | 1);
HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1) | 1);
@@ -3039,8 +3041,10 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
HFC_outb(hc, A_CON_HDLC, 0x20 | V_HDLC_TRP | V_IFF);
HFC_outb(hc, A_SUBCH_CFG, 0);
HFC_outb(hc, A_IRQ_MSK, 0);
- HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
- HFC_wait(hc);
+ if (hc->chan[ch].protocol != protocol) {
+ HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+ HFC_wait(hc);
+ }
/* tx silence */
HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
HFC_outb(hc, R_SLOT, (((ch / 4) * 8) +
@@ -3059,8 +3063,10 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
V_HDLC_TRP | V_IFF);
HFC_outb(hc, A_SUBCH_CFG, 0);
HFC_outb(hc, A_IRQ_MSK, 0);
- HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
- HFC_wait(hc);
+ if (hc->chan[ch].protocol != protocol) {
+ HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+ HFC_wait(hc);
+ }
/* tx silence */
HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
/* enable RX fifo */
@@ -3075,8 +3081,10 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
V_HDLC_TRP);
HFC_outb(hc, A_SUBCH_CFG, 0);
HFC_outb(hc, A_IRQ_MSK, 0);
- HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
- HFC_wait(hc);
+ if (hc->chan[ch].protocol != protocol) {
+ HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
+ HFC_wait(hc);
+ }
}
if (hc->ctype != HFC_TYPE_E1) {
hc->hw.a_st_ctrl0[hc->chan[ch].port] |=
--
1.7.3.4
^ permalink raw reply related
* [PATCH 3/4] mISDN: Rework of LED status display for HFC-4S/8S/E1 cards.
From: Karsten Keil @ 2012-04-25 6:52 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Andreas Eversberg
In-Reply-To: <1335336734-25181-1-git-send-email-kkeil@linux-pingi.de>
From: Andreas Eversberg <jolly@eversberg.eu>
LEDs will show RED if layer 1 is disabled or fails.
LEDs will show GREEN if layer 1 is active.
LEDs will blink if traffic on D-channel.
Signed-off-by: Andreas Eversberg <jolly@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/hardware/mISDN/hfc_multi.h | 9 +-
drivers/isdn/hardware/mISDN/hfcmulti.c | 157 ++++++++++++++++++-------------
2 files changed, 95 insertions(+), 71 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h
index b0588ac..09e4e77 100644
--- a/drivers/isdn/hardware/mISDN/hfc_multi.h
+++ b/drivers/isdn/hardware/mISDN/hfc_multi.h
@@ -205,18 +205,19 @@ struct hfc_multi {
u_int slots; /* number of PCM slots */
u_int leds; /* type of leds */
- u_int ledcount; /* used to animate leds */
u_long ledstate; /* save last state of leds */
int opticalsupport; /* has the e1 board */
/* an optical Interface */
int dslot; /* channel # of d-channel (E1) default 16 */
+ u_int activity_tx; /* if there is data TX / RX */
+ u_int activity_rx; /* bitmask according to port number */
+ /* (will be cleared after */
+ /* showing led-states) */
+ u_int flash[8]; /* counter for flashing 8 leds on activity */
u_long wdcount; /* every 500 ms we need to */
/* send the watchdog a signal */
u_char wdbyte; /* watchdog toggle byte */
- u_int activity[8]; /* if there is any action on this */
- /* port (will be cleared after */
- /* showing led-states) */
int e1_state; /* keep track of last state */
int e1_getclock; /* if sync is retrieved from interface */
int syncronized; /* keep track of existing sync interface */
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index cc978e8..876f7d0 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -1607,40 +1607,46 @@ hfcmulti_leds(struct hfc_multi *hc)
struct dchannel *dch;
int led[4];
- hc->ledcount += poll;
- if (hc->ledcount > 4096) {
- hc->ledcount -= 4096;
- hc->ledstate = 0xAFFEAFFE;
- }
-
switch (hc->leds) {
case 1: /* HFC-E1 OEM */
- /* 2 red blinking: NT mode deactivate
- * 2 red steady: TE mode deactivate
- * left green: L1 active
- * left red: frame sync, but no L1
- * todo right green: L2 active
+ /* 2 red steady: LOS
+ * 1 red steady: L1 not active
+ * 2 green steady: L1 active
+ * 1st green flashing: activity on TX
+ * 2nd green flashing: activity on RX
*/
+ led[0] = 0;
+ led[1] = 0;
+ led[2] = 0;
+ led[3] = 0;
dch = hc->chan[hc->dslot].dch;
- if (test_bit(FLG_ACTIVE, &dch->Flags)) {
- led[0] = 0;
- led[1] = 0;
- led[2] = 0;
- led[3] = 1;
- } else {
- if (dch->dev.D.protocol
- != ISDN_P_NT_E1) {
- led[0] = 1;
+ if (dch) {
+ if (hc->chan[hc->dslot].los)
led[1] = 1;
- } else if (hc->ledcount >> 11) {
+ if (hc->e1_state != 1) {
led[0] = 1;
- led[1] = 1;
+ hc->flash[2] = 0;
+ hc->flash[3] = 0;
} else {
- led[0] = 0;
- led[1] = 0;
+ led[2] = 1;
+ led[3] = 1;
+ if (!hc->flash[2] && hc->activity_tx)
+ hc->flash[2] = poll;
+ if (!hc->flash[3] && hc->activity_rx)
+ hc->flash[3] = poll;
+ if (hc->flash[2] && hc->flash[2] < 1024)
+ led[2] = 0;
+ if (hc->flash[3] && hc->flash[3] < 1024)
+ led[3] = 0;
+ if (hc->flash[2] >= 2048)
+ hc->flash[2] = 0;
+ if (hc->flash[3] >= 2048)
+ hc->flash[3] = 0;
+ if (hc->flash[2])
+ hc->flash[2] += poll;
+ if (hc->flash[3])
+ hc->flash[3] += poll;
}
- led[2] = 0;
- led[3] = 0;
}
leds = (led[0] | (led[1]<<2) | (led[2]<<1) | (led[3]<<3))^0xF;
/* leds are inverted */
@@ -1651,9 +1657,9 @@ hfcmulti_leds(struct hfc_multi *hc)
break;
case 2: /* HFC-4S OEM */
- /* red blinking = PH_DEACTIVATE NT Mode
- * red steady = PH_DEACTIVATE TE Mode
- * green steady = PH_ACTIVATE
+ /* red steady: PH_DEACTIVATE
+ * green steady: PH_ACTIVATE
+ * green flashing: activity on TX
*/
for (i = 0; i < 4; i++) {
state = 0;
@@ -1669,17 +1675,20 @@ hfcmulti_leds(struct hfc_multi *hc)
if (state) {
if (state == active) {
led[i] = 1; /* led green */
- } else
- if (dch->dev.D.protocol == ISDN_P_TE_S0)
- /* TE mode: led red */
- led[i] = 2;
- else
- if (hc->ledcount >> 11)
- /* led red */
- led[i] = 2;
- else
- /* led off */
- led[i] = 0;
+ hc->activity_tx |= hc->activity_rx;
+ if (!hc->flash[i] &&
+ (hc->activity_tx & (1 << i)))
+ hc->flash[i] = poll;
+ if (hc->flash[i] && hc->flash[i] < 1024)
+ led[i] = 0; /* led off */
+ if (hc->flash[i] >= 2048)
+ hc->flash[i] = 0;
+ if (hc->flash[i])
+ hc->flash[i] += poll;
+ } else {
+ led[i] = 2; /* led red */
+ hc->flash[i] = 0;
+ }
} else
led[i] = 0; /* led off */
}
@@ -1712,9 +1721,9 @@ hfcmulti_leds(struct hfc_multi *hc)
break;
case 3: /* HFC 1S/2S Beronet */
- /* red blinking = PH_DEACTIVATE NT Mode
- * red steady = PH_DEACTIVATE TE Mode
- * green steady = PH_ACTIVATE
+ /* red steady: PH_DEACTIVATE
+ * green steady: PH_ACTIVATE
+ * green flashing: activity on TX
*/
for (i = 0; i < 2; i++) {
state = 0;
@@ -1730,22 +1739,23 @@ hfcmulti_leds(struct hfc_multi *hc)
if (state) {
if (state == active) {
led[i] = 1; /* led green */
- } else
- if (dch->dev.D.protocol == ISDN_P_TE_S0)
- /* TE mode: led red */
- led[i] = 2;
- else
- if (hc->ledcount >> 11)
- /* led red */
- led[i] = 2;
- else
- /* led off */
- led[i] = 0;
+ hc->activity_tx |= hc->activity_rx;
+ if (!hc->flash[i] &&
+ (hc->activity_tx & (1 << i)))
+ hc->flash[i] = poll;
+ if (hc->flash[i] < 1024)
+ led[i] = 0; /* led off */
+ if (hc->flash[i] >= 2048)
+ hc->flash[i] = 0;
+ if (hc->flash[i])
+ hc->flash[i] += poll;
+ } else {
+ led[i] = 2; /* led red */
+ hc->flash[i] = 0;
+ }
} else
led[i] = 0; /* led off */
}
-
-
leds = (led[0] > 0) | ((led[1] > 0) << 1) | ((led[0]&1) << 2)
| ((led[1]&1) << 3);
if (leds != (int)hc->ledstate) {
@@ -1757,8 +1767,11 @@ hfcmulti_leds(struct hfc_multi *hc)
}
break;
case 8: /* HFC 8S+ Beronet */
- lled = 0;
-
+ /* off: PH_DEACTIVATE
+ * steady: PH_ACTIVATE
+ * flashing: activity on TX
+ */
+ lled = 0xff; /* leds off */
for (i = 0; i < 8; i++) {
state = 0;
active = -1;
@@ -1772,14 +1785,20 @@ hfcmulti_leds(struct hfc_multi *hc)
}
if (state) {
if (state == active) {
- lled |= 0 << i;
+ lled &= ~(1 << i); /* led on */
+ hc->activity_tx |= hc->activity_rx;
+ if (!hc->flash[i] &&
+ (hc->activity_tx & (1 << i)))
+ hc->flash[i] = poll;
+ if (hc->flash[i] < 1024)
+ lled |= 1 << i; /* led off */
+ if (hc->flash[i] >= 2048)
+ hc->flash[i] = 0;
+ if (hc->flash[i])
+ hc->flash[i] += poll;
} else
- if (hc->ledcount >> 11)
- lled |= 0 << i;
- else
- lled |= 1 << i;
- } else
- lled |= 1 << i;
+ hc->flash[i] = 0;
+ }
}
leddw = lled << 24 | lled << 16 | lled << 8 | lled;
if (leddw != hc->ledstate) {
@@ -1794,6 +1813,8 @@ hfcmulti_leds(struct hfc_multi *hc)
}
break;
}
+ hc->activity_tx = 0;
+ hc->activity_rx = 0;
}
/*
* read dtmf coefficients
@@ -2093,7 +2114,8 @@ next_frame:
*txpending = 1;
/* show activity */
- hc->activity[hc->chan[ch].port] = 1;
+ if (dch)
+ hc->activity_tx |= 1 << hc->chan[ch].port;
/* fill fifo to what we have left */
ii = len;
@@ -2236,7 +2258,8 @@ next_frame:
}
}
/* show activity */
- hc->activity[hc->chan[ch].port] = 1;
+ if (dch)
+ hc->activity_rx |= 1 << hc->chan[ch].port;
/* empty fifo with what we have */
if (dch || test_bit(FLG_HDLC, &bch->Flags)) {
--
1.7.3.4
^ permalink raw reply related
* [PATCH 4/4] mISDN: Added support for fragmentation of E1 interfaces of hfcmulti driver.
From: Karsten Keil @ 2012-04-25 6:52 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Andreas Eversberg
In-Reply-To: <1335336734-25181-1-git-send-email-kkeil@linux-pingi.de>
From: Andreas Eversberg <jolly@eversberg.eu>
Fragmentation is usefull if multiple devices are connected to an E1
interface. Each fragment will have a subset of the available timeslots.
These devices require a cascde connection or a multiplexer.
Signed-off-by: Andreas Eversberg <jolly@eversberg.eu>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
---
drivers/isdn/hardware/mISDN/hfc_multi.h | 6 +-
drivers/isdn/hardware/mISDN/hfcmulti.c | 396 ++++++++++++++++++-------------
2 files changed, 236 insertions(+), 166 deletions(-)
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h
index 09e4e77..c601f88 100644
--- a/drivers/isdn/hardware/mISDN/hfc_multi.h
+++ b/drivers/isdn/hardware/mISDN/hfc_multi.h
@@ -208,7 +208,10 @@ struct hfc_multi {
u_long ledstate; /* save last state of leds */
int opticalsupport; /* has the e1 board */
/* an optical Interface */
- int dslot; /* channel # of d-channel (E1) default 16 */
+
+ u_int bmask[32]; /* bitmask of bchannels for port */
+ u_char dnum[32]; /* array of used dchannel numbers for port */
+ u_char created[32]; /* what port is created */
u_int activity_tx; /* if there is data TX / RX */
u_int activity_rx; /* bitmask according to port number */
/* (will be cleared after */
@@ -234,7 +237,6 @@ struct hfc_multi {
* the bch->channel is equvalent to the hfc-channel
*/
struct hfc_chan chan[32];
- u_char created[8]; /* what port is created */
signed char slot_owner[256]; /* owner channel of slot */
};
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index 876f7d0..4301331 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -103,14 +103,26 @@
* Omit this value, if all cards are interconnected or none is connected.
* If unsure, don't give this parameter.
*
- * dslot:
- * NOTE: only one dslot value must be given for every card.
- * Also this value must be given for non-E1 cards. If omitted, the E1
- * card has D-channel on time slot 16, which is default.
- * If 1..15 or 17..31, an alternate time slot is used for D-channel.
- * In this case, the application must be able to handle this.
- * If -1 is given, the D-channel is disabled and all 31 slots can be used
- * for B-channel. (only for specific applications)
+ * dmask and bmask:
+ * NOTE: One dmask value must be given for every HFC-E1 card.
+ * If omitted, the E1 card has D-channel on time slot 16, which is default.
+ * dmask is a 32 bit mask. The bit must be set for an alternate time slot.
+ * If multiple bits are set, multiple virtual card fragments are created.
+ * For each bit set, a bmask value must be given. Each bit on the bmask
+ * value stands for a B-channel. The bmask may not overlap with dmask or
+ * with other bmask values for that card.
+ * Example: dmask=0x00020002 bmask=0x0000fffc,0xfffc0000
+ * This will create one fragment with D-channel on slot 1 with
+ * B-channels on slots 2..15, and a second fragment with D-channel
+ * on slot 17 with B-channels on slot 18..31. Slot 16 is unused.
+ * If bit 0 is set (dmask=0x00000001) the D-channel is on slot 0 and will
+ * not function.
+ * Example: dmask=0x00000001 bmask=0xfffffffe
+ * This will create a port with all 31 usable timeslots as
+ * B-channels.
+ * If no bits are set on bmask, no B-channel is created for that fragment.
+ * Example: dmask=0xfffffffe bmask=0,0,0,0.... (31 0-values for bmask)
+ * This will create 31 ports with one D-channel only.
* If you don't know how to use it, you don't need it!
*
* iomode:
@@ -172,6 +184,7 @@
#define MAX_CARDS 8
#define MAX_PORTS (8 * MAX_CARDS)
+#define MAX_FRAGS (32 * MAX_CARDS)
static LIST_HEAD(HFClist);
static spinlock_t HFClock; /* global hfc list lock */
@@ -203,7 +216,8 @@ static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 60, 30 };
static uint type[MAX_CARDS];
static int pcm[MAX_CARDS];
-static int dslot[MAX_CARDS];
+static uint dmask[MAX_CARDS];
+static uint bmask[MAX_FRAGS];
static uint iomode[MAX_CARDS];
static uint port[MAX_PORTS];
static uint debug;
@@ -218,7 +232,7 @@ static uint clockdelay_nt = CLKDEL_NT;
#define HWID_MINIP16 3
static uint hwid = HWID_NONE;
-static int HFC_cnt, Port_cnt, PCM_cnt = 99;
+static int HFC_cnt, E1_cnt, bmask_cnt, Port_cnt, PCM_cnt = 99;
MODULE_AUTHOR("Andreas Eversberg");
MODULE_LICENSE("GPL");
@@ -231,7 +245,8 @@ module_param(clockdelay_te, uint, S_IRUGO | S_IWUSR);
module_param(clockdelay_nt, uint, S_IRUGO | S_IWUSR);
module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(pcm, int, NULL, S_IRUGO | S_IWUSR);
-module_param_array(dslot, int, NULL, S_IRUGO | S_IWUSR);
+module_param_array(dmask, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(bmask, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(iomode, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR);
module_param(hwid, uint, S_IRUGO | S_IWUSR); /* The hardware ID */
@@ -1619,9 +1634,9 @@ hfcmulti_leds(struct hfc_multi *hc)
led[1] = 0;
led[2] = 0;
led[3] = 0;
- dch = hc->chan[hc->dslot].dch;
+ dch = hc->chan[hc->dnum[0]].dch;
if (dch) {
- if (hc->chan[hc->dslot].los)
+ if (hc->chan[hc->dnum[0]].los)
led[1] = 1;
if (hc->e1_state != 1) {
led[0] = 1;
@@ -2453,55 +2468,55 @@ handle_timer_irq(struct hfc_multi *hc)
}
}
if (hc->ctype == HFC_TYPE_E1 && hc->created[0]) {
- dch = hc->chan[hc->dslot].dch;
- if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) {
- /* LOS */
- temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_SIG_LOS;
- if (!temp && hc->chan[hc->dslot].los)
+ dch = hc->chan[hc->dnum[0]].dch;
+ /* LOS */
+ temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_SIG_LOS;
+ hc->chan[hc->dnum[0]].los = temp;
+ if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dnum[0]].cfg)) {
+ if (!temp && hc->chan[hc->dnum[0]].los)
signal_state_up(dch, L1_SIGNAL_LOS_ON,
"LOS detected");
- if (temp && !hc->chan[hc->dslot].los)
+ if (temp && !hc->chan[hc->dnum[0]].los)
signal_state_up(dch, L1_SIGNAL_LOS_OFF,
"LOS gone");
- hc->chan[hc->dslot].los = temp;
}
- if (test_bit(HFC_CFG_REPORT_AIS, &hc->chan[hc->dslot].cfg)) {
+ if (test_bit(HFC_CFG_REPORT_AIS, &hc->chan[hc->dnum[0]].cfg)) {
/* AIS */
temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_AIS;
- if (!temp && hc->chan[hc->dslot].ais)
+ if (!temp && hc->chan[hc->dnum[0]].ais)
signal_state_up(dch, L1_SIGNAL_AIS_ON,
"AIS detected");
- if (temp && !hc->chan[hc->dslot].ais)
+ if (temp && !hc->chan[hc->dnum[0]].ais)
signal_state_up(dch, L1_SIGNAL_AIS_OFF,
"AIS gone");
- hc->chan[hc->dslot].ais = temp;
+ hc->chan[hc->dnum[0]].ais = temp;
}
- if (test_bit(HFC_CFG_REPORT_SLIP, &hc->chan[hc->dslot].cfg)) {
+ if (test_bit(HFC_CFG_REPORT_SLIP, &hc->chan[hc->dnum[0]].cfg)) {
/* SLIP */
temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_RX;
- if (!temp && hc->chan[hc->dslot].slip_rx)
+ if (!temp && hc->chan[hc->dnum[0]].slip_rx)
signal_state_up(dch, L1_SIGNAL_SLIP_RX,
" bit SLIP detected RX");
- hc->chan[hc->dslot].slip_rx = temp;
+ hc->chan[hc->dnum[0]].slip_rx = temp;
temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_TX;
- if (!temp && hc->chan[hc->dslot].slip_tx)
+ if (!temp && hc->chan[hc->dnum[0]].slip_tx)
signal_state_up(dch, L1_SIGNAL_SLIP_TX,
" bit SLIP detected TX");
- hc->chan[hc->dslot].slip_tx = temp;
+ hc->chan[hc->dnum[0]].slip_tx = temp;
}
- if (test_bit(HFC_CFG_REPORT_RDI, &hc->chan[hc->dslot].cfg)) {
+ if (test_bit(HFC_CFG_REPORT_RDI, &hc->chan[hc->dnum[0]].cfg)) {
/* RDI */
temp = HFC_inb_nodebug(hc, R_RX_SL0_0) & V_A;
- if (!temp && hc->chan[hc->dslot].rdi)
+ if (!temp && hc->chan[hc->dnum[0]].rdi)
signal_state_up(dch, L1_SIGNAL_RDI_ON,
"RDI detected");
- if (temp && !hc->chan[hc->dslot].rdi)
+ if (temp && !hc->chan[hc->dnum[0]].rdi)
signal_state_up(dch, L1_SIGNAL_RDI_OFF,
"RDI gone");
- hc->chan[hc->dslot].rdi = temp;
+ hc->chan[hc->dnum[0]].rdi = temp;
}
temp = HFC_inb_nodebug(hc, R_JATT_DIR);
- switch (hc->chan[hc->dslot].sync) {
+ switch (hc->chan[hc->dnum[0]].sync) {
case 0:
if ((temp & 0x60) == 0x60) {
if (debug & DEBUG_HFCMULTI_SYNC)
@@ -2510,10 +2525,10 @@ handle_timer_irq(struct hfc_multi *hc)
"in clock sync\n",
__func__, hc->id);
HFC_outb(hc, R_RX_OFF,
- hc->chan[hc->dslot].jitter | V_RX_INIT);
+ hc->chan[hc->dnum[0]].jitter | V_RX_INIT);
HFC_outb(hc, R_TX_OFF,
- hc->chan[hc->dslot].jitter | V_RX_INIT);
- hc->chan[hc->dslot].sync = 1;
+ hc->chan[hc->dnum[0]].jitter | V_RX_INIT);
+ hc->chan[hc->dnum[0]].sync = 1;
goto check_framesync;
}
break;
@@ -2524,7 +2539,7 @@ handle_timer_irq(struct hfc_multi *hc)
"%s: (id=%d) E1 "
"lost clock sync\n",
__func__, hc->id);
- hc->chan[hc->dslot].sync = 0;
+ hc->chan[hc->dnum[0]].sync = 0;
break;
}
check_framesync:
@@ -2535,7 +2550,7 @@ handle_timer_irq(struct hfc_multi *hc)
"%s: (id=%d) E1 "
"now in frame sync\n",
__func__, hc->id);
- hc->chan[hc->dslot].sync = 2;
+ hc->chan[hc->dnum[0]].sync = 2;
}
break;
case 2:
@@ -2545,7 +2560,7 @@ handle_timer_irq(struct hfc_multi *hc)
"%s: (id=%d) E1 lost "
"clock & frame sync\n",
__func__, hc->id);
- hc->chan[hc->dslot].sync = 0;
+ hc->chan[hc->dnum[0]].sync = 0;
break;
}
temp = HFC_inb_nodebug(hc, R_SYNC_STA);
@@ -2555,7 +2570,7 @@ handle_timer_irq(struct hfc_multi *hc)
"%s: (id=%d) E1 "
"lost frame sync\n",
__func__, hc->id);
- hc->chan[hc->dslot].sync = 1;
+ hc->chan[hc->dnum[0]].sync = 1;
}
break;
}
@@ -2696,7 +2711,7 @@ hfcmulti_interrupt(int intno, void *dev_id)
int i;
void __iomem *plx_acc;
u_short wval;
- u_char e1_syncsta, temp;
+ u_char e1_syncsta, temp, temp2;
u_long flags;
if (!hc) {
@@ -2771,7 +2786,7 @@ hfcmulti_interrupt(int intno, void *dev_id)
if (r_irq_misc & V_STA_IRQ) {
if (hc->ctype == HFC_TYPE_E1) {
/* state machine */
- dch = hc->chan[hc->dslot].dch;
+ dch = hc->chan[hc->dnum[0]].dch;
e1_syncsta = HFC_inb_nodebug(hc, R_SYNC_STA);
if (test_bit(HFC_CHIP_PLXSD, &hc->chip)
&& hc->e1_getclock) {
@@ -2781,23 +2796,26 @@ hfcmulti_interrupt(int intno, void *dev_id)
hc->syncronized = 0;
}
/* undocumented: status changes during read */
- dch->state = HFC_inb_nodebug(hc, R_E1_RD_STA);
- while (dch->state != (temp =
+ temp = HFC_inb_nodebug(hc, R_E1_RD_STA);
+ while (temp != (temp2 =
HFC_inb_nodebug(hc, R_E1_RD_STA))) {
if (debug & DEBUG_HFCMULTI_STATE)
printk(KERN_DEBUG "%s: reread "
"STATE because %d!=%d\n",
- __func__, temp,
- dch->state);
- dch->state = temp; /* repeat */
+ __func__, temp, temp2);
+ temp = temp2; /* repeat */
}
- dch->state = HFC_inb_nodebug(hc, R_E1_RD_STA)
- & 0x7;
- schedule_event(dch, FLG_PHCHANGE);
+ /* broadcast state change to all fragments */
if (debug & DEBUG_HFCMULTI_STATE)
printk(KERN_DEBUG
"%s: E1 (id=%d) newstate %x\n",
- __func__, hc->id, dch->state);
+ __func__, hc->id, temp & 0x7);
+ for (i = 0; i < hc->ports; i++) {
+ dch = hc->chan[hc->dnum[i]].dch;
+ dch->state = temp & 0x7;
+ schedule_event(dch, FLG_PHCHANGE);
+ }
+
if (test_bit(HFC_CHIP_PLXSD, &hc->chip))
plxsd_checksync(hc, 0);
}
@@ -3870,31 +3888,37 @@ hfcmulti_initmode(struct dchannel *dch)
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: entered\n", __func__);
+ i = dch->slot;
+ pt = hc->chan[i].port;
if (hc->ctype == HFC_TYPE_E1) {
- hc->chan[hc->dslot].slot_tx = -1;
- hc->chan[hc->dslot].slot_rx = -1;
- hc->chan[hc->dslot].conf = -1;
- if (hc->dslot) {
- mode_hfcmulti(hc, hc->dslot, dch->dev.D.protocol,
+ /* E1 */
+ hc->chan[hc->dnum[pt]].slot_tx = -1;
+ hc->chan[hc->dnum[pt]].slot_rx = -1;
+ hc->chan[hc->dnum[pt]].conf = -1;
+ if (hc->dnum[pt]) {
+ mode_hfcmulti(hc, dch->slot, dch->dev.D.protocol,
-1, 0, -1, 0);
dch->timer.function = (void *) hfcmulti_dbusy_timer;
dch->timer.data = (long) dch;
init_timer(&dch->timer);
}
for (i = 1; i <= 31; i++) {
- if (i == hc->dslot)
+ if (!((1 << i) & hc->bmask[pt])) /* skip unused chan */
continue;
hc->chan[i].slot_tx = -1;
hc->chan[i].slot_rx = -1;
hc->chan[i].conf = -1;
mode_hfcmulti(hc, i, ISDN_P_NONE, -1, 0, -1, 0);
}
- /* E1 */
- if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) {
+ }
+ if (hc->ctype == HFC_TYPE_E1 && pt == 0) {
+ /* E1, port 0 */
+ dch = hc->chan[hc->dnum[0]].dch;
+ if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dnum[0]].cfg)) {
HFC_outb(hc, R_LOS0, 255); /* 2 ms */
HFC_outb(hc, R_LOS1, 255); /* 512 ms */
}
- if (test_bit(HFC_CFG_OPTICAL, &hc->chan[hc->dslot].cfg)) {
+ if (test_bit(HFC_CFG_OPTICAL, &hc->chan[hc->dnum[0]].cfg)) {
HFC_outb(hc, R_RX0, 0);
hc->hw.r_tx0 = 0 | V_OUT_EN;
} else {
@@ -3907,12 +3931,12 @@ hfcmulti_initmode(struct dchannel *dch)
HFC_outb(hc, R_TX_FR0, 0x00);
HFC_outb(hc, R_TX_FR1, 0xf8);
- if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dslot].cfg))
+ if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dnum[0]].cfg))
HFC_outb(hc, R_TX_FR2, V_TX_MF | V_TX_E | V_NEG_E);
HFC_outb(hc, R_RX_FR0, V_AUTO_RESYNC | V_AUTO_RECO | 0);
- if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dslot].cfg))
+ if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dnum[0]].cfg))
HFC_outb(hc, R_RX_FR1, V_RX_MF | V_RX_MF_SYNC);
if (dch->dev.D.protocol == ISDN_P_NT_E1) {
@@ -3975,13 +3999,14 @@ hfcmulti_initmode(struct dchannel *dch)
hc->syncronized = 0;
plxsd_checksync(hc, 0);
}
- } else {
- i = dch->slot;
+ }
+ if (hc->ctype != HFC_TYPE_E1) {
+ /* ST */
hc->chan[i].slot_tx = -1;
hc->chan[i].slot_rx = -1;
hc->chan[i].conf = -1;
mode_hfcmulti(hc, i, dch->dev.D.protocol, -1, 0, -1, 0);
- dch->timer.function = (void *)hfcmulti_dbusy_timer;
+ dch->timer.function = (void *) hfcmulti_dbusy_timer;
dch->timer.data = (long) dch;
init_timer(&dch->timer);
hc->chan[i - 2].slot_tx = -1;
@@ -3992,8 +4017,6 @@ hfcmulti_initmode(struct dchannel *dch)
hc->chan[i - 1].slot_rx = -1;
hc->chan[i - 1].conf = -1;
mode_hfcmulti(hc, i - 1, ISDN_P_NONE, -1, 0, -1, 0);
- /* ST */
- pt = hc->chan[i].port;
/* select interface */
HFC_outb(hc, R_ST_SEL, pt);
/* undocumented: delay after R_ST_SEL */
@@ -4571,6 +4594,8 @@ release_port(struct hfc_multi *hc, struct dchannel *dch)
}
/* free channels */
for (i = 0; i <= 31; i++) {
+ if (!((1 << i) & hc->bmask[pt])) /* skip unused chan */
+ continue;
if (hc->chan[i].bch) {
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG
@@ -4626,7 +4651,8 @@ release_port(struct hfc_multi *hc, struct dchannel *dch)
spin_unlock_irqrestore(&hc->lock, flags);
if (debug & DEBUG_HFCMULTI_INIT)
- printk(KERN_DEBUG "%s: free port %d channel D\n", __func__, pt);
+ printk(KERN_DEBUG "%s: free port %d channel D(%d)\n", __func__,
+ pt+1, ci);
mISDN_freedchannel(dch);
kfree(dch);
@@ -4648,15 +4674,19 @@ release_card(struct hfc_multi *hc)
if (hc->iclock)
mISDN_unregister_clock(hc->iclock);
- /* disable irq */
+ /* disable and free irq */
spin_lock_irqsave(&hc->lock, flags);
disable_hwirq(hc);
spin_unlock_irqrestore(&hc->lock, flags);
udelay(1000);
+ if (hc->irq) {
+ if (debug & DEBUG_HFCMULTI_INIT)
+ printk(KERN_DEBUG "%s: free irq %d (hc=%p)\n",
+ __func__, hc->irq, hc);
+ free_irq(hc->irq, hc);
+ hc->irq = 0;
- /* dimm leds */
- if (hc->leds)
- hfcmulti_leds(hc);
+ }
/* disable D-channels & B-channels */
if (debug & DEBUG_HFCMULTI_INIT)
@@ -4667,15 +4697,11 @@ release_card(struct hfc_multi *hc)
release_port(hc, hc->chan[ch].dch);
}
- /* release hardware & irq */
- if (hc->irq) {
- if (debug & DEBUG_HFCMULTI_INIT)
- printk(KERN_DEBUG "%s: free irq %d\n",
- __func__, hc->irq);
- free_irq(hc->irq, hc);
- hc->irq = 0;
+ /* dimm leds */
+ if (hc->leds)
+ hfcmulti_leds(hc);
- }
+ /* release hardware */
release_io_hfcmulti(hc);
if (debug & DEBUG_HFCMULTI_INIT)
@@ -4693,61 +4719,9 @@ release_card(struct hfc_multi *hc)
__func__);
}
-static int
-init_e1_port(struct hfc_multi *hc, struct hm_map *m)
+static void
+init_e1_port_hw(struct hfc_multi *hc, struct hm_map *m)
{
- struct dchannel *dch;
- struct bchannel *bch;
- int ch, ret = 0;
- char name[MISDN_MAX_IDLEN];
-
- dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL);
- if (!dch)
- return -ENOMEM;
- dch->debug = debug;
- mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, ph_state_change);
- dch->hw = hc;
- dch->dev.Dprotocols = (1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1);
- dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
- (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
- dch->dev.D.send = handle_dmsg;
- dch->dev.D.ctrl = hfcm_dctrl;
- dch->dev.nrbchan = (hc->dslot) ? 30 : 31;
- dch->slot = hc->dslot;
- hc->chan[hc->dslot].dch = dch;
- hc->chan[hc->dslot].port = 0;
- hc->chan[hc->dslot].nt_timer = -1;
- for (ch = 1; ch <= 31; ch++) {
- if (ch == hc->dslot) /* skip dchannel */
- continue;
- bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL);
- if (!bch) {
- printk(KERN_ERR "%s: no memory for bchannel\n",
- __func__);
- ret = -ENOMEM;
- goto free_chan;
- }
- hc->chan[ch].coeff = kzalloc(512, GFP_KERNEL);
- if (!hc->chan[ch].coeff) {
- printk(KERN_ERR "%s: no memory for coeffs\n",
- __func__);
- ret = -ENOMEM;
- kfree(bch);
- goto free_chan;
- }
- bch->nr = ch;
- bch->slot = ch;
- bch->debug = debug;
- mISDN_initbchannel(bch, MAX_DATA_MEM);
- bch->hw = hc;
- bch->ch.send = handle_bmsg;
- bch->ch.ctrl = hfcm_bctrl;
- bch->ch.nr = ch;
- list_add(&bch->ch.list, &dch->dev.bchannels);
- hc->chan[ch].bch = bch;
- hc->chan[ch].port = 0;
- set_channelmap(bch->nr, dch->dev.channelmap);
- }
/* set optical line type */
if (port[Port_cnt] & 0x001) {
if (!m->opticalsupport) {
@@ -4763,7 +4737,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
__func__,
HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_OPTICAL,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
}
}
/* set LOS report */
@@ -4773,7 +4747,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
"LOS report: card(%d) port(%d)\n",
__func__, HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_REPORT_LOS,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
}
/* set AIS report */
if (port[Port_cnt] & 0x008) {
@@ -4782,7 +4756,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
"AIS report: card(%d) port(%d)\n",
__func__, HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_REPORT_AIS,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
}
/* set SLIP report */
if (port[Port_cnt] & 0x010) {
@@ -4792,7 +4766,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
"card(%d) port(%d)\n",
__func__, HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_REPORT_SLIP,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
}
/* set RDI report */
if (port[Port_cnt] & 0x020) {
@@ -4802,7 +4776,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
"card(%d) port(%d)\n",
__func__, HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_REPORT_RDI,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
}
/* set CRC-4 Mode */
if (!(port[Port_cnt] & 0x100)) {
@@ -4811,7 +4785,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
" card(%d) port(%d)\n",
__func__, HFC_cnt + 1, 1);
test_and_set_bit(HFC_CFG_CRC4,
- &hc->chan[hc->dslot].cfg);
+ &hc->chan[hc->dnum[0]].cfg);
} else {
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: PORT turn off CRC4"
@@ -4843,20 +4817,85 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
}
/* set elastic jitter buffer */
if (port[Port_cnt] & 0x3000) {
- hc->chan[hc->dslot].jitter = (port[Port_cnt]>>12) & 0x3;
+ hc->chan[hc->dnum[0]].jitter = (port[Port_cnt]>>12) & 0x3;
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG
"%s: PORT set elastic "
"buffer to %d: card(%d) port(%d)\n",
- __func__, hc->chan[hc->dslot].jitter,
+ __func__, hc->chan[hc->dnum[0]].jitter,
HFC_cnt + 1, 1);
} else
- hc->chan[hc->dslot].jitter = 2; /* default */
- snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1);
+ hc->chan[hc->dnum[0]].jitter = 2; /* default */
+}
+
+static int
+init_e1_port(struct hfc_multi *hc, struct hm_map *m, int pt)
+{
+ struct dchannel *dch;
+ struct bchannel *bch;
+ int ch, ret = 0;
+ char name[MISDN_MAX_IDLEN];
+ int bcount = 0;
+
+ dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL);
+ if (!dch)
+ return -ENOMEM;
+ dch->debug = debug;
+ mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, ph_state_change);
+ dch->hw = hc;
+ dch->dev.Dprotocols = (1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1);
+ dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+ (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
+ dch->dev.D.send = handle_dmsg;
+ dch->dev.D.ctrl = hfcm_dctrl;
+ dch->slot = hc->dnum[pt];
+ hc->chan[hc->dnum[pt]].dch = dch;
+ hc->chan[hc->dnum[pt]].port = pt;
+ hc->chan[hc->dnum[pt]].nt_timer = -1;
+ for (ch = 1; ch <= 31; ch++) {
+ if (!((1 << ch) & hc->bmask[pt])) /* skip unused channel */
+ continue;
+ bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL);
+ if (!bch) {
+ printk(KERN_ERR "%s: no memory for bchannel\n",
+ __func__);
+ ret = -ENOMEM;
+ goto free_chan;
+ }
+ hc->chan[ch].coeff = kzalloc(512, GFP_KERNEL);
+ if (!hc->chan[ch].coeff) {
+ printk(KERN_ERR "%s: no memory for coeffs\n",
+ __func__);
+ ret = -ENOMEM;
+ kfree(bch);
+ goto free_chan;
+ }
+ bch->nr = ch;
+ bch->slot = ch;
+ bch->debug = debug;
+ mISDN_initbchannel(bch, MAX_DATA_MEM);
+ bch->hw = hc;
+ bch->ch.send = handle_bmsg;
+ bch->ch.ctrl = hfcm_bctrl;
+ bch->ch.nr = ch;
+ list_add(&bch->ch.list, &dch->dev.bchannels);
+ hc->chan[ch].bch = bch;
+ hc->chan[ch].port = pt;
+ set_channelmap(bch->nr, dch->dev.channelmap);
+ bcount++;
+ }
+ dch->dev.nrbchan = bcount;
+ if (pt == 0)
+ init_e1_port_hw(hc, m);
+ if (hc->ports > 1)
+ snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d-%d",
+ HFC_cnt + 1, pt+1);
+ else
+ snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1);
ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name);
if (ret)
goto free_chan;
- hc->created[0] = 1;
+ hc->created[pt] = 1;
return ret;
free_chan:
release_port(hc, dch);
@@ -4989,7 +5028,8 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,
struct hfc_multi *hc;
u_long flags;
u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */
- int i;
+ int i, ch;
+ u_int maskcheck;
if (HFC_cnt >= MAX_CARDS) {
printk(KERN_ERR "too many cards (max=%d).\n",
@@ -5023,18 +5063,36 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,
hc->id = HFC_cnt;
hc->pcm = pcm[HFC_cnt];
hc->io_mode = iomode[HFC_cnt];
- if (dslot[HFC_cnt] < 0 && hc->ctype == HFC_TYPE_E1) {
- hc->dslot = 0;
- printk(KERN_INFO "HFC-E1 card has disabled D-channel, but "
- "31 B-channels\n");
- }
- if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32
- && hc->ctype == HFC_TYPE_E1) {
- hc->dslot = dslot[HFC_cnt];
- printk(KERN_INFO "HFC-E1 card has alternating D-channel on "
- "time slot %d\n", dslot[HFC_cnt]);
- } else
- hc->dslot = 16;
+ if (hc->ctype == HFC_TYPE_E1 && dmask[E1_cnt]) {
+ /* fragment card */
+ pt = 0;
+ maskcheck = 0;
+ for (ch = 0; ch <= 31; ch++) {
+ if (!((1 << ch) & dmask[E1_cnt]))
+ continue;
+ hc->dnum[pt] = ch;
+ hc->bmask[pt] = bmask[bmask_cnt++];
+ if ((maskcheck & hc->bmask[pt])
+ || (dmask[E1_cnt] & hc->bmask[pt])) {
+ printk(KERN_INFO
+ "HFC-E1 #%d has overlapping B-channels on fragment #%d\n",
+ E1_cnt + 1, pt);
+ return -EINVAL;
+ }
+ maskcheck |= hc->bmask[pt];
+ printk(KERN_INFO
+ "HFC-E1 #%d uses D-channel on slot %d and a B-channel map of 0x%08x\n",
+ E1_cnt + 1, ch, hc->bmask[pt]);
+ pt++;
+ }
+ hc->ports = pt;
+ }
+ if (hc->ctype == HFC_TYPE_E1 && !dmask[E1_cnt]) {
+ /* default card layout */
+ hc->dnum[0] = 16;
+ hc->bmask[0] = 0xfffefffe;
+ hc->ports = 1;
+ }
/* set chip specific features */
hc->masterclk = -1;
@@ -5117,23 +5175,33 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,
goto free_card;
}
if (hc->ctype == HFC_TYPE_E1)
- ret_err = init_e1_port(hc, m);
+ ret_err = init_e1_port(hc, m, pt);
else
ret_err = init_multi_port(hc, pt);
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG
- "%s: Registering D-channel, card(%d) port(%d)"
+ "%s: Registering D-channel, card(%d) port(%d) "
"result %d\n",
- __func__, HFC_cnt + 1, pt, ret_err);
+ __func__, HFC_cnt + 1, pt + 1, ret_err);
if (ret_err) {
while (pt) { /* release already registered ports */
pt--;
- release_port(hc, hc->chan[(pt << 2) + 2].dch);
+ if (hc->ctype == HFC_TYPE_E1)
+ release_port(hc,
+ hc->chan[hc->dnum[pt]].dch);
+ else
+ release_port(hc,
+ hc->chan[(pt << 2) + 2].dch);
}
goto free_card;
}
- Port_cnt++;
+ if (hc->ctype != HFC_TYPE_E1)
+ Port_cnt++; /* for each S0 port */
+ }
+ if (hc->ctype == HFC_TYPE_E1) {
+ Port_cnt++; /* for each E1 port */
+ E1_cnt++;
}
/* disp switches */
--
1.7.3.4
^ permalink raw reply related
* [PATCH 0/4] mISDN Fix and enhancements for the HFC 4S/8S/E1 driver
From: Karsten Keil @ 2012-04-25 6:52 UTC (permalink / raw)
To: David Miller; +Cc: netdev
For net-next.
Patchset contains fixes for issues fond in long time testing.
The LED support now works as proposed by the card documentation.
For special cases you can now split a E1 line into independ logical
instances.
Andreas Eversberg (4):
mISDN: Fixed false interruption of audio during bridging change.
mISDN: Using FLG_ACTIVE flag to determine if layer 1 is active or
not.
mISDN: Rework of LED status display for HFC-4S/8S/E1 cards.
mISDN: Added support for fragmentation of E1 interfaces of hfcmulti
driver.
drivers/isdn/hardware/mISDN/hfc_multi.h | 15 +-
drivers/isdn/hardware/mISDN/hfcmulti.c | 582 ++++++++++++++++++-------------
2 files changed, 347 insertions(+), 250 deletions(-)
--
1.7.3.4
^ permalink raw reply
* [net 2/2] e1000e: Fix default interrupt throttle rate not set in NIC HW
From: Jeff Kirsher @ 2012-04-25 5:55 UTC (permalink / raw)
To: davem
Cc: Jeff Kirsher, netdev, gospo, sassmann, Ying Cai, David Decotigny,
Jeff Kirsher
In-Reply-To: <1335333314-6814-1-git-send-email-jeffrey.t.kirsher@intel.com>
Based on the original patch from Ying Cai <ycai@google.com>
This change ensures that the itr/itr_setting adjustment logic is used,
even for the default/compiled-in value.
Context:
When we changed the default InterruptThrottleRate value from default
(3 = dynamic mode) to 8000 for example, only adapter->itr_setting
(which controls interrupt coalescing mode) was set to 8000, but
adapter->itr (which controls the value set in NIC register) was not
updated accordingly. So from ethtool, it seemed the interrupt
throttling is enabled at 8000 intr/s, but the NIC actually was
running in dynamic mode which has lower CPU efficiency especially
when throughput is not high.
CC: Ying Cai <ycai@google.com>
CC: David Decotigny <david.decotigny@google.com>
Signed-off-by: Jeff Kirsher <jeffrey.kirsher@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
---
drivers/net/ethernet/intel/e1000e/param.c | 99 +++++++++++++++-------------
1 files changed, 53 insertions(+), 46 deletions(-)
diff --git a/drivers/net/ethernet/intel/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c
index ff796e4..16adeb9 100644
--- a/drivers/net/ethernet/intel/e1000e/param.c
+++ b/drivers/net/ethernet/intel/e1000e/param.c
@@ -106,7 +106,7 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
/*
* Interrupt Throttle Rate (interrupts/sec)
*
- * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
+ * Valid Range: 100-100000 or one of: 0=off, 1=dynamic, 3=dynamic conservative
*/
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
#define DEFAULT_ITR 3
@@ -344,53 +344,60 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
if (num_InterruptThrottleRate > bd) {
adapter->itr = InterruptThrottleRate[bd];
- switch (adapter->itr) {
- case 0:
- e_info("%s turned off\n", opt.name);
- break;
- case 1:
- e_info("%s set to dynamic mode\n", opt.name);
- adapter->itr_setting = adapter->itr;
- adapter->itr = 20000;
- break;
- case 3:
- e_info("%s set to dynamic conservative mode\n",
- opt.name);
- adapter->itr_setting = adapter->itr;
- adapter->itr = 20000;
- break;
- case 4:
- e_info("%s set to simplified (2000-8000 ints) "
- "mode\n", opt.name);
- adapter->itr_setting = 4;
- break;
- default:
- /*
- * Save the setting, because the dynamic bits
- * change itr.
- */
- if (e1000_validate_option(&adapter->itr, &opt,
- adapter) &&
- (adapter->itr == 3)) {
- /*
- * In case of invalid user value,
- * default to conservative mode.
- */
- adapter->itr_setting = adapter->itr;
- adapter->itr = 20000;
- } else {
- /*
- * Clear the lower two bits because
- * they are used as control.
- */
- adapter->itr_setting =
- adapter->itr & ~3;
- }
- break;
- }
+
+ /*
+ * Make sure a message is printed for non-special
+ * values. And in case of an invalid option, display
+ * warning, use default and got through itr/itr_setting
+ * adjustment logic below
+ */
+ if ((adapter->itr > 4) &&
+ e1000_validate_option(&adapter->itr, &opt, adapter))
+ adapter->itr = opt.def;
} else {
- adapter->itr_setting = opt.def;
+ /*
+ * If no option specified, use default value and go
+ * through the logic below to adjust itr/itr_setting
+ */
+ adapter->itr = opt.def;
+
+ /*
+ * Make sure a message is printed for non-special
+ * default values
+ */
+ if (adapter->itr > 40)
+ e_info("%s set to default %d\n", opt.name,
+ adapter->itr);
+ }
+
+ adapter->itr_setting = adapter->itr;
+ switch (adapter->itr) {
+ case 0:
+ e_info("%s turned off\n", opt.name);
+ break;
+ case 1:
+ e_info("%s set to dynamic mode\n", opt.name);
+ adapter->itr = 20000;
+ break;
+ case 3:
+ e_info("%s set to dynamic conservative mode\n",
+ opt.name);
adapter->itr = 20000;
+ break;
+ case 4:
+ e_info("%s set to simplified (2000-8000 ints) mode\n",
+ opt.name);
+ break;
+ default:
+ /*
+ * Save the setting, because the dynamic bits
+ * change itr.
+ *
+ * Clear the lower two bits because
+ * they are used as control.
+ */
+ adapter->itr_setting &= ~3;
+ break;
}
}
{ /* Interrupt Mode */
--
1.7.7.6
^ permalink raw reply related
* [net 1/2] e1000e: MSI interrupt test failed, using legacy interrupt
From: Jeff Kirsher @ 2012-04-25 5:55 UTC (permalink / raw)
To: davem; +Cc: Prasanna S Panchamukhi, netdev, gospo, sassmann, Jeff Kirsher
In-Reply-To: <1335333314-6814-1-git-send-email-jeffrey.t.kirsher@intel.com>
From: Prasanna S Panchamukhi <ppanchamukhi@riverbed.com>
Following logs where seen on Systems with multiple NICs,
while using MSI interrupts as shown below:
Feb 16 15:09:32 (none) user.notice kernel: 0000:00:0d.0: lan0_0: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
Feb 16 15:09:32 (none) user.notice kernel: 0000:40:0d.0: wan0_1: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
Feb 16 15:09:32 (none) user.notice kernel: 0000:40:0d.0: lan0_1: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
Feb 16 15:09:32 (none) user.warn kernel: 0000:40:0e.0: wan4_0: MSI interrupt
test failed, using legacy interrupt.
Feb 16 15:09:32 (none) user.notice kernel: 0000:00:0e.0: wan1_0: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
Feb 16 15:09:33 (none) user.notice kernel: 0000:00:0e.0: lan1_0: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
Feb 16 15:09:33 (none) user.notice kernel: 0000:00:0f.0: wan2_0: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
Feb 16 15:09:33 (none) user.notice kernel: 0000:00:0f.0: lan2_0: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
Feb 16 15:09:33 (none) user.notice kernel: 0000:40:0a.0: wan3_0: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
Feb 16 15:09:33 (none) user.notice kernel: 0000:40:0a.0: lan3_0: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
Feb 16 15:09:34 (none) user.notice kernel: 0000:40:0e.0: lan4_0: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
Feb 16 15:09:34 (none) user.notice kernel: 0000:40:0f.0: wan5_0: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
Feb 16 15:09:34 (none) user.notice kernel: 0000:40:0f.0: lan5_0: NIC Link is Up
1000 Mbps Full Duplex, Flow Control: RX/TX
This patch fixes this problem by increasing the msleep from 50 to 100.
Signed-off-by: Prasanna S Panchamukhi <ppanchamukhi@riverbed.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/e1000e/netdev.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 19ab215..9520a6a 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -3799,7 +3799,7 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
/* fire an unusual interrupt on the test handler */
ew32(ICS, E1000_ICS_RXSEQ);
e1e_flush();
- msleep(50);
+ msleep(100);
e1000_irq_disable(adapter);
--
1.7.7.6
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox