* [PATCH net-next v2 4/6] ppc: bpf: rename bpf_jit_64.S to bpf_jit_asm.S
From: Denis Kirjanov @ 2015-02-17 7:04 UTC (permalink / raw)
To: netdev; +Cc: linuxppc-dev, Denis Kirjanov
In-Reply-To: <1424156683-2682-1-git-send-email-kda@linux-powerpc.org>
Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
---
arch/powerpc/net/Makefile | 2 +-
arch/powerpc/net/{bpf_jit_64.S => bpf_jit_asm.S} | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename arch/powerpc/net/{bpf_jit_64.S => bpf_jit_asm.S} (100%)
diff --git a/arch/powerpc/net/Makefile b/arch/powerpc/net/Makefile
index 266b395..1306a58 100644
--- a/arch/powerpc/net/Makefile
+++ b/arch/powerpc/net/Makefile
@@ -1,4 +1,4 @@
#
# Arch-specific network modules
#
-obj-$(CONFIG_BPF_JIT) += bpf_jit_64.o bpf_jit_comp.o
+obj-$(CONFIG_BPF_JIT) += bpf_jit_asm.o bpf_jit_comp.o
diff --git a/arch/powerpc/net/bpf_jit_64.S b/arch/powerpc/net/bpf_jit_asm.S
similarity index 100%
rename from arch/powerpc/net/bpf_jit_64.S
rename to arch/powerpc/net/bpf_jit_asm.S
--
2.1.3
^ permalink raw reply related
* [PATCH net-next v2 5/6] ppc: bpf: Add SKF_AD_CPU for ppc32
From: Denis Kirjanov @ 2015-02-17 7:04 UTC (permalink / raw)
To: netdev; +Cc: linuxppc-dev, Denis Kirjanov
In-Reply-To: <1424156683-2682-1-git-send-email-kda@linux-powerpc.org>
Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
---
arch/powerpc/net/bpf_jit.h | 17 +++++++++++++++++
arch/powerpc/net/bpf_jit_comp.c | 14 +-------------
2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 2d5e715..889fd19 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -154,6 +154,23 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
#define PPC_LL_OFFS(r, base, i) do { PPC_LWZ_OFFS(r, base, i); } while(0)
#endif
+#ifdef CONFIG_SMP
+#ifdef CONFIG_PPC64
+#define PPC_BPF_LOAD_CPU(r) \
+ do { BUILD_BUG_ON(FIELD_SIZEOF(struct paca_struct, paca_index) != 2); \
+ PPC_LHZ_OFFS(r, 13, offsetof(struct paca_struct, paca_index)); \
+ } while (0)
+#else
+#define PPC_BPF_LOAD_CPU(r) \
+ do { BUILD_BUG_ON(FIELD_SIZEOF(struct thread_info, cpu) != 4); \
+ PPC_LHZ_OFFS(r, (1 & ~(THREAD_SIZE - 1)), \
+ offsetof(struct thread_info, cpu)); \
+ } while(0)
+#endif
+#else
+#define PPC_BPF_LOAD_CPU(r) do { PPC_LI(r, 0); } while(0)
+#endif
+
#define PPC_CMPWI(a, i) EMIT(PPC_INST_CMPWI | ___PPC_RA(a) | IMM_L(i))
#define PPC_CMPDI(a, i) EMIT(PPC_INST_CMPDI | ___PPC_RA(a) | IMM_L(i))
#define PPC_CMPLWI(a, i) EMIT(PPC_INST_CMPLWI | ___PPC_RA(a) | IMM_L(i))
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 8b29268..17cea18 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -411,20 +411,8 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
PPC_SRWI(r_A, r_A, 5);
break;
case BPF_ANC | SKF_AD_CPU:
-#ifdef CONFIG_SMP
- /*
- * PACA ptr is r13:
- * raw_smp_processor_id() = local_paca->paca_index
- */
- BUILD_BUG_ON(FIELD_SIZEOF(struct paca_struct,
- paca_index) != 2);
- PPC_LHZ_OFFS(r_A, 13,
- offsetof(struct paca_struct, paca_index));
-#else
- PPC_LI(r_A, 0);
-#endif
+ PPC_BPF_LOAD_CPU(r_A);
break;
-
/*** Absolute loads from packet header/data ***/
case BPF_LD | BPF_W | BPF_ABS:
func = CHOOSE_LOAD_FUNC(K, sk_load_word);
--
2.1.3
^ permalink raw reply related
* [PATCH net-next v2 6/6] ppc: Kconfig: Enable BPF JIT on ppc32
From: Denis Kirjanov @ 2015-02-17 7:04 UTC (permalink / raw)
To: netdev; +Cc: linuxppc-dev, Denis Kirjanov
In-Reply-To: <1424156683-2682-1-git-send-email-kda@linux-powerpc.org>
Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
---
arch/powerpc/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 22b0940..5084bdc 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -126,7 +126,7 @@ config PPC
select IRQ_FORCED_THREADING
select HAVE_RCU_TABLE_FREE if SMP
select HAVE_SYSCALL_TRACEPOINTS
- select HAVE_BPF_JIT if PPC64
+ select HAVE_BPF_JIT
select HAVE_ARCH_JUMP_LABEL
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_HAS_GCOV_PROFILE_ALL
--
2.1.3
^ permalink raw reply related
* Re: [PATCH] vhost: support upto 509 memory regions
From: Michael S. Tsirkin @ 2015-02-17 9:02 UTC (permalink / raw)
To: Igor Mammedov; +Cc: linux-kernel, kvm, netdev, pbonzini
In-Reply-To: <1423842599-5174-1-git-send-email-imammedo@redhat.com>
On Fri, Feb 13, 2015 at 03:49:59PM +0000, Igor Mammedov wrote:
> since commit
> 1d4e7e3 kvm: x86: increase user memory slots to 509
>
> it became possible to use a bigger amount of memory
> slots, which is used by memory hotplug for
> registering hotplugged memory.
> However QEMU aborts if it's used with more than ~60
> pc-dimm devices and vhost-net since host kernel
> in module vhost-net refuses to accept more than 65
> memory regions.
>
> Increasing VHOST_MEMORY_MAX_NREGIONS from 65 to 509
> to match KVM_USER_MEM_SLOTS fixes issue for vhost-net.
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
This scares me a bit: each region is 32byte, we are talking
a 16K allocation that userspace can trigger.
How does kvm handle this issue?
> ---
> drivers/vhost/vhost.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index 2ee2826..ecbd7a4 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -29,7 +29,7 @@
> #include "vhost.h"
>
> enum {
> - VHOST_MEMORY_MAX_NREGIONS = 64,
> + VHOST_MEMORY_MAX_NREGIONS = 509,
> VHOST_MEMORY_F_LOG = 0x1,
> };
>
> --
> 1.8.3.1
^ permalink raw reply
* Re: brcmsmac: TX power blocked in BCM4313
From: Nikita N. @ 2015-02-17 9:03 UTC (permalink / raw)
To: Arend van Spriel
Cc: hauke, brcm80211-dev-list, linux-wireless, Kalle Valo, Pat Erley,
brudley, Franky Lin, meuleman, linville, pieterpg, hdegoede, wens,
netdev, linux-kernel@vger.kernel.org
In-Reply-To: <54E24B48.80601@broadcom.com>
Hi Arend,
> brcmsmac does assure tx power is within regulatory limits by enforcing a
> world regulatory domain. So what is not supported is modifying tx power
> settings through user-space.
Yes, I believe that could be right, *a* world regulatory domain looks
indeed enforced, the USA one only, which is pre-set default inside
EEPROM registries device, isn't it?
> I know, but that driver is not fully open-source as it links in a binary
> blob.
AFAIK, also brcmsmac needs at least 2 firmware files to operate, without
those nothing works.
Isn't it the same concept?
> I totally lost track of this one. I am using brcmsmac in monitor mode
> using bcm43224 which captures 11n frames just fine. I will give it a try
> with a bcm4313. The assoc response in your capture shows undefined MCS
> set so maybe there really are no 11n MCS rates used (?).
If that was a suggestion about to purchase a bcm43224 or any other
Broadcom Corp. product, isn't really convincing, seen the overall
support quality Customers are experiencing in here...
About my capture file, in the case it was really incomplete someone
could have informed me at least a year ago.
But anyway no respectable QA Testing team needs a purchasing Customer to
help in verifying such enormous issue, isn't it?
> Our team consist of two man working full-time on the upstream linux
> drivers. So our "customer care" is something that we try to deal with on
> the side and admittedly things slip between the cracks.
Really, *TWO* men? Are you kidding? Is that how much Broadcom Corp.
values the Linux community?
Needles to remind, even if Linux users don't pay for the OS license as
Windows do, they do pay allright for any Broadcom hardware they
purchase!
Internet startups which sell a button on internet, they have Dev and QA
team 5 times bigger than that!
I sense a very gross capacity and resource planning competence issue in
here.
I kindly ask you, please forward that mail to your higher Managers, on
my personal behalf, Thanks.
--
http://www.fastmail.com - Same, same, but different...
^ permalink raw reply
* [PATCH] hso: always read interface number from the current altsetting
From: Aleksander Morgado @ 2015-02-17 10:31 UTC (permalink / raw)
To: j.dumon-x9gZzRpC1QbQT0dZR+AlfA
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
Aleksander Morgado
Always read bInterfaceNumber from the current altsetting, not from the first one
available in the altsetting array. This is coming from code review, not related
to any specific bug.
Signed-off-by: Aleksander Morgado <aleksander-Dvg4H30XQSRVIjRurl1/8g@public.gmane.org>
---
drivers/net/usb/hso.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 9cdfb3f..3c8dfe5 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1477,6 +1477,7 @@ static void tiocmget_intr_callback(struct urb *urb)
struct uart_icount *icount;
struct hso_serial_state_notification *serial_state_notification;
struct usb_device *usb;
+ struct usb_interface *interface;
int if_num;
/* Sanity checks */
@@ -1494,7 +1495,9 @@ static void tiocmget_intr_callback(struct urb *urb)
BUG_ON((serial->parent->port_spec & HSO_PORT_MASK) != HSO_PORT_MODEM);
usb = serial->parent->usb;
- if_num = serial->parent->interface->altsetting->desc.bInterfaceNumber;
+ interface = serial->parent->interface;
+
+ if_num = interface->cur_altsetting->desc.bInterfaceNumber;
/* wIndex should be the USB interface number of the port to which the
* notification applies, which should always be the Modem port.
@@ -1675,6 +1678,7 @@ static int hso_serial_tiocmset(struct tty_struct *tty,
unsigned long flags;
int if_num;
struct hso_serial *serial = tty->driver_data;
+ struct usb_interface *interface;
/* sanity check */
if (!serial) {
@@ -1685,7 +1689,8 @@ static int hso_serial_tiocmset(struct tty_struct *tty,
if ((serial->parent->port_spec & HSO_PORT_MASK) != HSO_PORT_MODEM)
return -EINVAL;
- if_num = serial->parent->interface->altsetting->desc.bInterfaceNumber;
+ interface = serial->parent->interface;
+ if_num = interface->cur_altsetting->desc.bInterfaceNumber;
spin_lock_irqsave(&serial->serial_lock, flags);
if (set & TIOCM_RTS)
@@ -2808,7 +2813,7 @@ static int hso_get_config_data(struct usb_interface *interface)
{
struct usb_device *usbdev = interface_to_usbdev(interface);
u8 *config_data = kmalloc(17, GFP_KERNEL);
- u32 if_num = interface->altsetting->desc.bInterfaceNumber;
+ u32 if_num = interface->cur_altsetting->desc.bInterfaceNumber;
s32 result;
if (!config_data)
@@ -2886,7 +2891,7 @@ static int hso_probe(struct usb_interface *interface,
return -ENODEV;
}
- if_num = interface->altsetting->desc.bInterfaceNumber;
+ if_num = interface->cur_altsetting->desc.bInterfaceNumber;
/* Get the interface/port specification from either driver_info or from
* the device itself */
--
2.3.0
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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 related
* [PATCH] ipv4: ip_check_defrag should correctly check return value of skb_copy_bits
From: Alexander Drozdov @ 2015-02-17 10:33 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy
Cc: netdev, linux-kernel, Alexander Drozdov
skb_copy_bits() returns zero on success and negative value on error,
so it is needed to invert the condition in ip_check_defrag().
Fixes: 1bf3751ec90c ("ipv4: ip_check_defrag must not modify skb before unsharing")
Signed-off-by: Alexander Drozdov <al.drozdov@gmail.com>
---
net/ipv4/ip_fragment.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index e5b6d0d..2c8d98e 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -664,7 +664,7 @@ struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
if (skb->protocol != htons(ETH_P_IP))
return skb;
- if (!skb_copy_bits(skb, 0, &iph, sizeof(iph)))
+ if (skb_copy_bits(skb, 0, &iph, sizeof(iph)) < 0)
return skb;
if (iph.ihl < 5 || iph.version != 4)
--
1.9.1
^ permalink raw reply related
* Re: [PATCH] vhost: support upto 509 memory regions
From: Paolo Bonzini @ 2015-02-17 10:59 UTC (permalink / raw)
To: Michael S. Tsirkin, Igor Mammedov; +Cc: linux-kernel, kvm, netdev
In-Reply-To: <20150217090242.GA20254@redhat.com>
On 17/02/2015 10:02, Michael S. Tsirkin wrote:
> > Increasing VHOST_MEMORY_MAX_NREGIONS from 65 to 509
> > to match KVM_USER_MEM_SLOTS fixes issue for vhost-net.
> >
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
>
> This scares me a bit: each region is 32byte, we are talking
> a 16K allocation that userspace can trigger.
What's bad with a 16K allocation?
> How does kvm handle this issue?
It doesn't.
Paolo
^ permalink raw reply
* Re: [PATCH] multicast: Extend ip address command to enable multicast group join/leave on IP level.
From: Eric Dumazet @ 2015-02-17 11:10 UTC (permalink / raw)
To: Madhu Challa; +Cc: netdev
In-Reply-To: <1424125238-4505-1-git-send-email-challa@noironetworks.com>
On Mon, 2015-02-16 at 14:20 -0800, Madhu Challa wrote:
> Joining multicast group on ethernet level via "ip maddr" command would
> not work if we have an Ethernet switch that does igmp snooping since
> the switch would not replicate multicast packets on ports that did not
> have IGMP reports for the multicast addresses.
>
...
> +struct mc_autojoin_request {
> + union {
> + struct sockaddr_in sin;
> + struct sockaddr_in6 sin6;
> + } addr;
> + int ifindex;
> + struct sock *sk;
> + struct work_struct ipv4_work;
> + struct work_struct ipv6_work;
> + bool join;
> +};
This looks a net-next patch, right ?
You do not need 2 separate work_struct. A single one is enough, or even
no work queue at all as a matter of fact.
I'll send a preparation patch like this one, then you'll be able to call
__ip_mc_{join|leave}_group() directly while RTNL is held.
[PATCH net-next] igmp: add __ip_mc_{join|leave}_group()
There is a need to perform igmp join/leave operations while RTNL is
held. Make ip_mc_{join|leave}_group() wrappers around __ip_mc_{join|
leave}_group() to avoid the proliferation of work queues.
...
^ permalink raw reply
* [PATCH net-next] igmp: add __ip_mc_{join|leave}_group()
From: Eric Dumazet @ 2015-02-17 11:19 UTC (permalink / raw)
To: Madhu Challa, David Miller; +Cc: netdev
In-Reply-To: <1424125238-4505-1-git-send-email-challa@noironetworks.com>
From: Eric Dumazet <edumazet@google.com>
There is a need to perform igmp join/leave operations while RTNL is
held.
Make ip_mc_{join|leave}_group() wrappers around
__ip_mc_{join|leave}_group() to avoid the proliferation of work queues.
For example, vxlan_igmp_join() could possibly be removed.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/linux/igmp.h | 2 +
net/ipv4/igmp.c | 52 ++++++++++++++++++++++++++---------------
2 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 2c677afeea4782c96b79d0d8ede4846d87783b99..b5a6470e686c436f619ee086cbdfc3ece389db35 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -111,7 +111,9 @@ struct ip_mc_list {
extern int ip_check_mc_rcu(struct in_device *dev, __be32 mc_addr, __be32 src_addr, u16 proto);
extern int igmp_rcv(struct sk_buff *);
+extern int __ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
+extern int __ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
extern int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
extern void ip_mc_drop_socket(struct sock *sk);
extern int ip_mc_source(int add, int omode, struct sock *sk,
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 666cf364df86dffbab3cd2b7b1ea66e72d3ac7a8..4b1172d73e0309766d6d1a70473dd4c14d2c6fc0 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1849,30 +1849,25 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc)
pmc->sfcount[MCAST_EXCLUDE] = 1;
}
-
-/*
- * Join a multicast group
- */
-int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
+int __ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr)
{
- int err;
__be32 addr = imr->imr_multiaddr.s_addr;
- struct ip_mc_socklist *iml = NULL, *i;
+ struct ip_mc_socklist *iml, *i;
struct in_device *in_dev;
struct inet_sock *inet = inet_sk(sk);
struct net *net = sock_net(sk);
int ifindex;
int count = 0;
+ int err;
+
+ ASSERT_RTNL();
if (!ipv4_is_multicast(addr))
return -EINVAL;
- rtnl_lock();
-
in_dev = ip_mc_find_dev(net, imr);
if (!in_dev) {
- iml = NULL;
err = -ENODEV;
goto done;
}
@@ -1900,9 +1895,22 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
ip_mc_inc_group(in_dev, addr);
err = 0;
done:
- rtnl_unlock();
return err;
}
+EXPORT_SYMBOL(__ip_mc_join_group);
+
+/* Join a multicast group
+ */
+int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr)
+{
+ int ret;
+
+ rtnl_lock();
+ ret = __ip_mc_join_group(sk, imr);
+ rtnl_unlock();
+
+ return ret;
+}
EXPORT_SYMBOL(ip_mc_join_group);
static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
@@ -1925,11 +1933,7 @@ static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
return err;
}
-/*
- * Ask a socket to leave a group.
- */
-
-int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
+int __ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
{
struct inet_sock *inet = inet_sk(sk);
struct ip_mc_socklist *iml;
@@ -1940,7 +1944,8 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
u32 ifindex;
int ret = -EADDRNOTAVAIL;
- rtnl_lock();
+ ASSERT_RTNL();
+
in_dev = ip_mc_find_dev(net, imr);
if (!in_dev) {
ret = -ENODEV;
@@ -1964,14 +1969,25 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
*imlp = iml->next_rcu;
ip_mc_dec_group(in_dev, group);
- rtnl_unlock();
+
/* decrease mem now to avoid the memleak warning */
atomic_sub(sizeof(*iml), &sk->sk_omem_alloc);
kfree_rcu(iml, rcu);
return 0;
}
out:
+ return ret;
+}
+EXPORT_SYMBOL(__ip_mc_leave_group);
+
+int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
+{
+ int ret;
+
+ rtnl_lock();
+ ret = __ip_mc_leave_group(sk, imr);
rtnl_unlock();
+
return ret;
}
EXPORT_SYMBOL(ip_mc_leave_group);
^ permalink raw reply related
* [PATCH 3.12 065/122] lib/checksum.c: fix carry in csum_tcpudp_nofold
From: Jiri Slaby @ 2015-02-17 11:34 UTC (permalink / raw)
To: stable
Cc: linux-kernel, karl beldan, Karl Beldan, Al Viro, Eric Dumazet,
Arnd Bergmann, Mike Frysinger, netdev, Eric Dumazet,
David S. Miller, Jiri Slaby
In-Reply-To: <cover.1424099973.git.jslaby@suse.cz>
From: karl beldan <karl.beldan@gmail.com>
3.12-stable review patch. If anyone has any objections, please let me know.
===============
commit 150ae0e94634714b23919f0c333fee28a5b199d5 upstream.
The carry from the 64->32bits folding was dropped, e.g with:
saddr=0xFFFFFFFF daddr=0xFF0000FF len=0xFFFF proto=0 sum=1,
csum_tcpudp_nofold returned 0 instead of 1.
Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
lib/checksum.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/lib/checksum.c b/lib/checksum.c
index 129775eb6de6..fcf38943132c 100644
--- a/lib/checksum.c
+++ b/lib/checksum.c
@@ -47,6 +47,15 @@ static inline unsigned short from32to16(unsigned int x)
return x;
}
+static inline u32 from64to32(u64 x)
+{
+ /* add up 32-bit and 32-bit for 32+c bit */
+ x = (x & 0xffffffff) + (x >> 32);
+ /* add up carry.. */
+ x = (x & 0xffffffff) + (x >> 32);
+ return (u32)x;
+}
+
static unsigned int do_csum(const unsigned char *buff, int len)
{
int odd;
@@ -195,8 +204,7 @@ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
#else
s += (proto + len) << 8;
#endif
- s += (s >> 32);
- return (__force __wsum)s;
+ return (__force __wsum)from64to32(s);
}
EXPORT_SYMBOL(csum_tcpudp_nofold);
#endif
--
2.2.2
^ permalink raw reply related
* RE: [PATCH 3.12 065/122] lib/checksum.c: fix carry in csum_tcpudp_nofold
From: David Laight @ 2015-02-17 12:04 UTC (permalink / raw)
To: 'Jiri Slaby', stable@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, karl beldan, Karl Beldan, Al Viro,
Eric Dumazet, Arnd Bergmann, Mike Frysinger,
netdev@vger.kernel.org, Eric Dumazet, David S. Miller
In-Reply-To: <07707a797d6c3cd0bfe86f037d3d1eb329acbc86.1424099973.git.jslaby@suse.cz>
> +static inline u32 from64to32(u64 x)
> +{
> + /* add up 32-bit and 32-bit for 32+c bit */
> + x = (x & 0xffffffff) + (x >> 32);
> + /* add up carry.. */
> + x = (x & 0xffffffff) + (x >> 32);
> + return (u32)x;
> +}
As a matter of interest, does the compiler optimise away the
second (x & 0xffffffff) ?
The code could just be:
x = (x & 0xffffffff) + (x >> 32);
return x + (x >> 32);
David
^ permalink raw reply
* Re: [PATCH] batman-adv: Remove uses of return value of seq_printf
From: Antonio Quartulli @ 2015-02-17 12:15 UTC (permalink / raw)
To: Joe Perches, Marek Lindner; +Cc: b.a.t.m.a.n, netdev, LKML
In-Reply-To: <1424136699.8287.10.camel@perches.com>
[-- Attachment #1: Type: text/plain, Size: 380 bytes --]
Hi Joe,
thank you very much for this patch.
On 17/02/15 02:31, Joe Perches wrote:
> This function is soon going to return void so remove the
> return value use.
>
> Convert the return value to test seq_has_overflowed() instead.
>
> Signed-off-by: Joe Perches <joe@perches.com>
Acked-by: Antonio Quartulli <antonio@meshcoding.com>
--
Antonio Quartulli
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* Re: [PATCH] vhost: support upto 509 memory regions
From: Michael S. Tsirkin @ 2015-02-17 12:32 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Igor Mammedov, linux-kernel, kvm, netdev
In-Reply-To: <54E31F24.1060705@redhat.com>
On Tue, Feb 17, 2015 at 11:59:48AM +0100, Paolo Bonzini wrote:
>
>
> On 17/02/2015 10:02, Michael S. Tsirkin wrote:
> > > Increasing VHOST_MEMORY_MAX_NREGIONS from 65 to 509
> > > to match KVM_USER_MEM_SLOTS fixes issue for vhost-net.
> > >
> > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> >
> > This scares me a bit: each region is 32byte, we are talking
> > a 16K allocation that userspace can trigger.
>
> What's bad with a 16K allocation?
It fails when memory is fragmented.
> > How does kvm handle this issue?
>
> It doesn't.
>
> Paolo
I'm guessing kvm doesn't do memory scans on data path,
vhost does.
qemu is just doing things that kernel didn't expect it to need.
Instead, I suggest reducing number of GPA<->HVA mappings:
you have GPA 1,5,7
map them at HVA 11,15,17
then you can have 1 slot: 1->11
To avoid libc reusing the memory holes, reserve them with MAP_NORESERVE
or something like this.
We can discuss smarter lookup algorithms but I'd rather
userspace didn't do things that we then have to
work around in kernel.
--
MST
^ permalink raw reply
* Re: [PATCH] batman-adv: Remove uses of return value of seq_printf
From: Antonio Quartulli @ 2015-02-17 12:15 UTC (permalink / raw)
To: Joe Perches, Marek Lindner; +Cc: b.a.t.m.a.n, netdev, LKML
In-Reply-To: <1424136699.8287.10.camel@perches.com>
[-- Attachment #1: Type: text/plain, Size: 380 bytes --]
Hi Joe,
thank you very much for this patch.
On 17/02/15 02:31, Joe Perches wrote:
> This function is soon going to return void so remove the
> return value use.
>
> Convert the return value to test seq_has_overflowed() instead.
>
> Signed-off-by: Joe Perches <joe@perches.com>
Acked-by: Antonio Quartulli <antonio@meshcoding.com>
--
Antonio Quartulli
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* Re: [PATCH] vhost: support upto 509 memory regions
From: Paolo Bonzini @ 2015-02-17 13:11 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: Igor Mammedov, linux-kernel, kvm, netdev
In-Reply-To: <20150217123212.GA6362@redhat.com>
On 17/02/2015 13:32, Michael S. Tsirkin wrote:
> On Tue, Feb 17, 2015 at 11:59:48AM +0100, Paolo Bonzini wrote:
>>
>>
>> On 17/02/2015 10:02, Michael S. Tsirkin wrote:
>>>> Increasing VHOST_MEMORY_MAX_NREGIONS from 65 to 509
>>>> to match KVM_USER_MEM_SLOTS fixes issue for vhost-net.
>>>>
>>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
>>>
>>> This scares me a bit: each region is 32byte, we are talking
>>> a 16K allocation that userspace can trigger.
>>
>> What's bad with a 16K allocation?
>
> It fails when memory is fragmented.
If memory is _that_ fragmented I think you have much bigger problems
than vhost.
> I'm guessing kvm doesn't do memory scans on data path, vhost does.
It does for MMIO memory-to-memory writes, but that's not a particularly
fast path.
KVM doesn't access the memory map on fast paths, but QEMU does, so I
don't think it's beyond the expectations of the kernel. For example you
can use a radix tree (not lib/radix-tree.c unfortunately), and cache
GVA->HPA translations if it turns out that lookup has become a hot path.
The addressing space of x86 is in practice 44 bits or fewer, and each
slot will typically be at least 1 GiB, so you only have 14 bits to
dispatch on. It's probably possible to only have two or three levels
in the radix tree in the common case, and beat the linear scan real quick.
The radix tree can be tuned to use order-0 allocations, and then your
worries about fragmentation go away too.
Paolo
^ permalink raw reply
* Re: [PATCH] vhost: support upto 509 memory regions
From: Michael S. Tsirkin @ 2015-02-17 13:29 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Igor Mammedov, linux-kernel, kvm, netdev
In-Reply-To: <54E33E09.5090603@redhat.com>
On Tue, Feb 17, 2015 at 02:11:37PM +0100, Paolo Bonzini wrote:
>
>
> On 17/02/2015 13:32, Michael S. Tsirkin wrote:
> > On Tue, Feb 17, 2015 at 11:59:48AM +0100, Paolo Bonzini wrote:
> >>
> >>
> >> On 17/02/2015 10:02, Michael S. Tsirkin wrote:
> >>>> Increasing VHOST_MEMORY_MAX_NREGIONS from 65 to 509
> >>>> to match KVM_USER_MEM_SLOTS fixes issue for vhost-net.
> >>>>
> >>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> >>>
> >>> This scares me a bit: each region is 32byte, we are talking
> >>> a 16K allocation that userspace can trigger.
> >>
> >> What's bad with a 16K allocation?
> >
> > It fails when memory is fragmented.
>
> If memory is _that_ fragmented I think you have much bigger problems
> than vhost.
>
> > I'm guessing kvm doesn't do memory scans on data path, vhost does.
>
> It does for MMIO memory-to-memory writes, but that's not a particularly
> fast path.
>
> KVM doesn't access the memory map on fast paths, but QEMU does, so I
> don't think it's beyond the expectations of the kernel.
QEMU has an elaborate data structure to deal with that.
> For example you
> can use a radix tree (not lib/radix-tree.c unfortunately), and cache
> GVA->HPA translations if it turns out that lookup has become a hot path.
All vhost lookups are hot path.
> The addressing space of x86 is in practice 44 bits or fewer, and each
> slot will typically be at least 1 GiB, so you only have 14 bits to
> dispatch on. It's probably possible to only have two or three levels
> in the radix tree in the common case, and beat the linear scan real quick.
Not if there are about 6 regions, I think.
> The radix tree can be tuned to use order-0 allocations, and then your
> worries about fragmentation go away too.
>
> Paolo
Increasing the number might be reasonable for workloads such as nested
virt. But depending on this in userspace when you don't have to is not a
good idea IMHO.
--
MST
^ permalink raw reply
* Re: [PATCH] ipv4: ip_check_defrag should correctly check return value of skb_copy_bits
From: Denis Kirjanov @ 2015-02-17 13:33 UTC (permalink / raw)
To: Alexander Drozdov
Cc: David S. Miller, Alexey Kuznetsov, James Morris,
Hideaki YOSHIFUJI, Patrick McHardy, netdev, linux-kernel
In-Reply-To: <1424169226-30112-1-git-send-email-al.drozdov@gmail.com>
On 2/17/15, Alexander Drozdov <al.drozdov@gmail.com> wrote:
> skb_copy_bits() returns zero on success and negative value on error,
> so it is needed to invert the condition in ip_check_defrag().
>
Nice. Grepping through the net directory shows that the skb_copy_bits()
return value is completely ignored in net/wireless/util.c
> Fixes: 1bf3751ec90c ("ipv4: ip_check_defrag must not modify skb before
> unsharing")
> Signed-off-by: Alexander Drozdov <al.drozdov@gmail.com>
> ---
> net/ipv4/ip_fragment.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
> index e5b6d0d..2c8d98e 100644
> --- a/net/ipv4/ip_fragment.c
> +++ b/net/ipv4/ip_fragment.c
> @@ -664,7 +664,7 @@ struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32
> user)
> if (skb->protocol != htons(ETH_P_IP))
> return skb;
>
> - if (!skb_copy_bits(skb, 0, &iph, sizeof(iph)))
> + if (skb_copy_bits(skb, 0, &iph, sizeof(iph)) < 0)
> return skb;
>
> if (iph.ihl < 5 || iph.version != 4)
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH v2 0/3] net: Linn Ethernet Packet Sniffer driver
From: Stathis Voukelatos @ 2015-02-17 14:03 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
Cc: abrestic-F7+t8E8rja9g9hUCZPvPmw, Stathis Voukelatos
This patch adds support the Ethernet Packet Sniffer H/W module
developed by Linn Products Ltd and found in the IMG Pistachio SoC.
The module allows Ethernet packets to be parsed, matched against
a user-defined pattern and timestamped. It sits between a 100M
Ethernet MAC and PHY and is completely passive with respect to
Ethernet frames.
Matched packet bytes and timestamp values are returned through a
FIFO. Timestamps are provided to the module through an externally
generated Gray-encoded counter.
The command string for packet matching is stored in module RAM
and consists of a sequence of 16-bit entries. Each entry includes
an 8-bit command code and and 8-bit data value. Valid command
codes are:
0 - Don't care
1 - Match: packet data must match command string byte
2 - Copy: packet data will be copied to FIFO
3 - Match/Stamp: if packet data matches string byte, a timestamp
is copied into the FIFO
4 - Copy/Done: packet data will be copied into the FIFO.
This command terminates the command string.
The driver consists of two modules:
- Core: it provides a common framework for managing backend packet
sniffer implementations. Each backend channel is registered
by the core as a netdev, which can be accessed from user
space through a raw packet socket.
- Ethernet Packet Sniffer backend: provides the driver for the
Linn Ethernet Packet Sniffer H/W modules.
The split between a core and backend modules allows for other
implementations to be added in the future apart of the Ethernet
packet sniffer presented in this patch set.
Changes:
v2:
* Complete redesign of core framework to use netdev instead of
the generic netlink framework
* Updated device tree binding
* A number of minor code improvements suggested by code review
Stathis Voukelatos (3):
Ethernet packet sniffer: Device tree binding and vendor prefix
Packet sniffer core framework
Linn Ethernet packet sniffer driver
.../bindings/net/linn-ether-packet-sniffer.txt | 42 +++
.../devicetree/bindings/vendor-prefixes.txt | 1 +
MAINTAINERS | 6 +
drivers/net/Kconfig | 2 +
drivers/net/Makefile | 2 +
drivers/net/pkt-sniffer/Kconfig | 19 +
drivers/net/pkt-sniffer/Makefile | 7 +
drivers/net/pkt-sniffer/backends/ether/channel.c | 392 +++++++++++++++++++++
drivers/net/pkt-sniffer/backends/ether/channel.h | 81 +++++
drivers/net/pkt-sniffer/backends/ether/hw.h | 46 +++
drivers/net/pkt-sniffer/backends/ether/platform.c | 301 ++++++++++++++++
drivers/net/pkt-sniffer/core/module.c | 37 ++
drivers/net/pkt-sniffer/core/netdev.c | 254 +++++++++++++
drivers/net/pkt-sniffer/core/snf_core.h | 60 ++++
include/uapi/linux/pkt_sniffer.h | 33 ++
15 files changed, 1283 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/linn-ether-packet-sniffer.txt
create mode 100644 drivers/net/pkt-sniffer/Kconfig
create mode 100644 drivers/net/pkt-sniffer/Makefile
create mode 100644 drivers/net/pkt-sniffer/backends/ether/channel.c
create mode 100644 drivers/net/pkt-sniffer/backends/ether/channel.h
create mode 100644 drivers/net/pkt-sniffer/backends/ether/hw.h
create mode 100644 drivers/net/pkt-sniffer/backends/ether/platform.c
create mode 100644 drivers/net/pkt-sniffer/core/module.c
create mode 100644 drivers/net/pkt-sniffer/core/netdev.c
create mode 100644 drivers/net/pkt-sniffer/core/snf_core.h
create mode 100644 include/uapi/linux/pkt_sniffer.h
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 1/3] Ethernet packet sniffer: Device tree binding and vendor prefix
From: Stathis Voukelatos @ 2015-02-17 14:03 UTC (permalink / raw)
To: linux-kernel, devicetree, netdev; +Cc: abrestic, Stathis Voukelatos
In-Reply-To: <cover.1424181053.git.stathis.voukelatos@linn.co.uk>
Signed-off-by: Stathis Voukelatos <stathis.voukelatos@linn.co.uk>
---
.../bindings/net/linn-ether-packet-sniffer.txt | 42 ++++++++++++++++++++++
.../devicetree/bindings/vendor-prefixes.txt | 1 +
2 files changed, 43 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/linn-ether-packet-sniffer.txt
diff --git a/Documentation/devicetree/bindings/net/linn-ether-packet-sniffer.txt b/Documentation/devicetree/bindings/net/linn-ether-packet-sniffer.txt
new file mode 100644
index 0000000..74bac5e
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/linn-ether-packet-sniffer.txt
@@ -0,0 +1,42 @@
+* Linn Products Ethernet Packet Sniffer
+The module allows Ethernet packets to be parsed, matched against
+a user-defined pattern and timestamped. It sits between a 100M
+Ethernet MAC and PHY and is completely passive with respect to
+Ethernet frames.
+Matched packet bytes and timestamp values are returned through a
+FIFO. Timestamps are provided to the module through an externally
+generated Gray-encoded counter.
+
+Required properties:
+- compatible : must be "linn,eth-sniffer"
+- reg : physical addresses and sizes of registers. Must contain 3 entries:
+ - registers memory space
+ - TX command string memory
+ - RX command string memory
+- reg-names : must contain the following 3 entries:
+ "regs", "tx-ram", "rx-ram"
+- interrupts : sniffer interrupt specifier
+- clocks : specify the system clock for the peripheral and
+ the enable clock for the timestamp counter
+- clock-names : must contain the "sys" and "tstamp" entries
+- fifo-block-words : number of words in one data FIFO entry
+- tstamp-hz : frequency of the timestamp counter
+- tstamp-shift : shift value for the timestamp cyclecounter struct
+- tstamp-bits : width in bits of the timestamp counter
+
+Example:
+
+sniffer@1814a000 {
+ compatible = "linn,eth-sniffer";
+ reg = <0x1814a000 0x100>, <0x1814a400 0x400>,
+ <0x1814a800 0x400>;
+ reg-names = "regs", "tx-ram", "rx-ram";
+ interrupts = <GIC_SHARED 58 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_core CLK_AUDIO>,
+ <&cr_periph SYS_CLK_EVENT_TIMER>;
+ clock-names = "sys", "tstamp";
+ fifo-block-words = <4>;
+ tstamp-hz = <52000000>;
+ tstamp-shift = <27>;
+ tstamp-bits = <30>;
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index d443279..891c224 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -90,6 +90,7 @@ lacie LaCie
lantiq Lantiq Semiconductor
lenovo Lenovo Group Ltd.
lg LG Corporation
+linn Linn Products Ltd.
linux Linux-specific binding
lsi LSI Corp. (LSI Logic)
lltc Linear Technology Corporation
--
1.9.1
^ permalink raw reply related
* [PATCH v2 2/3] Packet sniffer core framework
From: Stathis Voukelatos @ 2015-02-17 14:03 UTC (permalink / raw)
To: linux-kernel, devicetree, netdev; +Cc: abrestic, Stathis Voukelatos
In-Reply-To: <cover.1424181053.git.stathis.voukelatos@linn.co.uk>
The framework registers each backend sniffer channel as a netdev,
which can be accessed from user space through a raw packet socket.
Packets received from user space are treated as a command string
configuration. Each match event from the backend driver will
generate a packet with the matching bytes plus an optional
timestamp, if configured by the command string.
Signed-off-by: Stathis Voukelatos <stathis.voukelatos@linn.co.uk>
---
MAINTAINERS | 6 +
drivers/net/Kconfig | 2 +
drivers/net/Makefile | 2 +
drivers/net/pkt-sniffer/Kconfig | 8 +
drivers/net/pkt-sniffer/Makefile | 3 +
drivers/net/pkt-sniffer/core/module.c | 37 +++++
drivers/net/pkt-sniffer/core/netdev.c | 254 ++++++++++++++++++++++++++++++++
drivers/net/pkt-sniffer/core/snf_core.h | 60 ++++++++
include/uapi/linux/pkt_sniffer.h | 33 +++++
9 files changed, 405 insertions(+)
create mode 100644 drivers/net/pkt-sniffer/Kconfig
create mode 100644 drivers/net/pkt-sniffer/Makefile
create mode 100644 drivers/net/pkt-sniffer/core/module.c
create mode 100644 drivers/net/pkt-sniffer/core/netdev.c
create mode 100644 drivers/net/pkt-sniffer/core/snf_core.h
create mode 100644 include/uapi/linux/pkt_sniffer.h
diff --git a/MAINTAINERS b/MAINTAINERS
index aaa039d..7d882de 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5754,6 +5754,12 @@ M: Sasha Levin <sasha.levin@oracle.com>
S: Maintained
F: tools/lib/lockdep/
+LINN PACKET SNIFFER DRIVER
+M: Stathis Voukelatos <stathis.voukelatos@linn.co.uk>
+S: Maintained
+F: drivers/net/pkt-sniffer/
+F: Documentation/devicetree/bindings/net/linn-ether-packet-sniffer.txt
+
LINUX FOR IBM pSERIES (RS/6000)
M: Paul Mackerras <paulus@au.ibm.com>
W: http://www.ibm.com/linux/ltc/projects/ppc
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index d6607ee..219c786 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -380,4 +380,6 @@ config VMXNET3
source "drivers/net/hyperv/Kconfig"
+source "drivers/net/pkt-sniffer/Kconfig"
+
endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index e25fdd7..56ed84e 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -66,3 +66,5 @@ obj-$(CONFIG_USB_NET_DRIVERS) += usb/
obj-$(CONFIG_HYPERV_NET) += hyperv/
obj-$(CONFIG_NTB_NETDEV) += ntb_netdev.o
+obj-$(CONFIG_PKT_SNIFFER) += pkt-sniffer/
+
diff --git a/drivers/net/pkt-sniffer/Kconfig b/drivers/net/pkt-sniffer/Kconfig
new file mode 100644
index 0000000..53ffcc1
--- /dev/null
+++ b/drivers/net/pkt-sniffer/Kconfig
@@ -0,0 +1,8 @@
+menuconfig PKT_SNIFFER
+ tristate "Packet sniffer support"
+ ---help---
+ Say Y to add support for the packet sniffer driver framework.
+
+ The core driver can also be built as a module. If so, the module
+ will be called snf_core.
+
diff --git a/drivers/net/pkt-sniffer/Makefile b/drivers/net/pkt-sniffer/Makefile
new file mode 100644
index 0000000..31dc396
--- /dev/null
+++ b/drivers/net/pkt-sniffer/Makefile
@@ -0,0 +1,3 @@
+snf_core-y += core/netdev.o
+snf_core-y += core/module.o
+obj-$(CONFIG_PKT_SNIFFER) += snf_core.o
diff --git a/drivers/net/pkt-sniffer/core/module.c b/drivers/net/pkt-sniffer/core/module.c
new file mode 100644
index 0000000..1dbed1f
--- /dev/null
+++ b/drivers/net/pkt-sniffer/core/module.c
@@ -0,0 +1,37 @@
+/*
+ * Packet sniffer core driver:
+ * - backend channel management
+ * - interface to userland as a network I/F
+ *
+ * Copyright (C) 2015 Linn Products Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Written by:
+ * Stathis Voukelatos <stathis.voukelatos@linn.co.uk>
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+
+static int __init snf_core_init(void)
+{
+ return 0;
+}
+
+static void __exit snf_core_cleanup(void)
+{
+}
+
+module_init(snf_core_init);
+module_exit(snf_core_cleanup);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Core packet sniffer driver");
+MODULE_AUTHOR("Linn Products Ltd");
diff --git a/drivers/net/pkt-sniffer/core/netdev.c b/drivers/net/pkt-sniffer/core/netdev.c
new file mode 100644
index 0000000..ba25cc0
--- /dev/null
+++ b/drivers/net/pkt-sniffer/core/netdev.c
@@ -0,0 +1,254 @@
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/net_tstamp.h>
+#include <linux/if_arp.h>
+#include <linux/spinlock.h>
+#include "snf_core.h"
+
+struct snf_ndev_state {
+ struct snf_chan *chan;
+ bool rx_tstamp_enabled;
+ spinlock_t lock;
+};
+
+static int hw_timestamp_set(struct net_device *dev, struct ifreq *ifr)
+{
+ struct snf_ndev_state *priv = netdev_priv(dev);
+ struct hwtstamp_config tconf;
+
+ if (copy_from_user(&tconf, ifr->ifr_data, sizeof(tconf)))
+ return -EFAULT;
+
+ /* No TX timestamping supported.
+ * This interface only receives packets from the sniffer backend
+ */
+ if (tconf.tx_type != HWTSTAMP_TX_OFF)
+ return -ERANGE;
+
+ if (tconf.rx_filter != HWTSTAMP_FILTER_NONE) {
+ /* If timestamping is not enabled in the command string then
+ * we cannot return any RX timestamps
+ */
+ if (!priv->chan->ts_enabled(priv->chan))
+ return -ERANGE;
+ priv->rx_tstamp_enabled = true;
+ tconf.rx_filter = HWTSTAMP_FILTER_ALL;
+ } else {
+ priv->rx_tstamp_enabled = false;
+ }
+
+ return copy_to_user(ifr->ifr_data, &tconf, sizeof(tconf)) ? -EFAULT : 0;
+}
+
+static int hw_timestamp_get(struct net_device *dev, struct ifreq *ifr)
+{
+ struct snf_ndev_state *priv = netdev_priv(dev);
+ struct hwtstamp_config tconf;
+
+ memset(&tconf, 0, sizeof(tconf));
+ tconf.tx_type = HWTSTAMP_TX_OFF;
+ /* We also need to check here that the current command string
+ * will cause timestamps to be generated
+ */
+ tconf.rx_filter = (priv->rx_tstamp_enabled &&
+ priv->chan->ts_enabled(priv->chan)) ?
+ HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE;
+
+ return copy_to_user(ifr->ifr_data, &tconf, sizeof(tconf)) ? -EFAULT : 0;
+}
+
+static int snf_init(struct net_device *dev)
+{
+ struct snf_ndev_state *priv = netdev_priv(dev);
+
+ /* Two bytes per command string entry */
+ dev->mtu = priv->chan->max_ptn_entries(priv->chan) * 2;
+ return 0;
+}
+
+static int snf_open(struct net_device *dev)
+{
+ struct snf_ndev_state *priv = netdev_priv(dev);
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ret = priv->chan->start(priv->chan);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
+}
+
+static int snf_stop(struct net_device *dev)
+{
+ struct snf_ndev_state *priv = netdev_priv(dev);
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ret = priv->chan->stop(priv->chan);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
+}
+
+static int snf_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ switch (cmd) {
+ case SIOCSHWTSTAMP:
+ return hw_timestamp_set(dev, ifr);
+
+ case SIOCGHWTSTAMP:
+ return hw_timestamp_get(dev, ifr);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int snf_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct snf_ndev_state *priv = netdev_priv(dev);
+ struct snf_chan *sch = priv->chan;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ /* Stop the hardware */
+ sch->stop(sch);
+ /* Set the new command pattern */
+ ret = sch->set_pattern(sch, skb->data, skb->len / 2);
+ /* Restart the hardware */
+ sch->start(sch);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (ret < 0) {
+ dev->stats.tx_dropped++;
+ } else {
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+ }
+
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops snf_netdev_ops = {
+ .ndo_init = snf_init,
+ .ndo_open = snf_open,
+ .ndo_stop = snf_stop,
+ .ndo_start_xmit = snf_start_xmit,
+ .ndo_do_ioctl = snf_ioctl
+};
+
+static void snf_setup(struct net_device *dev)
+{
+ dev->netdev_ops = &snf_netdev_ops;
+ dev->tx_queue_len = 1;
+ dev->flags = IFF_NOARP;
+ dev->type = ARPHRD_NONE;
+}
+
+/* Initialise netdev for a sniffer channel */
+int snf_channel_add(struct snf_chan *sch, const char *name)
+{
+ int ret;
+ struct net_device *ndev;
+ struct snf_ndev_state *priv;
+
+ ndev = alloc_netdev(sizeof(*priv), name, NET_NAME_UNKNOWN, snf_setup);
+ if (!ndev)
+ return -ENOMEM;
+
+ priv = netdev_priv(ndev);
+ priv->chan = sch;
+ priv->rx_tstamp_enabled = false;
+ spin_lock_init(&priv->lock);
+
+ ret = register_netdev(ndev);
+ if (ret < 0) {
+ free_netdev(ndev);
+ return ret;
+ }
+
+ sch->cstate = ndev;
+ return 0;
+}
+EXPORT_SYMBOL(snf_channel_add);
+
+/* Release netdev for a sniffer channel and free resources */
+int snf_channel_remove(struct snf_chan *sch)
+{
+ struct net_device *ndev = (struct net_device *)sch->cstate;
+
+ unregister_netdev(ndev);
+ free_netdev(ndev);
+ return 0;
+}
+EXPORT_SYMBOL(snf_channel_remove);
+
+/* Send a packet to user space for a sniffer match event */
+int snf_channel_notify_match(struct snf_chan *sch, struct snf_match_evt *mt)
+{
+ struct net_device *ndev = (struct net_device *)sch->cstate;
+ struct snf_ndev_state *priv = netdev_priv(ndev);
+ struct sk_buff *skb;
+ struct skb_shared_hwtstamps *skts;
+
+ skb = netdev_alloc_skb(ndev, mt->len);
+ if (!skb) {
+ ndev->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ skb_put(skb, mt->len);
+ skb_copy_to_linear_data(skb, mt->data, mt->len);
+ if (mt->ts_valid && priv->rx_tstamp_enabled) {
+ skts = skb_hwtstamps(skb);
+ skts->hwtstamp = ns_to_ktime(mt->ts);
+ }
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += mt->len;
+ netif_rx(skb);
+ return 0;
+}
+EXPORT_SYMBOL(snf_channel_notify_match);
+
+/* Suspend the interface */
+int snf_channel_suspend(struct snf_chan *sch)
+{
+ struct net_device *ndev = (struct net_device *)sch->cstate;
+ struct snf_ndev_state *priv = netdev_priv(ndev);
+ unsigned long flags;
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ret = sch->stop(sch);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_device_detach(ndev);
+ return ret;
+}
+EXPORT_SYMBOL(snf_channel_suspend);
+
+/* Resume the interface */
+int snf_channel_resume(struct snf_chan *sch)
+{
+ struct net_device *ndev = (struct net_device *)sch->cstate;
+ struct snf_ndev_state *priv = netdev_priv(ndev);
+ unsigned long flags;
+ int ret;
+
+ if (!netif_running(ndev))
+ return 0;
+
+ netif_device_attach(ndev);
+ spin_lock_irqsave(&priv->lock, flags);
+ ret = sch->start(sch);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(snf_channel_resume);
+
diff --git a/drivers/net/pkt-sniffer/core/snf_core.h b/drivers/net/pkt-sniffer/core/snf_core.h
new file mode 100644
index 0000000..73a30ff
--- /dev/null
+++ b/drivers/net/pkt-sniffer/core/snf_core.h
@@ -0,0 +1,60 @@
+/*
+ * Packet sniffer core driver
+ * - this header provides the interface to specific backend packet
+ * sniffer implementations
+ *
+ * Copyright (C) 2015 Linn Products Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Written by:
+ * Stathis Voukelatos <stathis.voukelatos@linn.co.uk>
+ */
+#ifndef __SNF_CORE_H
+#define __SNF_CORE_H
+
+#include <linux/types.h>
+
+/* This is a global maximum. Each backend will have its own limit */
+#define MAX_MATCH_BYTES 512
+
+/* Sniffer channel data structure */
+struct snf_chan {
+ int (*start)(struct snf_chan *sch);
+ int (*stop)(struct snf_chan *sch);
+ int (*set_pattern)(struct snf_chan *sch, const u8 *pattern, int count);
+ int (*max_ptn_entries)(struct snf_chan *sch);
+ int (*ts_enabled)(struct snf_chan *sch);
+ void *cstate;
+};
+
+/* Data from a sniffer match event */
+struct snf_match_evt {
+ int ts_valid; /* flag indicating if timestamp is present */
+ u64 ts; /* timestamp value */
+ u8 data[MAX_MATCH_BYTES]; /* packet data bytes matched by sniffer */
+ int len; /* number of valid bytes in the 'data' buffer */
+};
+
+/* Registers a sniffer channel */
+int snf_channel_add(struct snf_chan *sch, const char *name);
+
+/* Removes a sniffer channel */
+int snf_channel_remove(struct snf_chan *sch);
+
+/* Send a packet to user space for a sniffer match event */
+int snf_channel_notify_match(struct snf_chan *sch, struct snf_match_evt *mt);
+
+/* Suspend and resume operations */
+int snf_channel_suspend(struct snf_chan *sch);
+int snf_channel_resume(struct snf_chan *sch);
+
+#endif
+
diff --git a/include/uapi/linux/pkt_sniffer.h b/include/uapi/linux/pkt_sniffer.h
new file mode 100644
index 0000000..39e9957
--- /dev/null
+++ b/include/uapi/linux/pkt_sniffer.h
@@ -0,0 +1,33 @@
+/*
+ * Linn packet sniffer driver interface
+ *
+ * Copyright (C) 2015 Linn Products Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Written by:
+ * Stathis Voukelatos <stathis.voukelatos@linn.co.uk>
+ */
+#ifndef __PKT_SNIFFER_H
+#define __PKT_SNIFFER_H
+
+/* Commands for the command string
+ * It consists of a series of bytes in the following format:
+ * --------------------------------
+ * | CMD | DATA | CMD | DATA | ....
+ * --------------------------------
+ */
+#define PTN_CMD_DONTCARE 0
+#define PTN_CMD_MATCH 1
+#define PTN_CMD_COPY 2
+#define PTN_CMD_MATCHSTAMP 3
+#define PTN_CMD_COPYDONE 4
+
+#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v2 3/3] Linn Ethernet packet sniffer driver
From: Stathis Voukelatos @ 2015-02-17 14:03 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
Cc: abrestic-F7+t8E8rja9g9hUCZPvPmw, Stathis Voukelatos
In-Reply-To: <cover.1424181053.git.stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
Driver for the Ethernet Mii packet sniffer H/W module found in
the IMG Pistachio SoC.
Signed-off-by: Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
---
drivers/net/pkt-sniffer/Kconfig | 11 +
drivers/net/pkt-sniffer/Makefile | 4 +
drivers/net/pkt-sniffer/backends/ether/channel.c | 392 ++++++++++++++++++++++
drivers/net/pkt-sniffer/backends/ether/channel.h | 81 +++++
drivers/net/pkt-sniffer/backends/ether/hw.h | 46 +++
drivers/net/pkt-sniffer/backends/ether/platform.c | 301 +++++++++++++++++
6 files changed, 835 insertions(+)
create mode 100644 drivers/net/pkt-sniffer/backends/ether/channel.c
create mode 100644 drivers/net/pkt-sniffer/backends/ether/channel.h
create mode 100644 drivers/net/pkt-sniffer/backends/ether/hw.h
create mode 100644 drivers/net/pkt-sniffer/backends/ether/platform.c
diff --git a/drivers/net/pkt-sniffer/Kconfig b/drivers/net/pkt-sniffer/Kconfig
index 53ffcc1..b7c7f6b 100644
--- a/drivers/net/pkt-sniffer/Kconfig
+++ b/drivers/net/pkt-sniffer/Kconfig
@@ -6,3 +6,14 @@ menuconfig PKT_SNIFFER
The core driver can also be built as a module. If so, the module
will be called snf_core.
+config PKT_SNIFFER_ETHER
+ tristate "Ethernet packet sniffer"
+ depends on PKT_SNIFFER
+ help
+ Say Y here if you want to use the Ethernet packet sniffer
+ module by Linn Products Ltd. It can be found in the upcoming
+ Pistachio SoC by Imagination Technologies.
+
+ The driver can also be built as a module. If so, the module
+ will be called snf_ether.
+
diff --git a/drivers/net/pkt-sniffer/Makefile b/drivers/net/pkt-sniffer/Makefile
index 31dc396..89a3c60 100644
--- a/drivers/net/pkt-sniffer/Makefile
+++ b/drivers/net/pkt-sniffer/Makefile
@@ -1,3 +1,7 @@
snf_core-y += core/netdev.o
snf_core-y += core/module.o
obj-$(CONFIG_PKT_SNIFFER) += snf_core.o
+
+snf_ether-y += backends/ether/platform.o
+snf_ether-y += backends/ether/channel.o
+obj-$(CONFIG_PKT_SNIFFER_ETHER) += snf_ether.o
diff --git a/drivers/net/pkt-sniffer/backends/ether/channel.c b/drivers/net/pkt-sniffer/backends/ether/channel.c
new file mode 100644
index 0000000..a7fed4e
--- /dev/null
+++ b/drivers/net/pkt-sniffer/backends/ether/channel.c
@@ -0,0 +1,392 @@
+/*
+ * Ethernet Mii packet sniffer driver
+ * - channel functions
+ *
+ * Copyright (C) 2015 Linn Products Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Written by:
+ * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
+ */
+#include <linux/io.h>
+#include <linux/hrtimer.h>
+#include <linux/pkt_sniffer.h>
+#include "../../core/snf_core.h"
+#include "hw.h"
+#include "channel.h"
+
+#define to_ether_snf_chan(dev) container_of(dev, struct ether_snf_chan, chan)
+
+/* Checks if the supplied command string is compatible with the
+ * capabilities of the H/W. The command string consists of a series
+ * of bytes in the following format
+ * --------------------------------
+ * | CMD | DATA | CMD | DATA | ....
+ * --------------------------------
+ */
+static bool validate_pattern(
+ struct ether_snf_chan *ch,
+ const u8 *buf,
+ int count)
+{
+ int i, complete, max_copy_bytes;
+ int ts = 0;
+ int copy_before = 0;
+ int copy_after = 0;
+
+ if (count > ch->max_cmds)
+ return false;
+
+ /* Iterate through the commands in the string */
+ for (i = 0, complete = 0; (i < count) && !complete; i++) {
+ u8 cmd = buf[2*i];
+
+ switch (cmd) {
+ case PTN_CMD_DONTCARE:
+ case PTN_CMD_MATCH:
+ break;
+
+ case PTN_CMD_MATCHSTAMP:
+ /* The timestamp needs to be word-aligned in the FIFO
+ * therefore, the number of 'copy' commands before it
+ * needs to be a multiple of 4
+ */
+ if (copy_before & 3)
+ return false;
+ /* Signal that a timestamp will be present */
+ ts = 1;
+ break;
+
+ case PTN_CMD_COPY:
+ /* Increment count of bytes that will be returned */
+ if (ts)
+ copy_after++;
+ else
+ copy_before++;
+ break;
+
+ case PTN_CMD_COPYDONE:
+ /* Increment count of bytes that will be returned
+ * This command terminates the string
+ */
+ if (ts)
+ copy_after++;
+ else
+ copy_before++;
+ /* This command completes the command string */
+ complete = 1;
+ break;
+
+ default:
+ /* Invalid command id */
+ return false;
+ }
+ }
+
+ /* Check if the string was properly terminated
+ * and contained valid number of commands
+ */
+ if (complete) {
+ max_copy_bytes = ch->fifo_blk_words * 4;
+ if (ts)
+ max_copy_bytes -= 4;
+ /* Too many copy commands will case the FIFO
+ * to wrap around
+ */
+ if ((copy_before + copy_after) > max_copy_bytes)
+ return false;
+ ch->nfb_before = copy_before;
+ ch->nfb_after = copy_after;
+ ch->evt.ts_valid = ts;
+ ch->evt.len = ch->nfb_before + ch->nfb_after;
+ return true;
+ }
+
+ /* Command string not terminated */
+ return false;
+}
+
+/* Channel methods */
+
+/* Enables the channel */
+static int esnf_start(struct snf_chan *dev)
+{
+ struct ether_snf_chan *ch = to_ether_snf_chan(dev);
+
+ if (!ch->started) {
+ ch->evt.ts = 0;
+ /* Enable interrupts */
+ iowrite32(ch->data_irq_bit | ch->full_irq_bit,
+ ch->regs + SET_INTERRUPT_ENABLE);
+ /* Enable the packet matching logic */
+ iowrite32(ENABLE_BIT, ch->reg_enable);
+
+ ch->started = 1;
+ dev_info(ch->dev, "%s: started\n", ch->name);
+ } else {
+ dev_dbg(ch->dev, "%s: already running\n", ch->name);
+ }
+
+ return 0;
+}
+
+/* Disables the channel */
+static int esnf_stop(struct snf_chan *dev)
+{
+ struct ether_snf_chan *ch = to_ether_snf_chan(dev);
+
+ if (ch->started) {
+ /* Disable interrupts */
+ iowrite32(ch->data_irq_bit | ch->full_irq_bit,
+ ch->regs + CLEAR_INTERRUPT_ENABLE);
+ /* Stop the sniffer channel */
+ iowrite32(0, ch->reg_enable);
+ /* Clear any pending interrupts */
+ iowrite32(ch->data_irq_bit | ch->full_irq_bit,
+ ch->regs + INTERRUPT_STATUS);
+
+ ch->started = 0;
+ dev_info(ch->dev, "%s: stopped\n", ch->name);
+ } else {
+ dev_dbg(ch->dev, "%s: already stopped\n", ch->name);
+ }
+
+ return 0;
+}
+
+/* Sets the command string (pattern) for the channel
+ * The bytes in the pattern buffer are in the following order:
+ */
+static int esnf_set_pattern(struct snf_chan *dev, const u8 *pattern, int count)
+{
+ struct ether_snf_chan *ch = to_ether_snf_chan(dev);
+ int i, shift = 0;
+ u32 val = 0, *ptr;
+
+ dev_info(ch->dev, "%s: set cmd pattern with %d entries\n",
+ ch->name, count);
+
+ if (ch->started) {
+ dev_err(ch->dev,
+ "%s: cannot apply cmd pattern. Channel is active\n",
+ ch->name);
+ return -EBUSY;
+ }
+
+ if (!validate_pattern(ch, pattern, count)) {
+ dev_err(ch->dev,
+ "%s: invalid cmd pattern\n",
+ ch->name);
+ return -EINVAL;
+ }
+
+ for (ptr = ch->cmd_ram, i = 0, shift = 24; i < (2*count); i++) {
+ val |= ((u32)pattern[i]) << shift;
+ if (!shift) {
+ iowrite32(val, ptr++);
+ val = 0;
+ shift = 24;
+ } else {
+ shift -= 8;
+ }
+ }
+ if (shift)
+ iowrite32(val, ptr);
+
+ return 0;
+}
+
+/* Returns max number of commands supported by the channel */
+static int esnf_max_ptn_entries(struct snf_chan *dev)
+{
+ struct ether_snf_chan *ch = to_ether_snf_chan(dev);
+
+ return ch->max_cmds;
+}
+
+static int esnf_ts_enabled(struct snf_chan *dev)
+{
+ struct ether_snf_chan *ch = to_ether_snf_chan(dev);
+
+ return ch->evt.ts_valid;
+}
+
+/* Gray decoder */
+static u32 gray_decode(u32 gray)
+{
+ gray ^= (gray >> 16);
+ gray ^= (gray >> 8);
+ gray ^= (gray >> 4);
+ gray ^= (gray >> 2);
+ gray ^= (gray >> 1);
+ return gray;
+}
+
+/* Read a block from the data FIFO */
+static void read_fifo_data(struct ether_snf_chan *ch)
+{
+ int i;
+ u32 val, *ptr;
+ int ts = ch->evt.ts_valid;
+ int dw = ch->fifo_blk_words;
+ int bytes_before = ch->nfb_before;
+ int bytes_after = ch->nfb_after;
+
+ ptr = (u32 *)ch->evt.data;
+ for (i = 0; i < dw; i++) {
+ val = ioread32(ch->reg_fifo);
+ if (bytes_before > 0) {
+ /* Bytes before the timestamp */
+ *ptr++ = cpu_to_be32(val);
+ bytes_before -= 4;
+ } else if (ts) {
+ ch->raw_tstamp = gray_decode(val);
+ /* First timestamp since the channel was started.
+ * Initialise the timecounter
+ */
+ if (!ch->evt.ts)
+ timecounter_init(
+ &ch->tc,
+ &ch->cc,
+ ktime_to_ns(ktime_get_real()));
+ ch->evt.ts = timecounter_read(&ch->tc);
+ ts = 0;
+ } else if (bytes_after > 0) {
+ /* Bytes after the timestamp */
+ *ptr++ = cpu_to_be32(val);
+ bytes_after -= 4;
+ }
+ }
+}
+
+/* Read method for the timestamp cycle counter
+ * Returns the last received timestamp value
+ */
+static cycle_t esnf_cyclecounter_read(const struct cyclecounter *cc)
+{
+ struct ether_snf_chan *ch = container_of(cc, struct ether_snf_chan, cc);
+
+ return ch->raw_tstamp;
+}
+
+/* Initialises a sniffer channel */
+int channel_init(
+ struct ether_snf_chan *ch,
+ struct platform_device *pdev,
+ void *regs,
+ int fifo_blk_words,
+ u32 tstamp_hz,
+ u32 tstamp_shift,
+ u32 tstamp_bits,
+ int tx)
+{
+ struct resource *res;
+ u32 *ptr;
+ int i;
+
+ ch->regs = regs;
+ ch->dev = &pdev->dev;
+ ch->data_irq_bit = tx ? TX_DATA_IRQ_BIT : RX_DATA_IRQ_BIT;
+ ch->full_irq_bit = tx ? TX_FULL_IRQ_BIT : RX_FULL_IRQ_BIT;
+ ch->reg_enable = ch->regs +
+ (tx ? TX_SNIFFER_ENABLE : RX_SNIFFER_ENABLE);
+ ch->reg_fifo = ch->regs + (tx ? TX_FIFO_DAT : RX_FIFO_DAT);
+
+ /* Retrieve and remap the address space for the command memory */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ tx ? "tx-ram" : "rx-ram");
+ if (!res)
+ return -ENOSYS;
+ ch->cmd_ram = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ch->cmd_ram))
+ return PTR_ERR(ch->cmd_ram);
+
+ /* It is 2 bytes/command, hence divide by 2 */
+ ch->max_cmds = resource_size(res) / 2;
+
+ /* Initialise the command string RAM */
+ for (i = 0, ptr = ch->cmd_ram; i < resource_size(res); i += 4)
+ iowrite32((PTN_CMD_DONTCARE << 24) | (PTN_CMD_DONTCARE << 8),
+ ptr++);
+
+ ch->fifo_blk_words = fifo_blk_words;
+ ch->started = 0;
+
+ /* Initialise the timestamp cycle counter */
+ ch->cc.read = esnf_cyclecounter_read;
+ ch->cc.mask = CLOCKSOURCE_MASK(tstamp_bits);
+ ch->cc.mult = clocksource_hz2mult(tstamp_hz, tstamp_shift);
+ ch->cc.shift = tstamp_shift;
+
+ /* Register the channel methods */
+ ch->chan.start = esnf_start;
+ ch->chan.stop = esnf_stop;
+ ch->chan.set_pattern = esnf_set_pattern;
+ ch->chan.max_ptn_entries = esnf_max_ptn_entries;
+ ch->chan.ts_enabled = esnf_ts_enabled;
+
+ strncpy(ch->name, tx ? "TX" : "RX", MAX_CHAN_NAME_SIZE - 1);
+
+ dev_dbg(ch->dev, "%s: channel initialized\n", ch->name);
+
+ return 0;
+}
+
+/* Registers the channel with the sniffer core module */
+int channel_register(struct ether_snf_chan *ch, const char *name)
+{
+ int ret;
+
+ ret = snf_channel_add(&ch->chan, name);
+ if (ret < 0)
+ return ret;
+
+ dev_info(ch->dev, "%s channel added\n", ch->name);
+ return 0;
+}
+
+/* Unregisters the channel */
+int channel_unregister(struct ether_snf_chan *ch)
+{
+ int ret;
+
+ ch->chan.stop(&ch->chan);
+ ret = snf_channel_remove(&ch->chan);
+ if (!ret)
+ dev_info(ch->dev, "%s channel removed\n", ch->name);
+ return ret;
+}
+
+/* Process match event data */
+void channel_data_available(struct ether_snf_chan *ch)
+{
+ int ret;
+
+ dev_dbg(ch->dev, "%s match event\n", ch->name);
+
+ read_fifo_data(ch);
+ ret = snf_channel_notify_match(&ch->chan, &ch->evt);
+ if (ret < 0)
+ dev_err(ch->dev, "%s: event notification failed\n", ch->name);
+}
+
+/* Suspend opertion */
+int channel_suspend(struct ether_snf_chan *ch)
+{
+ return snf_channel_suspend(&ch->chan);
+}
+
+/* Resume operation */
+int channel_resume(struct ether_snf_chan *ch)
+{
+ return snf_channel_resume(&ch->chan);
+}
+
diff --git a/drivers/net/pkt-sniffer/backends/ether/channel.h b/drivers/net/pkt-sniffer/backends/ether/channel.h
new file mode 100644
index 0000000..35ed891
--- /dev/null
+++ b/drivers/net/pkt-sniffer/backends/ether/channel.h
@@ -0,0 +1,81 @@
+/*
+ * Ethernet Mii packet sniffer driver
+ * - channel interface
+ *
+ * Copyright (C) 2015 Linn Products Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Written by:
+ * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
+ */
+#ifndef _ETHER_SNIFFER_CHANNEL_H_
+#define _ETHER_SNIFFER_CHANNEL_H_
+
+#include <linux/platform_device.h>
+#include <linux/clocksource.h>
+#include "../../core/snf_core.h"
+
+#define MAX_CHAN_NAME_SIZE 5
+
+struct ether_snf_chan {
+ /* Sniffer core structure */
+ struct snf_chan chan;
+ /* Pointer to device struct */
+ struct device *dev;
+ /* Registers */
+ u8 __iomem *regs;
+ /* Command string memory */
+ u32 __iomem *cmd_ram;
+ /* Bit number for the data IRQ */
+ int data_irq_bit;
+ /* Bit number for the FIFO full IRQ */
+ int full_irq_bit;
+ /* Channel enable register */
+ u8 __iomem *reg_enable;
+ /* Data FIFO register */
+ u8 __iomem *reg_fifo;
+ /* Max number of commands in the string */
+ int max_cmds;
+ /* Max matching bytes that can fit in a FIFO block */
+ int fifo_blk_words;
+ /* Number of bytes in the FIFO before the timestamp */
+ int nfb_before;
+ /* Number of bytes in the FIFO after the timestamp */
+ int nfb_after;
+ /* Channel active flag */
+ int started;
+ /* Last raw timestamp from the FIFO */
+ u32 raw_tstamp;
+ /* Channel name (only used by debug messages) */
+ char name[MAX_CHAN_NAME_SIZE];
+ /* Struct to hold data from a packet match */
+ struct snf_match_evt evt;
+ /* Cycle and time counters for tstamp handling */
+ struct cyclecounter cc;
+ struct timecounter tc;
+};
+
+int channel_init(
+ struct ether_snf_chan *ch,
+ struct platform_device *pdev,
+ void *regs,
+ int fifo_blk_words,
+ u32 tstamp_hz,
+ u32 tstamp_shift,
+ u32 tstamp_bits,
+ int tx);
+int channel_register(struct ether_snf_chan *ch, const char *name);
+int channel_unregister(struct ether_snf_chan *ch);
+void channel_data_available(struct ether_snf_chan *ch);
+int channel_suspend(struct ether_snf_chan *ch);
+int channel_resume(struct ether_snf_chan *ch);
+
+#endif
diff --git a/drivers/net/pkt-sniffer/backends/ether/hw.h b/drivers/net/pkt-sniffer/backends/ether/hw.h
new file mode 100644
index 0000000..edb1093
--- /dev/null
+++ b/drivers/net/pkt-sniffer/backends/ether/hw.h
@@ -0,0 +1,46 @@
+/*
+ * Ethernet Mii packet sniffer driver
+ * - register map
+ *
+ * Copyright (C) 2015 Linn Products Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Written by:
+ * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
+ */
+#ifndef _ETHER_SNIFFER_HW_H_
+#define _ETHER_SNIFFER_HW_H_
+
+#include <linux/bitops.h>
+
+/* Registers */
+#define INTERRUPT_ENABLE 0x00
+#define SET_INTERRUPT_ENABLE 0x04
+#define CLEAR_INTERRUPT_ENABLE 0x08
+#define INTERRUPT_STATUS 0x0c
+#define TX_FIFO_DAT 0x10
+#define RX_FIFO_DAT 0x14
+#define TX_FIFO_OCC 0x18
+#define RX_FIFO_OCC 0x1c
+#define TX_SNIFFER_ENABLE 0x20
+#define RX_SNIFFER_ENABLE 0x24
+
+/* IRQ register bits */
+#define TX_DATA_IRQ_BIT BIT(0)
+#define RX_DATA_IRQ_BIT BIT(1)
+#define TX_FULL_IRQ_BIT BIT(2)
+#define RX_FULL_IRQ_BIT BIT(3)
+
+/* Enable register bits */
+#define ENABLE_BIT BIT(0)
+
+#endif
+
diff --git a/drivers/net/pkt-sniffer/backends/ether/platform.c b/drivers/net/pkt-sniffer/backends/ether/platform.c
new file mode 100644
index 0000000..06b26b5
--- /dev/null
+++ b/drivers/net/pkt-sniffer/backends/ether/platform.c
@@ -0,0 +1,301 @@
+/*
+ * Ethernet Mii packet sniffer driver
+ *
+ * Copyright (C) 2015 Linn Products Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Written by:
+ * Stathis Voukelatos <stathis.voukelatos-zgcZaY4qg+21Qrn1Bg8BZw@public.gmane.org>
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include "../../core/snf_core.h"
+#include "hw.h"
+#include "channel.h"
+
+/* Names for the TX and RX channel net interfaces */
+static const char tx_channel_name[] = "snfethtx%d";
+static const char rx_channel_name[] = "snfethrx%d";
+
+struct ether_snf {
+ u8 __iomem *regs;
+ int irq;
+ struct clk *sys_clk;
+ struct clk *ts_clk;
+ struct ether_snf_chan txc;
+ struct ether_snf_chan rxc;
+};
+
+/* Interrupt handler */
+static irqreturn_t esnf_interrupt(int irq, void *dev_id)
+{
+ struct platform_device *pdev = (struct platform_device *)dev_id;
+ struct ether_snf *esnf = (struct ether_snf *)platform_get_drvdata(pdev);
+ u32 irq_status;
+
+ if (unlikely(esnf->irq != irq))
+ return IRQ_NONE;
+
+ irq_status = ioread32(esnf->regs + INTERRUPT_STATUS) &
+ ioread32(esnf->regs + INTERRUPT_ENABLE);
+
+ dev_dbg(&pdev->dev, "irq: 0x%08x\n", irq_status);
+
+ /* TX FIFO full */
+ if (unlikely(irq_status & TX_FULL_IRQ_BIT))
+ dev_notice(&pdev->dev, "TX FIFO full\n");
+
+ /* RX FIFO full */
+ if (unlikely(irq_status & RX_FULL_IRQ_BIT))
+ dev_notice(&pdev->dev, "RX FIFO full\n");
+
+ /* TX match data available */
+ if (irq_status & TX_DATA_IRQ_BIT) {
+ dev_dbg(&pdev->dev, "TX data\n");
+ channel_data_available(&esnf->txc);
+ }
+
+ /* RX match data available */
+ if (irq_status & RX_DATA_IRQ_BIT) {
+ dev_dbg(&pdev->dev, "RX data\n");
+ channel_data_available(&esnf->rxc);
+ }
+
+ /* Clear interrupts */
+ iowrite32(irq_status, esnf->regs + INTERRUPT_STATUS);
+
+ return IRQ_HANDLED;
+}
+
+/* Called when the packet sniffer device is bound with the driver */
+static int esnf_driver_probe(struct platform_device *pdev)
+{
+ struct ether_snf *esnf;
+ struct resource *res;
+ int ret, irq;
+ u32 fifo_blk_words, ts_hz, ts_shift, ts_bits;
+ void __iomem *regs;
+ struct device_node *ofn = pdev->dev.of_node;
+
+ /* Allocate the device data structure */
+ esnf = devm_kzalloc(&pdev->dev, sizeof(*esnf), GFP_KERNEL);
+ if (!esnf)
+ return -ENOMEM;
+
+ /* Retrieve and remap register memory space */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+ regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+ esnf->regs = regs;
+
+ if (!ofn)
+ return -ENODEV;
+
+ /* Read requirede properties from the device tree node */
+ ret = of_property_read_u32(
+ ofn,
+ "fifo-block-words",
+ &fifo_blk_words);
+ if (ret < 0)
+ return ret;
+
+ if (((fifo_blk_words - 1)*4) > MAX_MATCH_BYTES) {
+ dev_err(&pdev->dev,
+ "Invalid FIFO block size entry in device tree\n");
+ return -EINVAL;
+ }
+
+ ret = of_property_read_u32(
+ ofn,
+ "tstamp-hz",
+ &ts_hz);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_read_u32(
+ ofn,
+ "tstamp-shift",
+ &ts_shift);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_read_u32(
+ ofn,
+ "tstamp-bits",
+ &ts_bits);
+ if (ret < 0)
+ return ret;
+
+ /* Enable peripheral bus and timstamp clocks */
+ esnf->sys_clk = devm_clk_get(&pdev->dev, "sys");
+ if (IS_ERR(esnf->sys_clk)) {
+ ret = PTR_ERR(esnf->sys_clk);
+ return ret;
+ }
+ ret = clk_prepare_enable(esnf->sys_clk);
+ if (ret < 0)
+ return ret;
+
+ esnf->ts_clk = devm_clk_get(&pdev->dev, "tstamp");
+ if (IS_ERR(esnf->ts_clk)) {
+ ret = PTR_ERR(esnf->ts_clk);
+ goto fail1;
+ }
+ ret = clk_prepare_enable(esnf->ts_clk);
+ if (ret < 0)
+ goto fail1;
+
+ /* Initialise the TX and RX channels */
+ ret = channel_init(
+ &esnf->txc,
+ pdev,
+ regs,
+ fifo_blk_words,
+ ts_hz,
+ ts_shift,
+ ts_bits,
+ 1);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to init TX channel (%d)\n", ret);
+ goto fail2;
+ }
+ ret = channel_init(
+ &esnf->rxc,
+ pdev,
+ regs,
+ fifo_blk_words,
+ ts_hz,
+ ts_shift,
+ ts_bits,
+ 0);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to init RX channel (%d)\n", ret);
+ goto fail2;
+ }
+
+ /* Register the channels with the sniffer core module */
+ ret = channel_register(&esnf->txc, tx_channel_name);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register TX chan (%d)\n", ret);
+ goto fail2;
+ }
+ ret = channel_register(&esnf->rxc, rx_channel_name);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register RX chan (%d)\n", ret);
+ goto fail3;
+ }
+
+ platform_set_drvdata(pdev, esnf);
+
+ /* Register the interrupt handler */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ goto fail4;
+ esnf->irq = irq;
+ ret = devm_request_irq(
+ &pdev->dev,
+ irq,
+ esnf_interrupt,
+ 0,
+ KBUILD_MODNAME,
+ pdev);
+ if (ret < 0)
+ goto fail4;
+
+ return 0;
+
+fail4:
+ channel_unregister(&esnf->rxc);
+fail3:
+ channel_unregister(&esnf->txc);
+fail2:
+ clk_disable_unprepare(esnf->ts_clk);
+fail1:
+ clk_disable_unprepare(esnf->sys_clk);
+ return ret;
+}
+
+/* Called when the packet sniffer device unregisters with the driver */
+static int esnf_driver_remove(struct platform_device *pdev)
+{
+ struct ether_snf *esnf = (struct ether_snf *)platform_get_drvdata(pdev);
+ int ret;
+
+ ret = channel_unregister(&esnf->txc);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to unregister TX chan (%d)\n", ret);
+ return ret;
+ }
+ ret = channel_unregister(&esnf->rxc);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to unregister RX chan (%d)\n", ret);
+ return ret;
+ }
+ clk_disable_unprepare(esnf->ts_clk);
+ clk_disable_unprepare(esnf->sys_clk);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+/* Driver suspend method */
+static int esnf_driver_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct ether_snf *esnf = (struct ether_snf *)platform_get_drvdata(pdev);
+
+ channel_suspend(&esnf->txc);
+ channel_suspend(&esnf->rxc);
+ return 0;
+}
+
+/* Driver resume method */
+static int esnf_driver_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct ether_snf *esnf = (struct ether_snf *)platform_get_drvdata(pdev);
+
+ channel_resume(&esnf->txc);
+ channel_resume(&esnf->rxc);
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(esnf_pm_ops, esnf_driver_suspend, esnf_driver_resume);
+#endif
+
+static const struct of_device_id esnf_of_match_table[] = {
+ { .compatible = "linn,eth-sniffer" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, esnf_of_match_table);
+
+static struct platform_driver esnf_platform_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+#ifdef CONFIG_PM
+ .pm = &esnf_pm_ops,
+#endif
+ .of_match_table = esnf_of_match_table,
+ },
+ .probe = esnf_driver_probe,
+ .remove = esnf_driver_remove,
+};
+
+module_platform_driver(esnf_platform_driver);
+
+MODULE_DESCRIPTION("Linn Ethernet Packet Sniffer");
+MODULE_AUTHOR("Linn Products Ltd");
+MODULE_LICENSE("GPL v2");
+
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" 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 related
* Re: [PATCH] vhost: support upto 509 memory regions
From: Paolo Bonzini @ 2015-02-17 14:11 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: Igor Mammedov, linux-kernel, kvm, netdev
In-Reply-To: <20150217132931.GB6362@redhat.com>
On 17/02/2015 14:29, Michael S. Tsirkin wrote:
> On Tue, Feb 17, 2015 at 02:11:37PM +0100, Paolo Bonzini wrote:
>>
>>
>> On 17/02/2015 13:32, Michael S. Tsirkin wrote:
>>> On Tue, Feb 17, 2015 at 11:59:48AM +0100, Paolo Bonzini wrote:
>>>>
>>>>
>>>> On 17/02/2015 10:02, Michael S. Tsirkin wrote:
>>>>>> Increasing VHOST_MEMORY_MAX_NREGIONS from 65 to 509
>>>>>> to match KVM_USER_MEM_SLOTS fixes issue for vhost-net.
>>>>>>
>>>>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
>>>>>
>>>>> This scares me a bit: each region is 32byte, we are talking
>>>>> a 16K allocation that userspace can trigger.
>>>>
>>>> What's bad with a 16K allocation?
>>>
>>> It fails when memory is fragmented.
>>
>> If memory is _that_ fragmented I think you have much bigger problems
>> than vhost.
>>
>>> I'm guessing kvm doesn't do memory scans on data path, vhost does.
>>
>> It does for MMIO memory-to-memory writes, but that's not a particularly
>> fast path.
>>
>> KVM doesn't access the memory map on fast paths, but QEMU does, so I
>> don't think it's beyond the expectations of the kernel.
>
> QEMU has an elaborate data structure to deal with that.
It's not elaborate, it's just a radix tree. The complicated part is
building the flat view and computing what changed in the memory map, but
none of this would have to be done in vhost. vhost gets the flat memory
map in VHOST_SET_MEM_TABLE.
A lookup is basically:
#define LOG_TRIE_WIDTH (PAGE_SHIFT - LOG_BITS_PER_LONG)
unsigned long node_val = (unsigned long) trie_root;
/* log of highest valid address in the memory map */
if (addr & (-1U << vhost_address_space_bits))
return NULL;
addr <<= 64 - vhost_address_space_bits;
do {
struct memmap_trie_node *node;
unsigned i = addr >> (64 - LOG_TRIE_WIDTH);
addr = addr << LOG_TRIE_WIDTH;
node = (struct memmap_trie_node *) (node_val - 1);
node_val = (unsigned long) node[i];
} while (node_val & 1);
return (struct vhost_mem_slot *)node_val;
bit 0: 0 if leaf
if leaf:
bits 1-63: pointer to mem table entry
if not leaf:
bits 1-63: pointer to next level
>> For example you
>> can use a radix tree (not lib/radix-tree.c unfortunately), and cache
>> GVA->HPA translations if it turns out that lookup has become a hot path.
>
> All vhost lookups are hot path.
What % is lookup vs the networking stuff? Also, adding a simple MRU
cache might make lookups less prominent in the profile.
>> The addressing space of x86 is in practice 44 bits or fewer, and each
>> slot will typically be at least 1 GiB, so you only have 14 bits to
>> dispatch on. It's probably possible to only have two or three levels
>> in the radix tree in the common case, and beat the linear scan real quick.
>
> Not if there are about 6 regions, I think.
It depends on many factors including branch prediction, MRU cache hits, etc.
> Increasing the number might be reasonable for workloads such as nested
> virt.
Why does nested virt matter?
Paolo
^ permalink raw reply
* Re: [PATCH v2 1/3] Ethernet packet sniffer: Device tree binding and vendor prefix
From: Sergei Shtylyov @ 2015-02-17 14:16 UTC (permalink / raw)
To: Stathis Voukelatos, linux-kernel, devicetree, netdev; +Cc: abrestic
In-Reply-To: <0a86907642a97e5bd880f69299664232fcffaf9d.1424181053.git.stathis.voukelatos@linn.co.uk>
Hello.
On 02/17/2015 05:03 PM, Stathis Voukelatos wrote:
> Signed-off-by: Stathis Voukelatos <stathis.voukelatos@linn.co.uk>
[...]
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index d443279..891c224 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -90,6 +90,7 @@ lacie LaCie
> lantiq Lantiq Semiconductor
> lenovo Lenovo Group Ltd.
> lg LG Corporation
> +linn Linn Products Ltd.
Please use tab for indenting the company name.
> linux Linux-specific binding
> lsi LSI Corp. (LSI Logic)
> lltc Linear Technology Corporation
WBR, Sergei
^ permalink raw reply
* Re: [PATCH] vhost: support upto 509 memory regions
From: Igor Mammedov @ 2015-02-17 14:44 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: Paolo Bonzini, linux-kernel, kvm, netdev
In-Reply-To: <20150217123212.GA6362@redhat.com>
On Tue, 17 Feb 2015 13:32:12 +0100
"Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Tue, Feb 17, 2015 at 11:59:48AM +0100, Paolo Bonzini wrote:
> >
> >
> > On 17/02/2015 10:02, Michael S. Tsirkin wrote:
> > > > Increasing VHOST_MEMORY_MAX_NREGIONS from 65 to 509
> > > > to match KVM_USER_MEM_SLOTS fixes issue for vhost-net.
> > > >
> > > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > >
> > > This scares me a bit: each region is 32byte, we are talking
> > > a 16K allocation that userspace can trigger.
> >
> > What's bad with a 16K allocation?
>
> It fails when memory is fragmented.
>
> > > How does kvm handle this issue?
> >
> > It doesn't.
> >
> > Paolo
>
> I'm guessing kvm doesn't do memory scans on data path,
> vhost does.
>
> qemu is just doing things that kernel didn't expect it to need.
>
> Instead, I suggest reducing number of GPA<->HVA mappings:
>
> you have GPA 1,5,7
> map them at HVA 11,15,17
> then you can have 1 slot: 1->11
>
> To avoid libc reusing the memory holes, reserve them with MAP_NORESERVE
> or something like this.
Lets suppose that we add API to reserve whole memory hotplug region
with MAP_NORESERVE and passed it as memslot to KVM.
Then what will happen to guest accessing not really mapped region?
This memslot will also be passed to vhost as region, is it really ok?
I don't know what else it might break.
As alternative:
we can filter out hotplugged memory and vhost will continue to work with
only initial memory.
So question is id we have to tell vhost about hotplugged memory?
>
> We can discuss smarter lookup algorithms but I'd rather
> userspace didn't do things that we then have to
> work around in kernel.
>
>
^ 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