* Re: [PATCH net-next] bonding: remove entries for master_ip and vlan_ip and query devices instead
From: David Miller @ 2012-03-17 5:55 UTC (permalink / raw)
To: andy; +Cc: fubar, netdev, ralf.zeidler
In-Reply-To: <CAHashqDhq20rqeOEdB0onOkV9yGF-dDKh22Ea4ra1KG21Uc9xQ@mail.gmail.com>
From: Andy Gospodarek <andy@greyhouse.net>
Date: Fri, 16 Mar 2012 09:48:23 -0400
> On Thu, Mar 15, 2012 at 9:03 PM, Jay Vosburgh <fubar@us.ibm.com> wrote:
>>>@@ -2618,7 +2624,9 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
>>> if (!bond_vlan_used(bond)) {
>>> pr_debug("basa: empty vlan: arp_send\n");
>>> bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
>>>- bond->master_ip, 0);
>>>+ bond_confirm_addr(bond->dev,
>>>+ targets[i],
>>>+ 0), 0);
>>
>> Same comment here and for the later calls to bond_confirm_addr,
>> here putting "targets[i]" and perhaps the 0 on the previous line,
>> although I'm less sure that it won't look funky.
>>
>> -J
>>
>
> These we a bit tough to get looking great. What I did really seemed
> like the best I could do and keep it to a reasonable length. If you
> want me to just keep the length of these lines <100 characters wide, I
> could combine them into the same line. Either way is fine with me,
> but I really just didn't want the code to get too wide and hard to
> read when using a standard size terminal.
It seems to me that the easiest thing to do is:
__be32 addr = bond_confirm_addr(bond->dev, targets[i], 0);
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], addr, 0);
And actually this sequence is used in three places, so even better
to put it into a helper function.
^ permalink raw reply
* Re: [PATCH v3] stmmac: Add device-tree support
From: David Miller @ 2012-03-17 5:49 UTC (permalink / raw)
To: sr; +Cc: netdev, devicetree-discuss, spear-devel, peppe.cavallaro
In-Reply-To: <1331650597-16747-1-git-send-email-sr@denx.de>
From: Stefan Roese <sr@denx.de>
Date: Tue, 13 Mar 2012 15:56:37 +0100
> This patch adds support to configure the STMMAC ethernet driver via
> device-tree instead of platform_data.
>
> Currently, only the properties needed on SPEAr600 are provided. All
> other properties should be added once needed on other platforms.
>
> Signed-off-by: Stefan Roese <sr@denx.de>
> Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH net-next] usbnet: use netif_tx_wake_queue instead of netif_start_queue
From: David Miller @ 2012-03-17 5:50 UTC (permalink / raw)
To: oneukum; +Cc: alexey.orishko, netdev, linux-usb, greg, alexey.orishko
In-Reply-To: <201203151805.09136.oneukum@suse.de>
From: Oliver Neukum <oneukum@suse.de>
Date: Thu, 15 Mar 2012 18:05:09 +0100
> Am Mittwoch, 14. März 2012, 15:00:24 schrieb Alexey Orishko:
>> If host is going to autosuspend function with two interfaces and
>> if IP packet has arrived in-between of two usbnet_suspend() callbacks,
>> i.e usbnet_resume() is called in-between, tx data flow is stopped.
>> When autosuspend timer expires and device is put to autosuspend
>> again, tx queue is waked up and data can be sent again.
>> This behavior might be repeated several times in a row.
>>
>> Tested on Intel/ARM.
>>
>> Reviewed-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
>> Tested-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>
>> Signed-off-by: Alexey Orishko <alexey.orishko@stericsson.com>
> Acked-by: Oliver Neukum <oneukum@suse.de>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH v5] ipv6: Fix problem with expired dst cache
From: David Miller @ 2012-03-17 5:33 UTC (permalink / raw)
To: gaofeng; +Cc: netdev, eric.dumazet
In-Reply-To: <1330931762-1466-1-git-send-email-gaofeng@cn.fujitsu.com>
From: Gao feng <gaofeng@cn.fujitsu.com>
Date: Mon, 5 Mar 2012 15:16:02 +0800
> If the ipv6 dst cache which copy from the dst generated by ICMPV6 RA packet.
> this dst cache will not check expire because it has no RTF_EXPIRES flag.
> So this dst cache will always be used until the dst gc run.
>
> Change the struct dst_entry,add a union contains new pointer from and expires.
> When rt6_info.rt6i_flags has no RTF_EXPIRES flag,the dst.expires has no use.
> we can use this field to point to where the dst cache copy from.
> The dst.from is only used in IPV6.
>
> In func rt6_check_expired check if rt6_info.dst.from is expired.
>
> In func ip6_rt_copy only set dst.from when the ort has flag RTF_ADDRCONF
> and RTF_DEFAULT.then hold the ort.
>
> In func ip6_dst_destroy release the ort.
>
> Add some functions to operate the RTF_EXPIRES flag and expires(from) together.
> and change the code to use these new adding functions.
>
> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
I see some unprotected access to dst.expires in the router discovery
code in net/ipv6/ndisc.c, doesn't that need to be updated?
There are probably some more similar cases elsewhere in the ipv6 code
too.
^ permalink raw reply
* Re: [PATCH 3/3 v3] netxen: qlogic ethernet : Fix endian bug.
From: David Miller @ 2012-03-17 5:23 UTC (permalink / raw)
To: santoshprasadnayak
Cc: sony.chacko, rajesh.borundia, netdev, linux-kernel,
kernel-janitors
In-Reply-To: <1331629104-3283-1-git-send-email-santoshprasadnayak@gmail.com>
From: santosh nayak <santoshprasadnayak@gmail.com>
Date: Tue, 13 Mar 2012 14:28:24 +0530
> From: Santosh Nayak <santoshprasadnayak@gmail.com>
>
> Change the datatype of "ip_addr" to __be32 as 'ip' should be in
> big endian format.
>
> Adapter needs "ip address" in big endian format stored at lower 32bit
> of req.word[1]. netxen_config_ipaddr() now receives 'ip' in big endian
> format. To satisfy adapter's need, use memcpy() to copy byte by byte
> of 'ip' into lower 32bit of req.word[1].
>
> Mac address and serial number of adapter need to be in little endian format.
> Change the data type of the related variables to __le32 / __le64 or cast it
> explicitly to __le32 / __le64 depending upon the requirement.
>
> Signed-off-by: Santosh Nayak <santoshprasadnayak@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH] adjust __net_exit
From: David Miller @ 2012-03-17 5:18 UTC (permalink / raw)
To: JBeulich; +Cc: netdev, netfilter-devel, sam, xemul, ebiederm
In-Reply-To: <4F588BEC020000780007710A@nat28.tlf.novell.com>
From: "Jan Beulich" <JBeulich@suse.com>
Date: Thu, 08 Mar 2012 09:37:32 +0000
> __net_exit, judging by the majority of its uses, was intended to serve
> as an abstraction to allow calling such annotated functions from both
> __init and __exit functions. Using the (bogus and unused elsewhere)
> __exit_refok to implement this is inefficient - any non-modular code
> really can reside in __init (as non-modular __exit code is never used).
>
> Therefore, adjust __net_exit to resolve to nothing (i.e. normal .text)
> in modules, and __init in the core kernel.
>
> A few other adjustments are necessary/possible with this done - those
> were likely just oversights when added originally.
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
[ I have been waiting for more than a week for a netns developer
to review this patch, I guess I'm too optimistic these days. :-( ]
The only reason you think __exit_refok is "bogus" is because it's
semantics got changed by Sam Ravnborg in commit
312b1485fb509c9bc32eda28ad29537896658cb8 ("Introduce new section
reference annotations tags: __ref, __refdata, __refconst")
Beforehand the __exit_refok was a real .exit section, so it got
completely discarded AT LINK TIME. Now it sits together with
__init_refok which is an unremovable kernel image section, which
neither gets removed at compile time nor boot time.
So __exit_refok did exactly what you say it should do before Sam's
change.
It's just completely stupid to change the netns section defines,
and instead we should revert __exit_refok to mean what it always
meant previously.
I'm not applying this patch.
^ permalink raw reply
* Re: [PATCH] ipv6: fix incorrent ipv6 ipsec packet fragment
From: David Miller @ 2012-03-17 4:58 UTC (permalink / raw)
To: gaofeng; +Cc: steffen.klassert, eric.dumazet, netdev
In-Reply-To: <1331888235-10368-1-git-send-email-gaofeng@cn.fujitsu.com>
From: Gao feng <gaofeng@cn.fujitsu.com>
Date: Fri, 16 Mar 2012 16:57:15 +0800
> Since commit 299b0767(ipv6: Fix IPsec slowpath fragmentation problem)
> In func ip6_append_data,after call skb_put(skb, fraglen + dst_exthdrlen)
> the skb->len contains dst_exthdrlen,and we don't reduce dst_exthdrlen at last
> This will make fraggap>0 in next "while cycle",and cause the size of skb incorrent
>
> Call skb_pull reduce skb->len before next "while cycle"
>
> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Steffen please review this patch.
> ---
> net/ipv6/ip6_output.c | 3 ++-
> 1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index d97e071..f67f840 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -1450,7 +1450,8 @@ alloc_new_skb:
> kfree_skb(skb);
> goto error;
> }
> -
> +
> + skb_pull(skb, dst_exthdrlen);
> offset += copy;
> length -= datalen - fraggap;
> transhdrlen = 0;
> --
> 1.7.5.4
^ permalink raw reply
* Re: [PATCH] ipv6: Don't dev_hold(dev) in ip6_mc_find_dev_rcu.
From: David Miller @ 2012-03-17 4:57 UTC (permalink / raw)
To: eric.dumazet; +Cc: roy.qing.li, netdev
In-Reply-To: <1331907353.2420.1.camel@edumazet-laptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 16 Mar 2012 07:15:53 -0700
> Le vendredi 16 mars 2012 à 16:54 +0800, roy.qing.li@gmail.com a écrit :
>> From: RongQing.Li <roy.qing.li@gmail.com>
>>
>> ip6_mc_find_dev_rcu() is called with rcu_read_lock(), so don't
>> need to dev_hold().
>> With dev_hold(), not corresponding dev_put(), will lead to leak.
>>
>> Signed-off-by: RongQing.Li <roy.qing.li@gmail.com>
...
> Nice catch, bug introduced in 96b52e61be1 (ipv6: mcast: RCU conversions)
>
> Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* Re: [PATCH net-next-2.6 V2] pxa168: remove unused stats member.
From: David Miller @ 2012-03-17 4:55 UTC (permalink / raw)
To: ramirose; +Cc: netdev
In-Reply-To: <CAHLOa7R91pX6a-Nvs4j5rj1UhkQhXFywKM=G48b78tmANxfw5A@mail.gmail.com>
From: Rami Rosen <ramirose@gmail.com>
Date: Fri, 16 Mar 2012 17:19:36 +0200
> The patch removes unused stats member in pxa168 network driver.
>
> Signed-off-by: Rami Rosen <ramirose@gmail.com>
Applied, thanks.
^ permalink raw reply
* Your Mailbox Is Almost Full
From: William Pickavance @ 2012-03-17 0:28 UTC (permalink / raw)
Your Mailbox Is Almost Full "CLICK HERE<http://accountadmin.moy.su/microsoft_outlook.htm>" Update Your Mail Box And Increase Your Account. Thanks System Administrator.
^ permalink raw reply
* Re: setns question
From: Eric W. Biederman @ 2012-03-16 23:36 UTC (permalink / raw)
To: yao zhao; +Cc: netdev
In-Reply-To: <CADDf=MSHZUeq8V9jx9ybofCu9m=_L2vYaNRhFEd9EL0AVi5O4w@mail.gmail.com>
yao zhao <yao.development@gmail.com> writes:
> Hi Eric,
>
> Can I ask some questions about setns?
>
> 1.setns is complete > 3.0 but right now it doesn't support mnt and pid
> yet.
Correct. I need to find some time and get those patches merged.
> 2.setns can set a process' uts, net, ipc to different namespace,
Yes.
> it is not fd based, right?
The argument to setns is a fd.
> 3.is this supported:
> ProcessA's uts == ProcessB's uts
> ProcessA's ipc == ProcessC's ipc
> ProcessA's net == ProcessD's net
Yes. Even without setns that is supported.
I suggest if you want more details you read the code.
Eric
^ permalink raw reply
* Re: [PATCH net-next] ethtool: Added a field fw dump_state
From: Anirban Chakraborty @ 2012-03-16 22:37 UTC (permalink / raw)
To: Ben Hutchings, Eric Dumazet
Cc: David Miller, netdev, Dept-NX Linux NIC Driver, Manish Chopra
In-Reply-To: <1331933824.2504.22.camel@bwh-desktop.uk.solarflarecom.com>
On 3/16/12 2:37 PM, "Ben Hutchings" <bhutchings@solarflare.com> wrote:
>On Fri, 2012-03-16 at 14:22 -0700, Eric Dumazet wrote:
>> On Fri, 2012-03-16 at 14:10 -0700, Anirban Chakraborty wrote:
>> >
>> > On 3/16/12 11:27 AM, "Ben Hutchings" <bhutchings@solarflare.com>
>>wrote:
>> >
>> > >On Fri, 2012-03-16 at 10:58 -0700, Anirban Chakraborty wrote:
>> > >> +
>> > >> struct ethtool_dump {
>> > >> __u32 cmd;
>> > >> __u32 version;
>> > >> __u32 flag;
>> > >> __u32 len;
>> > >> __u8 data[0];
>> > >> + __u8 dump_state;
>> > >
>> > >Don't be ridiculous.
>> >
>> > Yeah I know, especially when there is a flag field already present
>>there.
>> > The only
>> > reason, we considered for adding it is to keep the backward
>>compatibility
>> > of scripts.
>> > Right now, the flag field sets/gets the dump level of fw. If we use
>>it to
>> > control the
>> > dump state, then it would break the existing scripts, if there are
>>any.
>> >
>>
>> You missed the point... data[0] must be the last element in the
>> structure.
>
>Right. And len is documented as not used by the ETHTOOL_SET_DUMP
>command so we cannot say that when len == 1 then data[0] is this new
>flag.
>
>Just reserve some value of the flag to mean 'disable', say 0 or
>0xffffffff. If you want this 'disable' value to be understood by all
>drivers and have ethtool support a keyword for it then also define a
>macro for the value in ethtool.h.
Thanks for your comments. We'll take care of it next submittal.
-Anirban
^ permalink raw reply
* Re: Sundance network driver (D-Link DFE-580TX) timeouts rendering interface unusable
From: Jonathan Nieder @ 2012-03-16 22:11 UTC (permalink / raw)
To: Mike .; +Cc: eric.dumazet, ben, kirjanov, netdev, benoit.mortier, herbert
In-Reply-To: <20120316220413.GA31359@burratino>
Jonathan Nieder wrote:
> Thanks. I assume current 3.3 release candidates behave the same way.
>
> Based on [2], it looks like v2.6.25-rc9~99^2~24 ([NET]: Add preemption
> point in qdisc_run, 2008-03-28) made this easier to trip.
>
> As for the next step: I'd suggest posting a summary of the symptoms,
> which kernel versions you have tested, and a link to [1] at
> http://bugzilla.kernel.org/
Here's the missing footnote[2]. Sorry for the noise.
[...]
> [1] http://thread.gmane.org/gmane.linux.network/219101
[2] http://bugs.debian.org/514833
^ permalink raw reply
* Re: Sundance network driver (D-Link DFE-580TX) timeouts rendering interface unusable
From: Jonathan Nieder @ 2012-03-16 22:04 UTC (permalink / raw)
To: Mike .; +Cc: eric.dumazet, ben, kirjanov, netdev, benoit.mortier, herbert
In-Reply-To: <SNT141-W2773C07AA4E8276F3E1E4496730@phx.gbl>
Hi again,
Mike . wrote:
>> Oh well, we also must make sure we held np->lock in TX completion when
>> doing our test to eventually call netif_wake_queue(), I missed it was
>> released too early.
>>
>> here is a more complete patch.
>
> I applied the patch, recompiled the module, loaded it into the kernel and
> started testing traffic on the interface with the following result :
>
> [ 1124.008030] ------------[ cut here ]------------
> [ 1124.008101] WARNING: at /build/buildd-linux-2.6_3.2.1-2-i386-4wAPNj/linux-2.6-3.2.1/debian/build/source_i386_none/net/sched/sch_generic.c:255 dev_watchdog+0xb1/0x104()
> [ 1124.008201] Hardware name:
> [ 1124.008252] NETDEV WATCHDOG: eth1 (sundance): transmit queue 0 timed out
[...]
> After this the same repeat of transmit timeouts (as posted earlier) in the
> log untill I down the interface.
Thanks. I assume current 3.3 release candidates behave the same way.
Based on [2], it looks like v2.6.25-rc9~99^2~24 ([NET]: Add preemption
point in qdisc_run, 2008-03-28) made this easier to trip.
As for the next step: I'd suggest posting a summary of the symptoms,
which kernel versions you have tested, and a link to [1] at
http://bugzilla.kernel.org/, product Drivers, component Network, and
letting us know the bug number so we can track it without forgetting
what has already been learned.
Hope that helps,
Jonathan
[1] http://thread.gmane.org/gmane.linux.network/219101
^ permalink raw reply
* Re: [PATCH v2 4/4] ath9k: Support ethtool getstats api.
From: Christian Lamparter @ 2012-03-16 21:38 UTC (permalink / raw)
To: Ben Greear; +Cc: Ben Hutchings, linux-wireless, netdev
In-Reply-To: <4F63B00A.4050904@candelatech.com>
On Friday 16 March 2012 22:26:34 Ben Greear wrote:
> On 03/16/2012 01:57 PM, Ben Hutchings wrote:
> > On Fri, 2012-03-16 at 20:53 +0000, Ben Hutchings wrote:
> >> On Fri, 2012-03-16 at 12:59 -0700, greearb@candelatech.com wrote:
> >>> From: Ben Greear<greearb@candelatech.com>
> >>>
> >>> This returns many of the values that formerly could
> >>> only be obtained from debugfs. This should be an
> >>> improvement when trying to access these counters
> >>> programatically. Currently this support is only
> >>> enabled when DEBUGFS is enabled because otherwise
> >>> these stats are not accumulated.
> >> [...]
> >>
> >> Given that ethtool (unlike debugfs) is itself an unconditional feature,
> >> why not make this unconditional? Is it expensive to accumulate the
> >> stats?
> >>
> >> Please at least fix the name.
> > ^ config option
> >
>
> The ath9k stats are currently only gathered when debugfs is enabled.
>
> I could do some patches in the future to allow stats to always
> be gathered regardless of debugfs being enabled, but since
> ath9k is used on small form factor systems, there may be some
> resistance to enabling that all the time.
When we are talking about small form factor.
Did you know that OpenWRT has enabled ath9k's debugfs feature by default?
Even the image for my TL-WR841ND [just a 4MiB flash] has it enabled!
So I don't that's much of a problem. Even more the debugfs bits are
probably smaller than all those initvals [you know, those for the whole
AR5008/AR91XX/AR92XX/AR93XX/AR94XX gang] they have to carry around.
[Yeah, if you use the same rev-chips on your stuff, you could get
away with just one initval... Think of the savings!]
Regards,
Chr
^ permalink raw reply
* Re: [PATCH net-next] ethtool: Added a field fw dump_state
From: Ben Hutchings @ 2012-03-16 21:37 UTC (permalink / raw)
To: Eric Dumazet
Cc: Anirban Chakraborty, David Miller, netdev,
Dept-NX Linux NIC Driver, Manish Chopra
In-Reply-To: <1331932962.19406.23.camel@edumazet-glaptop>
On Fri, 2012-03-16 at 14:22 -0700, Eric Dumazet wrote:
> On Fri, 2012-03-16 at 14:10 -0700, Anirban Chakraborty wrote:
> >
> > On 3/16/12 11:27 AM, "Ben Hutchings" <bhutchings@solarflare.com> wrote:
> >
> > >On Fri, 2012-03-16 at 10:58 -0700, Anirban Chakraborty wrote:
> > >> +
> > >> struct ethtool_dump {
> > >> __u32 cmd;
> > >> __u32 version;
> > >> __u32 flag;
> > >> __u32 len;
> > >> __u8 data[0];
> > >> + __u8 dump_state;
> > >
> > >Don't be ridiculous.
> >
> > Yeah I know, especially when there is a flag field already present there.
> > The only
> > reason, we considered for adding it is to keep the backward compatibility
> > of scripts.
> > Right now, the flag field sets/gets the dump level of fw. If we use it to
> > control the
> > dump state, then it would break the existing scripts, if there are any.
> >
>
> You missed the point... data[0] must be the last element in the
> structure.
Right. And len is documented as not used by the ETHTOOL_SET_DUMP
command so we cannot say that when len == 1 then data[0] is this new
flag.
Just reserve some value of the flag to mean 'disable', say 0 or
0xffffffff. If you want this 'disable' value to be understood by all
drivers and have ethtool support a keyword for it then also define a
macro for the value in ethtool.h.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* [PATCH v8 RESEND] ARM: net: JIT compiler for packet filters
From: Mircea Gherzan @ 2012-03-16 21:28 UTC (permalink / raw)
To: linux; +Cc: mgherzan, netdev, linux-arm-kernel, eric.dumazet, davem
Based of Matt Evans's PPC64 implementation.
The compiler generates ARM instructions but interworking is
supported for Thumb2 kernels.
Supports both little and big endian. Unaligned loads are emitted
for ARMv6+. Not all the BPF opcodes that deal with ancillary data
are supported. The scratch memory of the filter lives on the stack.
Hardware integer division is used if it is available.
Enabled in the same way as for x86-64 and PPC64:
echo 1 > /proc/sys/net/core/bpf_jit_enable
A value greater than 1 enables opcode output.
Signed-off-by: Mircea Gherzan <mgherzan@gmail.com>
---
Changes in v8:
* skb_copy_bits() return value check in LDX_MSH
* immediate value as signed integer for absolute loads
Changes in v7:
* fix the intruction generation for LDX_MSH, OR_X, LSH_K,
RSH_K and JMP_JA
* fix the condition for saving the A register
* use fls() instead of the compiler builtin
* punt to the interpreter on absolute loads with K < 0
* check for invalid data references
* support the NEG opcode
* clear X in the prologue based on a context flag
* simplify the conditional jumps
Changes in v6:
* fix the code generation for the ANC_CPU opcode
Changes in v5:
* replace SEEN_LEN with SEEN_SKB
* set ctx->seen when handling some ancillary data opcodes
Changes in v4:
* first check if the JIT compiler is enabled
* fix the code generation for the LDX_MSH opcode
Changes in v3:
* no longer depend on EABI and !Thumb2
* add BLX "emulation" for ARMv4 without Thumb
* use the integer divide instruction on Cortex-A15
* fix the handling of the DIV_K opcode
* use a C wrapper for __aeabi_uidiv
* fix the generation of the epilogue (non-FP case)
Changes in v2:
* enable the compiler only for ARMv5+ because of the BLX instruction
* use the same comparison for the ARM version checks
* use misaligned accesses on ARMv6
* fix the SEEN_MEM
* fix the mem_words_used()
arch/arm/Kconfig | 1 +
arch/arm/Makefile | 1 +
arch/arm/net/Makefile | 3 +
arch/arm/net/bpf_jit_32.c | 916 +++++++++++++++++++++++++++++++++++++++++++++
arch/arm/net/bpf_jit_32.h | 190 ++++++++++
5 files changed, 1111 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/net/Makefile
create mode 100644 arch/arm/net/bpf_jit_32.c
create mode 100644 arch/arm/net/bpf_jit_32.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dfb0312..ade6274 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -32,6 +32,7 @@ config ARM
select GENERIC_IRQ_SHOW
select CPU_PM if (SUSPEND || CPU_IDLE)
select GENERIC_PCI_IOMAP
+ select HAVE_BPF_JIT
help
The ARM series is a line of low-power-consumption RISC chip designs
licensed by ARM Ltd and targeted at embedded applications and
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 1683bfb..03b0039 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -252,6 +252,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/
# If we have a machine-specific directory, then include it in the build.
core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
+core-y += arch/arm/net/
core-y += $(machdirs) $(platdirs)
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
diff --git a/arch/arm/net/Makefile b/arch/arm/net/Makefile
new file mode 100644
index 0000000..c2c1084
--- /dev/null
+++ b/arch/arm/net/Makefile
@@ -0,0 +1,3 @@
+# ARM-specific networking code
+
+obj-$(CONFIG_BPF_JIT) += bpf_jit_32.o
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
new file mode 100644
index 0000000..2ee157a
--- /dev/null
+++ b/arch/arm/net/bpf_jit_32.c
@@ -0,0 +1,916 @@
+/*
+ * Just-In-Time compiler for BPF filters on 32bit ARM
+ *
+ * Copyright (c) 2011 Mircea Gherzan <mgherzan@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/filter.h>
+#include <linux/moduleloader.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/cacheflush.h>
+#include <asm/hwcap.h>
+
+#include "bpf_jit_32.h"
+
+/*
+ * ABI:
+ *
+ * r0 scratch register
+ * r4 BPF register A
+ * r5 BPF register X
+ * r6 pointer to the skb
+ * r7 skb->data
+ * r8 skb_headlen(skb)
+ */
+
+#define r_scratch ARM_R0
+/* r1-r3 are (also) used for the unaligned loads on the non-ARMv7 slowpath */
+#define r_off ARM_R1
+#define r_A ARM_R4
+#define r_X ARM_R5
+#define r_skb ARM_R6
+#define r_skb_data ARM_R7
+#define r_skb_hl ARM_R8
+
+#define SCRATCH_SP_OFFSET 0
+#define SCRATCH_OFF(k) (SCRATCH_SP_OFFSET + (k))
+
+#define SEEN_MEM ((1 << BPF_MEMWORDS) - 1)
+#define SEEN_MEM_WORD(k) (1 << (k))
+#define SEEN_X (1 << BPF_MEMWORDS)
+#define SEEN_CALL (1 << (BPF_MEMWORDS + 1))
+#define SEEN_SKB (1 << (BPF_MEMWORDS + 2))
+#define SEEN_DATA (1 << (BPF_MEMWORDS + 3))
+
+#define FLAG_NEED_X_RESET (1 << 0)
+
+struct jit_ctx {
+ const struct sk_filter *skf;
+ unsigned idx;
+ unsigned prologue_bytes;
+ int ret0_fp_idx;
+ u32 seen;
+ u32 flags;
+ u32 *offsets;
+ u32 *target;
+#if __LINUX_ARM_ARCH__ < 7
+ u16 epilogue_bytes;
+ u16 imm_count;
+ u32 *imms;
+#endif
+};
+
+int bpf_jit_enable __read_mostly;
+
+static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset)
+{
+ u8 ret;
+ int err;
+
+ err = skb_copy_bits(skb, offset, &ret, 1);
+
+ return (u64)err << 32 | ret;
+}
+
+static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset)
+{
+ u16 ret;
+ int err;
+
+ err = skb_copy_bits(skb, offset, &ret, 2);
+
+ return (u64)err << 32 | ntohs(ret);
+}
+
+static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset)
+{
+ u32 ret;
+ int err;
+
+ err = skb_copy_bits(skb, offset, &ret, 4);
+
+ return (u64)err << 32 | ntohl(ret);
+}
+
+/*
+ * Wrapper that handles both OABI and EABI and assures Thumb2 interworking
+ * (where the assembly routines like __aeabi_uidiv could cause problems).
+ */
+static u32 jit_udiv(u32 dividend, u32 divisor)
+{
+ return dividend / divisor;
+}
+
+static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx)
+{
+ if (ctx->target != NULL)
+ ctx->target[ctx->idx] = inst | (cond << 28);
+
+ ctx->idx++;
+}
+
+/*
+ * Emit an instruction that will be executed unconditionally.
+ */
+static inline void emit(u32 inst, struct jit_ctx *ctx)
+{
+ _emit(ARM_COND_AL, inst, ctx);
+}
+
+static u16 saved_regs(struct jit_ctx *ctx)
+{
+ u16 ret = 0;
+
+ if ((ctx->skf->len > 1) ||
+ (ctx->skf->insns[0].code == BPF_S_RET_A))
+ ret |= 1 << r_A;
+
+#ifdef CONFIG_FRAME_POINTER
+ ret |= (1 << ARM_FP) | (1 << ARM_IP) | (1 << ARM_LR) | (1 << ARM_PC);
+#else
+ if (ctx->seen & SEEN_CALL)
+ ret |= 1 << ARM_LR;
+#endif
+ if (ctx->seen & (SEEN_DATA | SEEN_SKB))
+ ret |= 1 << r_skb;
+ if (ctx->seen & SEEN_DATA)
+ ret |= (1 << r_skb_data) | (1 << r_skb_hl);
+ if (ctx->seen & SEEN_X)
+ ret |= 1 << r_X;
+
+ return ret;
+}
+
+static inline int mem_words_used(struct jit_ctx *ctx)
+{
+ /* yes, we do waste some stack space IF there are "holes" in the set" */
+ return fls(ctx->seen & SEEN_MEM);
+}
+
+static inline bool is_load_to_a(u16 inst)
+{
+ switch (inst) {
+ case BPF_S_LD_W_LEN:
+ case BPF_S_LD_W_ABS:
+ case BPF_S_LD_H_ABS:
+ case BPF_S_LD_B_ABS:
+ case BPF_S_ANC_CPU:
+ case BPF_S_ANC_IFINDEX:
+ case BPF_S_ANC_MARK:
+ case BPF_S_ANC_PROTOCOL:
+ case BPF_S_ANC_RXHASH:
+ case BPF_S_ANC_QUEUE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void build_prologue(struct jit_ctx *ctx)
+{
+ u16 reg_set = saved_regs(ctx);
+ u16 first_inst = ctx->skf->insns[0].code;
+ u16 off;
+
+#ifdef CONFIG_FRAME_POINTER
+ emit(ARM_MOV_R(ARM_IP, ARM_SP), ctx);
+ emit(ARM_PUSH(reg_set), ctx);
+ emit(ARM_SUB_I(ARM_FP, ARM_IP, 4), ctx);
+#else
+ if (reg_set)
+ emit(ARM_PUSH(reg_set), ctx);
+#endif
+
+ if (ctx->seen & (SEEN_DATA | SEEN_SKB))
+ emit(ARM_MOV_R(r_skb, ARM_R0), ctx);
+
+ if (ctx->seen & SEEN_DATA) {
+ off = offsetof(struct sk_buff, data);
+ emit(ARM_LDR_I(r_skb_data, r_skb, off), ctx);
+ /* headlen = len - data_len */
+ off = offsetof(struct sk_buff, len);
+ emit(ARM_LDR_I(r_skb_hl, r_skb, off), ctx);
+ off = offsetof(struct sk_buff, data_len);
+ emit(ARM_LDR_I(r_scratch, r_skb, off), ctx);
+ emit(ARM_SUB_R(r_skb_hl, r_skb_hl, r_scratch), ctx);
+ }
+
+ if (ctx->flags & FLAG_NEED_X_RESET)
+ emit(ARM_MOV_I(r_X, 0), ctx);
+
+ /* do not leak kernel data to userspace */
+ if ((first_inst != BPF_S_RET_K) && !(is_load_to_a(first_inst)))
+ emit(ARM_MOV_I(r_A, 0), ctx);
+
+ /* stack space for the BPF_MEM words */
+ if (ctx->seen & SEEN_MEM)
+ emit(ARM_SUB_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx);
+}
+
+static void build_epilogue(struct jit_ctx *ctx)
+{
+ u16 reg_set = saved_regs(ctx);
+
+ if (ctx->seen & SEEN_MEM)
+ emit(ARM_ADD_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx);
+
+ reg_set &= ~(1 << ARM_LR);
+
+#ifdef CONFIG_FRAME_POINTER
+ /* the first instruction of the prologue was: mov ip, sp */
+ reg_set &= ~(1 << ARM_IP);
+ reg_set |= (1 << ARM_SP);
+ emit(ARM_LDM(ARM_SP, reg_set), ctx);
+#else
+ if (reg_set) {
+ if (ctx->seen & SEEN_CALL)
+ reg_set |= 1 << ARM_PC;
+ emit(ARM_POP(reg_set), ctx);
+ }
+
+ if (!(ctx->seen & SEEN_CALL))
+ emit(ARM_BX(ARM_LR), ctx);
+#endif
+}
+
+static int16_t imm8m(u32 x)
+{
+ u32 rot;
+
+ for (rot = 0; rot < 16; rot++)
+ if ((x & ~ror32(0xff, 2 * rot)) == 0)
+ return rol32(x, 2 * rot) | (rot << 8);
+
+ return -1;
+}
+
+#if __LINUX_ARM_ARCH__ < 7
+
+static u16 imm_offset(u32 k, struct jit_ctx *ctx)
+{
+ unsigned i = 0, offset;
+ u16 imm;
+
+ /* on the "fake" run we just count them (duplicates included) */
+ if (ctx->target == NULL) {
+ ctx->imm_count++;
+ return 0;
+ }
+
+ while ((i < ctx->imm_count) && ctx->imms[i]) {
+ if (ctx->imms[i] == k)
+ break;
+ i++;
+ }
+
+ if (ctx->imms[i] == 0)
+ ctx->imms[i] = k;
+
+ /* constants go just after the epilogue */
+ offset = ctx->offsets[ctx->skf->len];
+ offset += ctx->prologue_bytes;
+ offset += ctx->epilogue_bytes;
+ offset += i * 4;
+
+ ctx->target[offset / 4] = k;
+
+ /* PC in ARM mode == address of the instruction + 8 */
+ imm = offset - (8 + ctx->idx * 4);
+
+ return imm;
+}
+
+#endif /* __LINUX_ARM_ARCH__ */
+
+/*
+ * Move an immediate that's not an imm8m to a core register.
+ */
+static inline void emit_mov_i_no8m(int rd, u32 val, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ < 7
+ emit(ARM_LDR_I(rd, ARM_PC, imm_offset(val, ctx)), ctx);
+#else
+ emit(ARM_MOVW(rd, val & 0xffff), ctx);
+ if (val > 0xffff)
+ emit(ARM_MOVT(rd, val >> 16), ctx);
+#endif
+}
+
+static inline void emit_mov_i(int rd, u32 val, struct jit_ctx *ctx)
+{
+ int imm12 = imm8m(val);
+
+ if (imm12 >= 0)
+ emit(ARM_MOV_I(rd, imm12), ctx);
+ else
+ emit_mov_i_no8m(rd, val, ctx);
+}
+
+#if __LINUX_ARM_ARCH__ < 6
+
+static void emit_load_be32(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+ _emit(cond, ARM_LDRB_I(ARM_R3, r_addr, 1), ctx);
+ _emit(cond, ARM_LDRB_I(ARM_R1, r_addr, 0), ctx);
+ _emit(cond, ARM_LDRB_I(ARM_R2, r_addr, 3), ctx);
+ _emit(cond, ARM_LSL_I(ARM_R3, ARM_R3, 16), ctx);
+ _emit(cond, ARM_LDRB_I(ARM_R0, r_addr, 2), ctx);
+ _emit(cond, ARM_ORR_S(ARM_R3, ARM_R3, ARM_R1, SRTYPE_LSL, 24), ctx);
+ _emit(cond, ARM_ORR_R(ARM_R3, ARM_R3, ARM_R2), ctx);
+ _emit(cond, ARM_ORR_S(r_res, ARM_R3, ARM_R0, SRTYPE_LSL, 8), ctx);
+}
+
+static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+ _emit(cond, ARM_LDRB_I(ARM_R1, r_addr, 0), ctx);
+ _emit(cond, ARM_LDRB_I(ARM_R2, r_addr, 1), ctx);
+ _emit(cond, ARM_ORR_S(r_res, ARM_R2, ARM_R1, SRTYPE_LSL, 8), ctx);
+}
+
+static inline void emit_swap16(u8 r_dst, u8 r_src, struct jit_ctx *ctx)
+{
+ emit(ARM_LSL_R(ARM_R1, r_src, 8), ctx);
+ emit(ARM_ORR_S(r_dst, ARM_R1, r_src, SRTYPE_LSL, 8), ctx);
+ emit(ARM_LSL_I(r_dst, r_dst, 8), ctx);
+ emit(ARM_LSL_R(r_dst, r_dst, 8), ctx);
+}
+
+#else /* ARMv6+ */
+
+static void emit_load_be32(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+ _emit(cond, ARM_LDR_I(r_res, r_addr, 0), ctx);
+#ifdef __LITTLE_ENDIAN
+ _emit(cond, ARM_REV(r_res, r_res), ctx);
+#endif
+}
+
+static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+ _emit(cond, ARM_LDRH_I(r_res, r_addr, 0), ctx);
+#ifdef __LITTLE_ENDIAN
+ _emit(cond, ARM_REV16(r_res, r_res), ctx);
+#endif
+}
+
+static inline void emit_swap16(u8 r_dst __maybe_unused,
+ u8 r_src __maybe_unused,
+ struct jit_ctx *ctx __maybe_unused)
+{
+#ifdef __LITTLE_ENDIAN
+ emit(ARM_REV16(r_dst, r_src), ctx);
+#endif
+}
+
+#endif /* __LINUX_ARM_ARCH__ < 6 */
+
+
+/* Compute the immediate value for a PC-relative branch. */
+static inline u32 b_imm(unsigned tgt, struct jit_ctx *ctx)
+{
+ u32 imm;
+
+ if (ctx->target == NULL)
+ return 0;
+ /*
+ * BPF allows only forward jumps and the offset of the target is
+ * still the one computed during the first pass.
+ */
+ imm = ctx->offsets[tgt] + ctx->prologue_bytes - (ctx->idx * 4 + 8);
+
+ return imm >> 2;
+}
+
+#define OP_IMM3(op, r1, r2, imm_val, ctx) \
+ do { \
+ imm12 = imm8m(imm_val); \
+ if (imm12 < 0) { \
+ emit_mov_i_no8m(r_scratch, imm_val, ctx); \
+ emit(op ## _R((r1), (r2), r_scratch), ctx); \
+ } else { \
+ emit(op ## _I((r1), (r2), imm12), ctx); \
+ } \
+ } while (0)
+
+static inline void emit_err_ret(u8 cond, struct jit_ctx *ctx)
+{
+ if (ctx->ret0_fp_idx >= 0) {
+ _emit(cond, ARM_B(b_imm(ctx->ret0_fp_idx, ctx)), ctx);
+ /* NOP to keep the size constant between passes */
+ emit(ARM_MOV_R(ARM_R0, ARM_R0), ctx);
+ } else {
+ _emit(cond, ARM_MOV_I(ARM_R0, 0), ctx);
+ _emit(cond, ARM_B(b_imm(ctx->skf->len, ctx)), ctx);
+ }
+}
+
+static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ < 5
+ emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
+
+ if (elf_hwcap & HWCAP_THUMB)
+ emit(ARM_BX(tgt_reg), ctx);
+ else
+ emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx);
+#else
+ emit(ARM_BLX_R(tgt_reg), ctx);
+#endif
+}
+
+static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ == 7
+ if (elf_hwcap & HWCAP_IDIVA) {
+ emit(ARM_UDIV(rd, rm, rn), ctx);
+ return;
+ }
+#endif
+ if (rm != ARM_R0)
+ emit(ARM_MOV_R(ARM_R0, rm), ctx);
+ if (rn != ARM_R1)
+ emit(ARM_MOV_R(ARM_R1, rn), ctx);
+
+ ctx->seen |= SEEN_CALL;
+ emit_mov_i(ARM_R3, (u32)jit_udiv, ctx);
+ emit_blx_r(ARM_R3, ctx);
+
+ if (rd != ARM_R0)
+ emit(ARM_MOV_R(rd, ARM_R0), ctx);
+}
+
+static inline void update_on_xread(struct jit_ctx *ctx)
+{
+ if (!(ctx->seen & SEEN_X))
+ ctx->flags |= FLAG_NEED_X_RESET;
+
+ ctx->seen |= SEEN_X;
+}
+
+static int build_body(struct jit_ctx *ctx)
+{
+ void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w};
+ const struct sk_filter *prog = ctx->skf;
+ const struct sock_filter *inst;
+ unsigned i, load_order, off, condt;
+ int imm12;
+ u32 k;
+
+ for (i = 0; i < prog->len; i++) {
+ inst = &(prog->insns[i]);
+ /* K as an immediate value operand */
+ k = inst->k;
+
+ /* compute offsets only in the fake pass */
+ if (ctx->target == NULL)
+ ctx->offsets[i] = ctx->idx * 4;
+
+ switch (inst->code) {
+ case BPF_S_LD_IMM:
+ emit_mov_i(r_A, k, ctx);
+ break;
+ case BPF_S_LD_W_LEN:
+ ctx->seen |= SEEN_SKB;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+ emit(ARM_LDR_I(r_A, r_skb,
+ offsetof(struct sk_buff, len)), ctx);
+ break;
+ case BPF_S_LD_MEM:
+ /* A = scratch[k] */
+ ctx->seen |= SEEN_MEM_WORD(k);
+ emit(ARM_LDR_I(r_A, ARM_SP, SCRATCH_OFF(k)), ctx);
+ break;
+ case BPF_S_LD_W_ABS:
+ load_order = 2;
+ goto load;
+ case BPF_S_LD_H_ABS:
+ load_order = 1;
+ goto load;
+ case BPF_S_LD_B_ABS:
+ load_order = 0;
+load:
+ /* the interpreter will deal with the negative K */
+ if ((int)k < 0)
+ return -ENOTSUPP;
+ emit_mov_i(r_off, k, ctx);
+load_common:
+ ctx->seen |= SEEN_DATA | SEEN_CALL;
+
+ if (load_order > 0) {
+ emit(ARM_SUB_I(r_scratch, r_skb_hl,
+ 1 << load_order), ctx);
+ emit(ARM_CMP_R(r_scratch, r_off), ctx);
+ condt = ARM_COND_HS;
+ } else {
+ emit(ARM_CMP_R(r_skb_hl, r_off), ctx);
+ condt = ARM_COND_HI;
+ }
+
+ _emit(condt, ARM_ADD_R(r_scratch, r_off, r_skb_data),
+ ctx);
+
+ if (load_order == 0)
+ _emit(condt, ARM_LDRB_I(r_A, r_scratch, 0),
+ ctx);
+ else if (load_order == 1)
+ emit_load_be16(condt, r_A, r_scratch, ctx);
+ else if (load_order == 2)
+ emit_load_be32(condt, r_A, r_scratch, ctx);
+
+ _emit(condt, ARM_B(b_imm(i + 1, ctx)), ctx);
+
+ /* the slowpath */
+ emit_mov_i(ARM_R3, (u32)load_func[load_order], ctx);
+ emit(ARM_MOV_R(ARM_R0, r_skb), ctx);
+ /* the offset is already in R1 */
+ emit_blx_r(ARM_R3, ctx);
+ /* check the result of skb_copy_bits */
+ emit(ARM_CMP_I(ARM_R1, 0), ctx);
+ emit_err_ret(ARM_COND_NE, ctx);
+ emit(ARM_MOV_R(r_A, ARM_R0), ctx);
+ break;
+ case BPF_S_LD_W_IND:
+ load_order = 2;
+ goto load_ind;
+ case BPF_S_LD_H_IND:
+ load_order = 1;
+ goto load_ind;
+ case BPF_S_LD_B_IND:
+ load_order = 0;
+load_ind:
+ OP_IMM3(ARM_ADD, r_off, r_X, k, ctx);
+ goto load_common;
+ case BPF_S_LDX_IMM:
+ ctx->seen |= SEEN_X;
+ emit_mov_i(r_X, k, ctx);
+ break;
+ case BPF_S_LDX_W_LEN:
+ ctx->seen |= SEEN_X | SEEN_SKB;
+ emit(ARM_LDR_I(r_X, r_skb,
+ offsetof(struct sk_buff, len)), ctx);
+ break;
+ case BPF_S_LDX_MEM:
+ ctx->seen |= SEEN_X | SEEN_MEM_WORD(k);
+ emit(ARM_LDR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx);
+ break;
+ case BPF_S_LDX_B_MSH:
+ /* x = ((*(frame + k)) & 0xf) << 2; */
+ ctx->seen |= SEEN_X | SEEN_DATA | SEEN_CALL;
+ /* the interpreter should deal with the negative K */
+ if (k < 0)
+ return -1;
+ /* offset in r1: we might have to take the slow path */
+ emit_mov_i(r_off, k, ctx);
+ emit(ARM_CMP_R(r_skb_hl, r_off), ctx);
+
+ /* load in r0: common with the slowpath */
+ _emit(ARM_COND_HI, ARM_LDRB_R(ARM_R0, r_skb_data,
+ ARM_R1), ctx);
+ /*
+ * emit_mov_i() might generate one or two instructions,
+ * the same holds for emit_blx_r()
+ */
+ _emit(ARM_COND_HI, ARM_B(b_imm(i + 1, ctx) - 2), ctx);
+
+ emit(ARM_MOV_R(ARM_R0, r_skb), ctx);
+ /* r_off is r1 */
+ emit_mov_i(ARM_R3, (u32)jit_get_skb_b, ctx);
+ emit_blx_r(ARM_R3, ctx);
+ /* check the return value of skb_copy_bits */
+ emit(ARM_CMP_I(ARM_R1, 0), ctx);
+ emit_err_ret(ARM_COND_NE, ctx);
+
+ emit(ARM_AND_I(r_X, ARM_R0, 0x00f), ctx);
+ emit(ARM_LSL_I(r_X, r_X, 2), ctx);
+ break;
+ case BPF_S_ST:
+ ctx->seen |= SEEN_MEM_WORD(k);
+ emit(ARM_STR_I(r_A, ARM_SP, SCRATCH_OFF(k)), ctx);
+ break;
+ case BPF_S_STX:
+ update_on_xread(ctx);
+ ctx->seen |= SEEN_MEM_WORD(k);
+ emit(ARM_STR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx);
+ break;
+ case BPF_S_ALU_ADD_K:
+ /* A += K */
+ OP_IMM3(ARM_ADD, r_A, r_A, k, ctx);
+ break;
+ case BPF_S_ALU_ADD_X:
+ update_on_xread(ctx);
+ emit(ARM_ADD_R(r_A, r_A, r_X), ctx);
+ break;
+ case BPF_S_ALU_SUB_K:
+ /* A -= K */
+ OP_IMM3(ARM_SUB, r_A, r_A, k, ctx);
+ break;
+ case BPF_S_ALU_SUB_X:
+ update_on_xread(ctx);
+ emit(ARM_SUB_R(r_A, r_A, r_X), ctx);
+ break;
+ case BPF_S_ALU_MUL_K:
+ /* A *= K */
+ emit_mov_i(r_scratch, k, ctx);
+ emit(ARM_MUL(r_A, r_A, r_scratch), ctx);
+ break;
+ case BPF_S_ALU_MUL_X:
+ update_on_xread(ctx);
+ emit(ARM_MUL(r_A, r_A, r_X), ctx);
+ break;
+ case BPF_S_ALU_DIV_K:
+ /* current k == reciprocal_value(userspace k) */
+ emit_mov_i(r_scratch, k, ctx);
+ /* A = top 32 bits of the product */
+ emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx);
+ break;
+ case BPF_S_ALU_DIV_X:
+ update_on_xread(ctx);
+ emit(ARM_CMP_I(r_X, 0), ctx);
+ emit_err_ret(ARM_COND_EQ, ctx);
+ emit_udiv(r_A, r_A, r_X, ctx);
+ break;
+ case BPF_S_ALU_OR_K:
+ /* A |= K */
+ OP_IMM3(ARM_ORR, r_A, r_A, k, ctx);
+ break;
+ case BPF_S_ALU_OR_X:
+ update_on_xread(ctx);
+ emit(ARM_ORR_R(r_A, r_A, r_X), ctx);
+ break;
+ case BPF_S_ALU_AND_K:
+ /* A &= K */
+ OP_IMM3(ARM_AND, r_A, r_A, k, ctx);
+ break;
+ case BPF_S_ALU_AND_X:
+ update_on_xread(ctx);
+ emit(ARM_AND_R(r_A, r_A, r_X), ctx);
+ break;
+ case BPF_S_ALU_LSH_K:
+ if (unlikely(k > 31))
+ return -1;
+ emit(ARM_LSL_I(r_A, r_A, k), ctx);
+ break;
+ case BPF_S_ALU_LSH_X:
+ update_on_xread(ctx);
+ emit(ARM_LSL_R(r_A, r_A, r_X), ctx);
+ break;
+ case BPF_S_ALU_RSH_K:
+ if (unlikely(k > 31))
+ return -1;
+ emit(ARM_LSR_I(r_A, r_A, k), ctx);
+ break;
+ case BPF_S_ALU_RSH_X:
+ update_on_xread(ctx);
+ emit(ARM_LSR_R(r_A, r_A, r_X), ctx);
+ break;
+ case BPF_S_ALU_NEG:
+ /* A = -A */
+ emit(ARM_RSB_I(r_A, r_A, 0), ctx);
+ break;
+ case BPF_S_JMP_JA:
+ /* pc += K */
+ emit(ARM_B(b_imm(i + k + 1, ctx)), ctx);
+ break;
+ case BPF_S_JMP_JEQ_K:
+ /* pc += (A == K) ? pc->jt : pc->jf */
+ condt = ARM_COND_EQ;
+ goto cmp_imm;
+ case BPF_S_JMP_JGT_K:
+ /* pc += (A > K) ? pc->jt : pc->jf */
+ condt = ARM_COND_HI;
+ goto cmp_imm;
+ case BPF_S_JMP_JGE_K:
+ /* pc += (A >= K) ? pc->jt : pc->jf */
+ condt = ARM_COND_HS;
+cmp_imm:
+ imm12 = imm8m(k);
+ if (imm12 < 0) {
+ emit_mov_i_no8m(r_scratch, k, ctx);
+ emit(ARM_CMP_R(r_A, r_scratch), ctx);
+ } else {
+ emit(ARM_CMP_I(r_A, imm12), ctx);
+ }
+cond_jump:
+ if (inst->jt)
+ _emit(condt, ARM_B(b_imm(i + inst->jt + 1,
+ ctx)), ctx);
+ if (inst->jf)
+ _emit(condt ^ 1, ARM_B(b_imm(i + inst->jf + 1,
+ ctx)), ctx);
+ break;
+ case BPF_S_JMP_JEQ_X:
+ /* pc += (A == X) ? pc->jt : pc->jf */
+ condt = ARM_COND_EQ;
+ goto cmp_x;
+ case BPF_S_JMP_JGT_X:
+ /* pc += (A > X) ? pc->jt : pc->jf */
+ condt = ARM_COND_HI;
+ goto cmp_x;
+ case BPF_S_JMP_JGE_X:
+ /* pc += (A >= X) ? pc->jt : pc->jf */
+ condt = ARM_COND_CS;
+cmp_x:
+ update_on_xread(ctx);
+ emit(ARM_CMP_R(r_A, r_X), ctx);
+ goto cond_jump;
+ case BPF_S_JMP_JSET_K:
+ /* pc += (A & K) ? pc->jt : pc->jf */
+ condt = ARM_COND_NE;
+ /* not set iff all zeroes iff Z==1 iff EQ */
+
+ imm12 = imm8m(k);
+ if (imm12 < 0) {
+ emit_mov_i_no8m(r_scratch, k, ctx);
+ emit(ARM_TST_R(r_A, r_scratch), ctx);
+ } else {
+ emit(ARM_TST_I(r_A, imm12), ctx);
+ }
+ goto cond_jump;
+ case BPF_S_JMP_JSET_X:
+ /* pc += (A & X) ? pc->jt : pc->jf */
+ update_on_xread(ctx);
+ condt = ARM_COND_NE;
+ emit(ARM_TST_R(r_A, r_X), ctx);
+ goto cond_jump;
+ case BPF_S_RET_A:
+ emit(ARM_MOV_R(ARM_R0, r_A), ctx);
+ goto b_epilogue;
+ case BPF_S_RET_K:
+ if ((k == 0) && (ctx->ret0_fp_idx < 0))
+ ctx->ret0_fp_idx = i;
+ emit_mov_i(ARM_R0, k, ctx);
+b_epilogue:
+ if (i != ctx->skf->len - 1)
+ emit(ARM_B(b_imm(prog->len, ctx)), ctx);
+ break;
+ case BPF_S_MISC_TAX:
+ /* X = A */
+ ctx->seen |= SEEN_X;
+ emit(ARM_MOV_R(r_X, r_A), ctx);
+ break;
+ case BPF_S_MISC_TXA:
+ /* A = X */
+ update_on_xread(ctx);
+ emit(ARM_MOV_R(r_A, r_X), ctx);
+ break;
+ case BPF_S_ANC_PROTOCOL:
+ /* A = ntohs(skb->protocol) */
+ ctx->seen |= SEEN_SKB;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+ protocol) != 2);
+ off = offsetof(struct sk_buff, protocol);
+ emit(ARM_LDRH_I(r_scratch, r_skb, off), ctx);
+ emit_swap16(r_A, r_scratch, ctx);
+ break;
+ case BPF_S_ANC_CPU:
+ /* r_scratch = current_thread_info() */
+ OP_IMM3(ARM_BIC, r_scratch, ARM_SP, THREAD_SIZE - 1, ctx);
+ /* A = current_thread_info()->cpu */
+ BUILD_BUG_ON(FIELD_SIZEOF(struct thread_info, cpu) != 4);
+ off = offsetof(struct thread_info, cpu);
+ emit(ARM_LDR_I(r_A, r_scratch, off), ctx);
+ break;
+ case BPF_S_ANC_IFINDEX:
+ /* A = skb->dev->ifindex */
+ ctx->seen |= SEEN_SKB;
+ off = offsetof(struct sk_buff, dev);
+ emit(ARM_LDR_I(r_scratch, r_skb, off), ctx);
+
+ emit(ARM_CMP_I(r_scratch, 0), ctx);
+ emit_err_ret(ARM_COND_EQ, ctx);
+
+ BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+ ifindex) != 4);
+ off = offsetof(struct net_device, ifindex);
+ emit(ARM_LDR_I(r_A, r_scratch, off), ctx);
+ break;
+ case BPF_S_ANC_MARK:
+ ctx->seen |= SEEN_SKB;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+ off = offsetof(struct sk_buff, mark);
+ emit(ARM_LDR_I(r_A, r_skb, off), ctx);
+ break;
+ case BPF_S_ANC_RXHASH:
+ ctx->seen |= SEEN_SKB;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
+ off = offsetof(struct sk_buff, rxhash);
+ emit(ARM_LDR_I(r_A, r_skb, off), ctx);
+ break;
+ case BPF_S_ANC_QUEUE:
+ ctx->seen |= SEEN_SKB;
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+ queue_mapping) != 2);
+ BUILD_BUG_ON(offsetof(struct sk_buff,
+ queue_mapping) > 0xff);
+ off = offsetof(struct sk_buff, queue_mapping);
+ emit(ARM_LDRH_I(r_A, r_skb, off), ctx);
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ /* compute offsets only during the first pass */
+ if (ctx->target == NULL)
+ ctx->offsets[i] = ctx->idx * 4;
+
+ return 0;
+}
+
+
+void bpf_jit_compile(struct sk_filter *fp)
+{
+ struct jit_ctx ctx;
+ unsigned tmp_idx;
+ unsigned alloc_size;
+
+ if (!bpf_jit_enable)
+ return;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.skf = fp;
+ ctx.ret0_fp_idx = -1;
+
+ ctx.offsets = kzalloc(GFP_KERNEL, 4 * (ctx.skf->len + 1));
+ if (ctx.offsets == NULL)
+ return;
+
+ /* fake pass to fill in the ctx->seen */
+ if (unlikely(build_body(&ctx)))
+ goto out;
+
+ tmp_idx = ctx.idx;
+ build_prologue(&ctx);
+ ctx.prologue_bytes = (ctx.idx - tmp_idx) * 4;
+
+#if __LINUX_ARM_ARCH__ < 7
+ tmp_idx = ctx.idx;
+ build_epilogue(&ctx);
+ ctx.epilogue_bytes = (ctx.idx - tmp_idx) * 4;
+
+ ctx.idx += ctx.imm_count;
+ if (ctx.imm_count) {
+ ctx.imms = kzalloc(GFP_KERNEL, 4 * ctx.imm_count);
+ if (ctx.imms == NULL)
+ goto out;
+ }
+#else
+ /* there's nothing after the epilogue on ARMv7 */
+ build_epilogue(&ctx);
+#endif
+
+ alloc_size = 4 * ctx.idx;
+ ctx.target = module_alloc(max(sizeof(struct work_struct),
+ alloc_size));
+ if (unlikely(ctx.target == NULL))
+ goto out;
+
+ ctx.idx = 0;
+ build_prologue(&ctx);
+ build_body(&ctx);
+ build_epilogue(&ctx);
+
+ flush_icache_range((u32)ctx.target, (u32)(ctx.target + ctx.idx));
+
+#if __LINUX_ARM_ARCH__ < 7
+ if (ctx.imm_count)
+ kfree(ctx.imms);
+#endif
+
+ if (bpf_jit_enable > 1)
+ print_hex_dump(KERN_INFO, "BPF JIT code: ",
+ DUMP_PREFIX_ADDRESS, 16, 4, ctx.target,
+ alloc_size, false);
+
+ fp->bpf_func = (void *)ctx.target;
+out:
+ kfree(ctx.offsets);
+ return;
+}
+
+static void bpf_jit_free_worker(struct work_struct *work)
+{
+ module_free(NULL, work);
+}
+
+void bpf_jit_free(struct sk_filter *fp)
+{
+ struct work_struct *work;
+
+ if (fp->bpf_func != sk_run_filter) {
+ work = (struct work_struct *)fp->bpf_func;
+
+ INIT_WORK(work, bpf_jit_free_worker);
+ schedule_work(work);
+ }
+}
+
diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h
new file mode 100644
index 0000000..99ae5e3
--- /dev/null
+++ b/arch/arm/net/bpf_jit_32.h
@@ -0,0 +1,190 @@
+/*
+ * Just-In-Time compiler for BPF filters on 32bit ARM
+ *
+ * Copyright (c) 2011 Mircea Gherzan <mgherzan@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#ifndef PFILTER_OPCODES_ARM_H
+#define PFILTER_OPCODES_ARM_H
+
+#define ARM_R0 0
+#define ARM_R1 1
+#define ARM_R2 2
+#define ARM_R3 3
+#define ARM_R4 4
+#define ARM_R5 5
+#define ARM_R6 6
+#define ARM_R7 7
+#define ARM_R8 8
+#define ARM_R9 9
+#define ARM_R10 10
+#define ARM_FP 11
+#define ARM_IP 12
+#define ARM_SP 13
+#define ARM_LR 14
+#define ARM_PC 15
+
+#define ARM_COND_EQ 0x0
+#define ARM_COND_NE 0x1
+#define ARM_COND_CS 0x2
+#define ARM_COND_HS ARM_COND_CS
+#define ARM_COND_CC 0x3
+#define ARM_COND_LO ARM_COND_CC
+#define ARM_COND_MI 0x4
+#define ARM_COND_PL 0x5
+#define ARM_COND_VS 0x6
+#define ARM_COND_VC 0x7
+#define ARM_COND_HI 0x8
+#define ARM_COND_LS 0x9
+#define ARM_COND_GE 0xa
+#define ARM_COND_LT 0xb
+#define ARM_COND_GT 0xc
+#define ARM_COND_LE 0xd
+#define ARM_COND_AL 0xe
+
+/* register shift types */
+#define SRTYPE_LSL 0
+#define SRTYPE_LSR 1
+#define SRTYPE_ASR 2
+#define SRTYPE_ROR 3
+
+#define ARM_INST_ADD_R 0x00800000
+#define ARM_INST_ADD_I 0x02800000
+
+#define ARM_INST_AND_R 0x00000000
+#define ARM_INST_AND_I 0x02000000
+
+#define ARM_INST_BIC_R 0x01c00000
+#define ARM_INST_BIC_I 0x03c00000
+
+#define ARM_INST_B 0x0a000000
+#define ARM_INST_BX 0x012FFF10
+#define ARM_INST_BLX_R 0x012fff30
+
+#define ARM_INST_CMP_R 0x01500000
+#define ARM_INST_CMP_I 0x03500000
+
+#define ARM_INST_LDRB_I 0x05d00000
+#define ARM_INST_LDRB_R 0x07d00000
+#define ARM_INST_LDRH_I 0x01d000b0
+#define ARM_INST_LDR_I 0x05900000
+
+#define ARM_INST_LDM 0x08900000
+
+#define ARM_INST_LSL_I 0x01a00000
+#define ARM_INST_LSL_R 0x01a00010
+
+#define ARM_INST_LSR_I 0x01a00020
+#define ARM_INST_LSR_R 0x01a00030
+
+#define ARM_INST_MOV_R 0x01a00000
+#define ARM_INST_MOV_I 0x03a00000
+#define ARM_INST_MOVW 0x03000000
+#define ARM_INST_MOVT 0x03400000
+
+#define ARM_INST_MUL 0x00000090
+
+#define ARM_INST_POP 0x08bd0000
+#define ARM_INST_PUSH 0x092d0000
+
+#define ARM_INST_ORR_R 0x01800000
+#define ARM_INST_ORR_I 0x03800000
+
+#define ARM_INST_REV 0x06bf0f30
+#define ARM_INST_REV16 0x06bf0fb0
+
+#define ARM_INST_RSB_I 0x02600000
+
+#define ARM_INST_SUB_R 0x00400000
+#define ARM_INST_SUB_I 0x02400000
+
+#define ARM_INST_STR_I 0x05800000
+
+#define ARM_INST_TST_R 0x01100000
+#define ARM_INST_TST_I 0x03100000
+
+#define ARM_INST_UDIV 0x0730f010
+
+#define ARM_INST_UMULL 0x00800090
+
+/* register */
+#define _AL3_R(op, rd, rn, rm) ((op ## _R) | (rd) << 12 | (rn) << 16 | (rm))
+/* immediate */
+#define _AL3_I(op, rd, rn, imm) ((op ## _I) | (rd) << 12 | (rn) << 16 | (imm))
+
+#define ARM_ADD_R(rd, rn, rm) _AL3_R(ARM_INST_ADD, rd, rn, rm)
+#define ARM_ADD_I(rd, rn, imm) _AL3_I(ARM_INST_ADD, rd, rn, imm)
+
+#define ARM_AND_R(rd, rn, rm) _AL3_R(ARM_INST_AND, rd, rn, rm)
+#define ARM_AND_I(rd, rn, imm) _AL3_I(ARM_INST_AND, rd, rn, imm)
+
+#define ARM_BIC_R(rd, rn, rm) _AL3_R(ARM_INST_BIC, rd, rn, rm)
+#define ARM_BIC_I(rd, rn, imm) _AL3_I(ARM_INST_BIC, rd, rn, imm)
+
+#define ARM_B(imm24) (ARM_INST_B | ((imm24) & 0xffffff))
+#define ARM_BX(rm) (ARM_INST_BX | (rm))
+#define ARM_BLX_R(rm) (ARM_INST_BLX_R | (rm))
+
+#define ARM_CMP_R(rn, rm) _AL3_R(ARM_INST_CMP, 0, rn, rm)
+#define ARM_CMP_I(rn, imm) _AL3_I(ARM_INST_CMP, 0, rn, imm)
+
+#define ARM_LDR_I(rt, rn, off) (ARM_INST_LDR_I | (rt) << 12 | (rn) << 16 \
+ | (off))
+#define ARM_LDRB_I(rt, rn, off) (ARM_INST_LDRB_I | (rt) << 12 | (rn) << 16 \
+ | (off))
+#define ARM_LDRB_R(rt, rn, rm) (ARM_INST_LDRB_R | (rt) << 12 | (rn) << 16 \
+ | (rm))
+#define ARM_LDRH_I(rt, rn, off) (ARM_INST_LDRH_I | (rt) << 12 | (rn) << 16 \
+ | (((off) & 0xf0) << 4) | ((off) & 0xf))
+
+#define ARM_LDM(rn, regs) (ARM_INST_LDM | (rn) << 16 | (regs))
+
+#define ARM_LSL_R(rd, rn, rm) (_AL3_R(ARM_INST_LSL, rd, 0, rn) | (rm) << 8)
+#define ARM_LSL_I(rd, rn, imm) (_AL3_I(ARM_INST_LSL, rd, 0, rn) | (imm) << 7)
+
+#define ARM_LSR_R(rd, rn, rm) (_AL3_R(ARM_INST_LSR, rd, 0, rn) | (rm) << 8)
+#define ARM_LSR_I(rd, rn, imm) (_AL3_I(ARM_INST_LSR, rd, 0, rn) | (imm) << 7)
+
+#define ARM_MOV_R(rd, rm) _AL3_R(ARM_INST_MOV, rd, 0, rm)
+#define ARM_MOV_I(rd, imm) _AL3_I(ARM_INST_MOV, rd, 0, imm)
+
+#define ARM_MOVW(rd, imm) \
+ (ARM_INST_MOVW | ((imm) >> 12) << 16 | (rd) << 12 | ((imm) & 0x0fff))
+
+#define ARM_MOVT(rd, imm) \
+ (ARM_INST_MOVT | ((imm) >> 12) << 16 | (rd) << 12 | ((imm) & 0x0fff))
+
+#define ARM_MUL(rd, rm, rn) (ARM_INST_MUL | (rd) << 16 | (rm) << 8 | (rn))
+
+#define ARM_POP(regs) (ARM_INST_POP | (regs))
+#define ARM_PUSH(regs) (ARM_INST_PUSH | (regs))
+
+#define ARM_ORR_R(rd, rn, rm) _AL3_R(ARM_INST_ORR, rd, rn, rm)
+#define ARM_ORR_I(rd, rn, imm) _AL3_I(ARM_INST_ORR, rd, rn, imm)
+#define ARM_ORR_S(rd, rn, rm, type, rs) \
+ (ARM_ORR_R(rd, rn, rm) | (type) << 5 | (rs) << 7)
+
+#define ARM_REV(rd, rm) (ARM_INST_REV | (rd) << 12 | (rm))
+#define ARM_REV16(rd, rm) (ARM_INST_REV16 | (rd) << 12 | (rm))
+
+#define ARM_RSB_I(rd, rn, imm) _AL3_I(ARM_INST_RSB, rd, rn, imm)
+
+#define ARM_SUB_R(rd, rn, rm) _AL3_R(ARM_INST_SUB, rd, rn, rm)
+#define ARM_SUB_I(rd, rn, imm) _AL3_I(ARM_INST_SUB, rd, rn, imm)
+
+#define ARM_STR_I(rt, rn, off) (ARM_INST_STR_I | (rt) << 12 | (rn) << 16 \
+ | (off))
+
+#define ARM_TST_R(rn, rm) _AL3_R(ARM_INST_TST, 0, rn, rm)
+#define ARM_TST_I(rn, imm) _AL3_I(ARM_INST_TST, 0, rn, imm)
+
+#define ARM_UDIV(rd, rn, rm) (ARM_INST_UDIV | (rd) << 16 | (rn) | (rm) << 8)
+
+#define ARM_UMULL(rd_lo, rd_hi, rn, rm) (ARM_INST_UMULL | (rd_hi) << 16 \
+ | (rd_lo) << 12 | (rm) << 8 | rn)
+
+#endif /* PFILTER_OPCODES_ARM_H */
--
1.7.9.1
^ permalink raw reply related
* Re: [PATCH net-next] ethtool: Added a field fw dump_state
From: Anirban Chakraborty @ 2012-03-16 21:28 UTC (permalink / raw)
To: Eric Dumazet
Cc: Ben Hutchings, David Miller, netdev, Dept-NX Linux NIC Driver,
Manish Chopra
In-Reply-To: <1331932962.19406.23.camel@edumazet-glaptop>
On 3/16/12 2:22 PM, "Eric Dumazet" <eric.dumazet@gmail.com> wrote:
>On Fri, 2012-03-16 at 14:10 -0700, Anirban Chakraborty wrote:
>>
>> On 3/16/12 11:27 AM, "Ben Hutchings" <bhutchings@solarflare.com> wrote:
>>
>> >On Fri, 2012-03-16 at 10:58 -0700, Anirban Chakraborty wrote:
>> >> +
>> >> struct ethtool_dump {
>> >> __u32 cmd;
>> >> __u32 version;
>> >> __u32 flag;
>> >> __u32 len;
>> >> __u8 data[0];
>> >> + __u8 dump_state;
>> >
>> >Don't be ridiculous.
>>
>> Yeah I know, especially when there is a flag field already present
>>there.
>> The only
>> reason, we considered for adding it is to keep the backward
>>compatibility
>> of scripts.
>> Right now, the flag field sets/gets the dump level of fw. If we use it
>>to
>> control the
>> dump state, then it would break the existing scripts, if there are any.
>>
>
>You missed the point... data[0] must be the last element in the
>structure.
Yes, that was wrong struct. Sorry, I should have caught it earlier. We'll
resend it.
-Anirban
^ permalink raw reply
* Re: [PATCH v2 4/4] ath9k: Support ethtool getstats api.
From: Ben Greear @ 2012-03-16 21:26 UTC (permalink / raw)
To: Ben Hutchings
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1331931427.2504.12.camel-/LGg1Z1CJKReKY3V0RtoKmatzQS1i7+A3tAM5lWOD0I@public.gmane.org>
On 03/16/2012 01:57 PM, Ben Hutchings wrote:
> On Fri, 2012-03-16 at 20:53 +0000, Ben Hutchings wrote:
>> On Fri, 2012-03-16 at 12:59 -0700, greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org wrote:
>>> From: Ben Greear<greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
>>>
>>> This returns many of the values that formerly could
>>> only be obtained from debugfs. This should be an
>>> improvement when trying to access these counters
>>> programatically. Currently this support is only
>>> enabled when DEBUGFS is enabled because otherwise
>>> these stats are not accumulated.
>> [...]
>>
>> Given that ethtool (unlike debugfs) is itself an unconditional feature,
>> why not make this unconditional? Is it expensive to accumulate the
>> stats?
>>
>> Please at least fix the name.
> ^ config option
>
The ath9k stats are currently only gathered when debugfs is enabled.
I could do some patches in the future to allow stats to always
be gathered regardless of debugfs being enabled, but since
ath9k is used on small form factor systems, there may be some
resistance to enabling that all the time.
Thanks,
Ben
--
Ben Greear <greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
Candela Technologies Inc http://www.candelatech.com
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net-next] ethtool: Added a field fw dump_state
From: Eric Dumazet @ 2012-03-16 21:22 UTC (permalink / raw)
To: Anirban Chakraborty
Cc: Ben Hutchings, David Miller, netdev, Dept-NX Linux NIC Driver,
Manish Chopra
In-Reply-To: <CB88F67C.2A1CE%anirban.chakraborty@qlogic.com>
On Fri, 2012-03-16 at 14:10 -0700, Anirban Chakraborty wrote:
>
> On 3/16/12 11:27 AM, "Ben Hutchings" <bhutchings@solarflare.com> wrote:
>
> >On Fri, 2012-03-16 at 10:58 -0700, Anirban Chakraborty wrote:
> >> +
> >> struct ethtool_dump {
> >> __u32 cmd;
> >> __u32 version;
> >> __u32 flag;
> >> __u32 len;
> >> __u8 data[0];
> >> + __u8 dump_state;
> >
> >Don't be ridiculous.
>
> Yeah I know, especially when there is a flag field already present there.
> The only
> reason, we considered for adding it is to keep the backward compatibility
> of scripts.
> Right now, the flag field sets/gets the dump level of fw. If we use it to
> control the
> dump state, then it would break the existing scripts, if there are any.
>
You missed the point... data[0] must be the last element in the
structure.
^ permalink raw reply
* Re: pull request: wireless-next 2012-03-16
From: David Miller @ 2012-03-16 21:12 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20120316180428.GD2563@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Fri, 16 Mar 2012 14:04:29 -0400
> Yet another batch of updates intended for 3.4 -- they keep on
> coming! :-)
>
> Highlights here include a batch of ath6kl updates, a batch of mwifiex
> code cleanups, a number of mac80211 refactoring patches from Johannes,
> the usual level of activity around iwlwifi and ath9k, and a handful
> of updates to other drivers.
>
> Please let me know if there are problems!
Pulled, thanks John.
^ permalink raw reply
* Re: [PATCH net-next] ethtool: Added a field fw dump_state
From: Anirban Chakraborty @ 2012-03-16 21:10 UTC (permalink / raw)
To: Ben Hutchings
Cc: David Miller, netdev, Dept-NX Linux NIC Driver, Manish Chopra
In-Reply-To: <1331922456.2504.0.camel@bwh-desktop.uk.solarflarecom.com>
On 3/16/12 11:27 AM, "Ben Hutchings" <bhutchings@solarflare.com> wrote:
>On Fri, 2012-03-16 at 10:58 -0700, Anirban Chakraborty wrote:
>> From: Manish chopra <manish.chopra@qlogic.com>
>>
>> This field is added to enable/disable firmware dump.
>>
>> Signed-off-by: Manish chopra <manish.chopra@qlogic.com>
>> Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
>> ---
>> include/linux/ethtool.h | 7 +++++++
>> 1 files changed, 7 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
>> index e1d9e0e..6ebc7de 100644
>> --- a/include/linux/ethtool.h
>> +++ b/include/linux/ethtool.h
>> @@ -666,15 +666,22 @@ struct ethtool_flash {
>> * %ETHTOOL_GET_DUMP_DATA and this is returned as dump length by
>>driver
>> * for %ETHTOOL_GET_DUMP_FLAG command
>> * @data: data collected for get dump data operation
>> + * @dump_state: state of the firmware dump. which can be
>>enable/disable.
>> */
>> +
>> +#define ETH_FW_DUMP_ENABLE 1
>> +#define ETH_FW_DUMP_DISABLE 0
>> +
>> struct ethtool_dump {
>> __u32 cmd;
>> __u32 version;
>> __u32 flag;
>> __u32 len;
>> __u8 data[0];
>> + __u8 dump_state;
>
>Don't be ridiculous.
Yeah I know, especially when there is a flag field already present there.
The only
reason, we considered for adding it is to keep the backward compatibility
of scripts.
Right now, the flag field sets/gets the dump level of fw. If we use it to
control the
dump state, then it would break the existing scripts, if there are any.
-Anirban
^ permalink raw reply
* Re: [PATCH v8] ARM: net: JIT compiler for packet filters
From: David Miller @ 2012-03-16 20:54 UTC (permalink / raw)
To: mgherzan; +Cc: eric.dumazet, linux, linux-arm-kernel, netdev
In-Reply-To: <4F63A106.9060603@gmail.com>
From: Mircea Gherzan <mgherzan@gmail.com>
Date: Fri, 16 Mar 2012 21:22:30 +0100
> Am 16.03.2012 21:17, schrieb Eric Dumazet:
>> On Fri, 2012-03-16 at 20:41 +0100, Mircea Gherzan wrote:
>>
>>> Updated in the patch tracking system as 7259/3. Hopefully it's not too
>>> late for the inclusion in 3.4.
>>
>> What was the point of copy/pasting the whole mail ?
>
> I forgot to cc netdev in the first mail. Sorry.
That doesn't work, if you just quote the patch then it doesn't
get picked up by patchwork at all.
You have to make a real, fresh, patch postings for it to get
logged correctly.
^ permalink raw reply
* Re: [PATCH v2 4/4] ath9k: Support ethtool getstats api.
From: Ben Hutchings @ 2012-03-16 20:57 UTC (permalink / raw)
To: greearb; +Cc: linux-wireless, netdev
In-Reply-To: <1331931232.2504.9.camel@bwh-desktop.uk.solarflarecom.com>
On Fri, 2012-03-16 at 20:53 +0000, Ben Hutchings wrote:
> On Fri, 2012-03-16 at 12:59 -0700, greearb@candelatech.com wrote:
> > From: Ben Greear <greearb@candelatech.com>
> >
> > This returns many of the values that formerly could
> > only be obtained from debugfs. This should be an
> > improvement when trying to access these counters
> > programatically. Currently this support is only
> > enabled when DEBUGFS is enabled because otherwise
> > these stats are not accumulated.
> [...]
>
> Given that ethtool (unlike debugfs) is itself an unconditional feature,
> why not make this unconditional? Is it expensive to accumulate the
> stats?
>
> Please at least fix the name.
^ config option
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH v2 2/4] mac80211: Support getting sta_info stats via ethtool.
From: Ben Hutchings @ 2012-03-16 20:56 UTC (permalink / raw)
To: greearb-my8/4N5VtI7c+919tysfdA
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1331927952-8706-2-git-send-email-greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
On Fri, 2012-03-16 at 12:59 -0700, greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org wrote:
> From: Ben Greear <greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
>
> This lets ethtool print out stats related to station
> interfaces. Does not yet get stats from the underlying
> driver.
[...]
Nice.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
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