All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] gnutls fixes
From: Martin Jansa @ 2012-01-17 10:57 UTC (permalink / raw)
  To: openembedded-core

Hi,

nobody likes when it's trying to use host's libraries and even worse 
when it succeeds and pulls them to rest of OE builds through .la files.

The following changes since commit 91e17c0c0ac2330f826b95e762542cd0d0c82385:

  pango: Use gnomebase class, not gnome (2012-01-16 18:01:31 +0000)

are available in the git repository at:
  git://git.openembedded.org/openembedded-core-contrib jansa/gnutls
  http://cgit.openembedded.org/cgit.cgi/openembedded-core-contrib/log/?h=jansa/gnutls

Martin Jansa (2):
  gnutls: add readline to DEPENDS and add --with-libreadline-prefix
  gnutls.inc: set libz prefix

 meta/recipes-support/gnutls/gnutls.inc |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

-- 
1.7.8.3




^ permalink raw reply

* [PATCH 2/4] netfilter: revert user-space expectation helper support
From: pablo @ 2012-01-17 11:04 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1326798289-11592-1-git-send-email-pablo@netfilter.org>

From: Pablo Neira Ayuso <pablo@netfilter.org>

This patch partially reverts:
3d058d7 netfilter: rework user-space expectation helper support
that was applied during the 3.2 development cycle.

After this patch, the tree remains just like before patch bc01bef,
that initially added the preliminary infrastructure.

I decided to partially revert this patch because the approach
that I proposed to resolve this problem is broken in NAT setups.
Moreover, a new infrastructure will be submitted for the 3.3.x
development cycle that resolve the existing issues while
providing a neat solution.

Since nobody has been seriously using this infrastructure in
user-space, the removal of this feature should affect any know
FOSS project (to my knowledge).

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter/nf_conntrack_common.h |    4 ----
 include/linux/netfilter/xt_CT.h               |    3 +--
 net/netfilter/nf_conntrack_helper.c           |   12 ------------
 net/netfilter/nf_conntrack_netlink.c          |    4 ----
 net/netfilter/xt_CT.c                         |    8 +++-----
 5 files changed, 4 insertions(+), 27 deletions(-)

diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index 9e3a283..0d3dd66 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -83,10 +83,6 @@ enum ip_conntrack_status {
 	/* Conntrack is a fake untracked entry */
 	IPS_UNTRACKED_BIT = 12,
 	IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),
-
-	/* Conntrack has a userspace helper. */
-	IPS_USERSPACE_HELPER_BIT = 13,
-	IPS_USERSPACE_HELPER = (1 << IPS_USERSPACE_HELPER_BIT),
 };
 
 /* Connection tracking event types */
diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h
index 6390f09..b56e768 100644
--- a/include/linux/netfilter/xt_CT.h
+++ b/include/linux/netfilter/xt_CT.h
@@ -3,8 +3,7 @@
 
 #include <linux/types.h>
 
-#define XT_CT_NOTRACK		0x1
-#define XT_CT_USERSPACE_HELPER	0x2
+#define XT_CT_NOTRACK	0x1
 
 struct xt_ct_target_info {
 	__u16 flags;
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 299fec9..bbe23ba 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -121,18 +121,6 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
 	int ret = 0;
 
 	if (tmpl != NULL) {
-		/* we've got a userspace helper. */
-		if (tmpl->status & IPS_USERSPACE_HELPER) {
-			help = nf_ct_helper_ext_add(ct, flags);
-			if (help == NULL) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			rcu_assign_pointer(help->helper, NULL);
-			__set_bit(IPS_USERSPACE_HELPER_BIT, &ct->status);
-			ret = 0;
-			goto out;
-		}
 		help = nfct_help(tmpl);
 		if (help != NULL)
 			helper = help->helper;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 2a4834b..9307b03 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -2042,10 +2042,6 @@ ctnetlink_create_expect(struct net *net, u16 zone,
 	}
 	help = nfct_help(ct);
 	if (!help) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-	if (test_bit(IPS_USERSPACE_HELPER_BIT, &ct->status)) {
 		if (!cda[CTA_EXPECT_TIMEOUT]) {
 			err = -EINVAL;
 			goto out;
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 8e87123..0221d10 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -62,8 +62,8 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
 	int ret = 0;
 	u8 proto;
 
-	if (info->flags & ~(XT_CT_NOTRACK | XT_CT_USERSPACE_HELPER))
-		return -EOPNOTSUPP;
+	if (info->flags & ~XT_CT_NOTRACK)
+		return -EINVAL;
 
 	if (info->flags & XT_CT_NOTRACK) {
 		ct = nf_ct_untracked_get();
@@ -92,9 +92,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
 				  GFP_KERNEL))
 		goto err3;
 
-	if (info->flags & XT_CT_USERSPACE_HELPER) {
-		__set_bit(IPS_USERSPACE_HELPER_BIT, &ct->status);
-	} else if (info->helper[0]) {
+	if (info->helper[0]) {
 		ret = -ENOENT;
 		proto = xt_ct_find_proto(par);
 		if (!proto) {
-- 
1.7.7.3


^ permalink raw reply related

* Re: [PATCH] regulator: Add devm_regulator_get()
From: Mark Brown @ 2012-01-17 11:04 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: Liam Girdwood, linux-kernel, linux-doc
In-Reply-To: <1326771598-28124-1-git-send-email-sboyd@codeaurora.org>

On Mon, Jan 16, 2012 at 07:39:58PM -0800, Stephen Boyd wrote:

> @@ -200,6 +202,11 @@ static inline struct regulator *__must_check regulator_get(struct device *dev,
>  	 */
>  	return NULL;
>  }
> +static inline struct regulator *__must_check
> +devm_regulator_get(struct device *dev, const char *id)
> +{
> +	return NULL;
> +}
>  static inline void regulator_put(struct regulator *regulator)
>  {
>  }

Oh, and it's not obvious from the diff but blank lines please like the
adjacent code.

^ permalink raw reply

* [PATCH] Add missing gate for HVM domain
From: Paul Durrant @ 2012-01-17 11:04 UTC (permalink / raw)
  To: xen-devel; +Cc: paul.durrant

# HG changeset patch
# User Paul Durrant <paul.durrant@citrix.com>
# Date 1326798293 0
# Node ID 37b60f1b74641ba9e10064d11ce7178680d1536e
# Parent  2913ccc6d70f15ffcc15c7e066c9269b15a30a09
Add missing gate for HVM domain.

This will fix localhost migrate failures found by the automatic tests.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>

diff -r 2913ccc6d70f -r 37b60f1b7464 tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c	Mon Jan 16 17:56:07 2012 +0000
+++ b/tools/libxl/xl_cmdimpl.c	Tue Jan 17 11:04:53 2012 +0000
@@ -1580,7 +1580,8 @@ static int create_domain(struct domain_c
         }
     }
 
-    d_config.b_info.u.hvm.no_incr_generationid = dom_info->no_incr_generationid;
+    if (d_config.c_info.type == LIBXL_DOMAIN_TYPE_HVM)
+        d_config.b_info.u.hvm.no_incr_generationid = dom_info->no_incr_generationid;
 
     if (debug || dom_info->dryrun)
         printf_info(-1, &d_config, &d_config.dm_info);

^ permalink raw reply

* [PATCH] Bluetooth: Adding USB device 13d3:3375 as an Atheros AR3012.
From: Michal Labedzki @ 2012-01-17 11:04 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <20111205221529.GA21676@over-here.org>

I verified this patch. It is works and seems to be correct. 
Please apply it. Tested on UX21 with/without patch and with/without 
firmware (from latest linux-firmware).

^ permalink raw reply

* [PATCH 4/4] netfilter: ipset: dumping error triggered removing references twice
From: pablo @ 2012-01-17 11:04 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1326798289-11592-1-git-send-email-pablo@netfilter.org>

From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>

If there was a dumping error in the middle, the set-specific variable was
not zeroed out and thus the 'done' function of the dumping wrongly tried
to release the already released reference of the set. The already released
reference was caught by __ip_set_put and triggered a kernel BUG message.
Reported by Jean-Philippe Menil.

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/ipset/ip_set_core.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 0f8e5f2..32dbf0f 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -1142,6 +1142,7 @@ release_refcount:
 	if (ret || !cb->args[2]) {
 		pr_debug("release set %s\n", ip_set_list[index]->name);
 		ip_set_put_byindex(index);
+		cb->args[2] = 0;
 	}
 out:
 	if (nlh) {
-- 
1.7.7.3

^ permalink raw reply related

* [PATCH 3/4] netfilter: ipset: autoload set type modules safely
From: pablo @ 2012-01-17 11:04 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1326798289-11592-1-git-send-email-pablo@netfilter.org>

From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>

Jan Engelhardt noticed when userspace requests a set type unknown
to the kernel, it can lead to a loop due to the unsafe type module
loading. The issue is fixed in this patch.

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/ipset/ip_set_core.c |   36 ++++++++++++++++++++++++++----------
 1 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 86137b5..0f8e5f2 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -77,35 +77,42 @@ find_set_type(const char *name, u8 family, u8 revision)
 }
 
 /* Unlock, try to load a set type module and lock again */
-static int
-try_to_load_type(const char *name)
+static bool
+load_settype(const char *name)
 {
 	nfnl_unlock();
 	pr_debug("try to load ip_set_%s\n", name);
 	if (request_module("ip_set_%s", name) < 0) {
 		pr_warning("Can't find ip_set type %s\n", name);
 		nfnl_lock();
-		return -IPSET_ERR_FIND_TYPE;
+		return false;
 	}
 	nfnl_lock();
-	return -EAGAIN;
+	return true;
 }
 
 /* Find a set type and reference it */
+#define find_set_type_get(name, family, revision, found)	\
+	__find_set_type_get(name, family, revision, found, false)
+
 static int
-find_set_type_get(const char *name, u8 family, u8 revision,
-		  struct ip_set_type **found)
+__find_set_type_get(const char *name, u8 family, u8 revision,
+		    struct ip_set_type **found, bool retry)
 {
 	struct ip_set_type *type;
 	int err;
 
+	if (retry && !load_settype(name))
+		return -IPSET_ERR_FIND_TYPE;
+
 	rcu_read_lock();
 	*found = find_set_type(name, family, revision);
 	if (*found) {
 		err = !try_module_get((*found)->me) ? -EFAULT : 0;
 		goto unlock;
 	}
-	/* Make sure the type is loaded but we don't support the revision */
+	/* Make sure the type is already loaded
+	 * but we don't support the revision */
 	list_for_each_entry_rcu(type, &ip_set_type_list, list)
 		if (STREQ(type->name, name)) {
 			err = -IPSET_ERR_FIND_TYPE;
@@ -113,7 +120,8 @@ find_set_type_get(const char *name, u8 family, u8 revision,
 		}
 	rcu_read_unlock();
 
-	return try_to_load_type(name);
+	return retry ? -IPSET_ERR_FIND_TYPE :
+		__find_set_type_get(name, family, revision, found, true);
 
 unlock:
 	rcu_read_unlock();
@@ -124,12 +132,19 @@ unlock:
  * If we succeeded, the supported minimal and maximum revisions are
  * filled out.
  */
+#define find_set_type_minmax(name, family, min, max) \
+	__find_set_type_minmax(name, family, min, max, false)
+
 static int
-find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
+__find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max,
+		       bool retry)
 {
 	struct ip_set_type *type;
 	bool found = false;
 
+	if (retry && !load_settype(name))
+		return -IPSET_ERR_FIND_TYPE;
+
 	*min = 255; *max = 0;
 	rcu_read_lock();
 	list_for_each_entry_rcu(type, &ip_set_type_list, list)
@@ -145,7 +160,8 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
 	if (found)
 		return 0;
 
-	return try_to_load_type(name);
+	return retry ? -IPSET_ERR_FIND_TYPE :
+		__find_set_type_minmax(name, family, min, max, true);
 }
 
 #define family_name(f)	((f) == AF_INET ? "inet" : \
-- 
1.7.7.3

^ permalink raw reply related

* [PATCH 1/4] netfilter: xt_hashlimit: fix unused variable warning if IPv6 disabled
From: pablo @ 2012-01-17 11:04 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1326798289-11592-1-git-send-email-pablo@netfilter.org>

From: Stephen Rothwell <sfr@canb.auug.org.au>

Fixes this warning when CONFIG_IP6_NF_IPTABLES is not enabled:

net/netfilter/xt_hashlimit.c: In function ‘hashlimit_init_dst’:
net/netfilter/xt_hashlimit.c:448:9: warning: unused variable ‘frag_off’ [-Wunused-variable]

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/xt_hashlimit.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 8e49921..d95f9c9 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -445,7 +445,6 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
 {
 	__be16 _ports[2], *ports;
 	u8 nexthdr;
-	__be16 frag_off;
 	int poff;
 
 	memset(dst, 0, sizeof(*dst));
@@ -466,6 +465,9 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
 		break;
 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 	case NFPROTO_IPV6:
+	{
+		__be16 frag_off;
+
 		if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) {
 			memcpy(&dst->ip6.dst, &ipv6_hdr(skb)->daddr,
 			       sizeof(dst->ip6.dst));
@@ -485,6 +487,7 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
 		if ((int)protoff < 0)
 			return -1;
 		break;
+	}
 #endif
 	default:
 		BUG();
-- 
1.7.7.3

^ permalink raw reply related

* [PATCH 0/4] netfilter updates for net tree
From: pablo @ 2012-01-17 11:04 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

From: Pablo Neira Ayuso <pablo@netfilter.org>

Hi Dave,

The following patches contains updates for your current net tree:

* A couple for bugfixes for ipset from Jozsef.

* Revert the user-space expectation helper support from myself.
  I decided to do this because I found problems specifically
  regarding NAT setups. I didn't throw the towel though. I'm
  working one new infrastructure. My plan is to submit it for
  net-next once it's open and it passes developers scrutiny
  (still work in progress):

 http://1984.lsi.us.es/git/net-next/commit/?h=cthelper&id=4e690f548859eec5a3dad151dec9c12bac17c014

* Fix one compilation warning if ip6tables is disabled in
  xt_hashlimit.

You can pull these changes from:

git://1984.lsi.us.es/net nf

Thanks.

Jozsef Kadlecsik (2):
  netfilter: ipset: autoload set type modules safely
  netfilter: ipset: dumping error triggered removing references twice

Pablo Neira Ayuso (1):
  netfilter: revert user-space expectation helper support

Stephen Rothwell (1):
  netfilter: xt_hashlimit: fix unused variable warning if IPv6 disabled

 include/linux/netfilter/nf_conntrack_common.h |    4 ---
 include/linux/netfilter/xt_CT.h               |    3 +-
 net/netfilter/ipset/ip_set_core.c             |   37 ++++++++++++++++++-------
 net/netfilter/nf_conntrack_helper.c           |   12 --------
 net/netfilter/nf_conntrack_netlink.c          |    4 ---
 net/netfilter/xt_CT.c                         |    8 ++---
 net/netfilter/xt_hashlimit.c                  |    5 +++-
 7 files changed, 35 insertions(+), 38 deletions(-)

-- 
1.7.7.3

^ permalink raw reply

* [U-Boot] [PATCH] arm, davinci: add PLL0 prediv to da850 lowlevel setup
From: Christian Riesch @ 2012-01-17 11:04 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <1326735795-23399-1-git-send-email-bengardiner@nanometrics.ca>

Hello Ben,

On Mon, Jan 16, 2012 at 6:43 PM, Ben Gardiner
<bengardiner@nanometrics.ca> wrote:
> The OMAP-L138 has a pre-divider available on PLL0.
>
> Add support to da850_lowlevel.c for configuring PLL0's pre-divider. This is
> to achieve certain OPP's -- e.g. the 372MHz OPP used also by Linux.

I noticed that that pre-divider configuration was missing while
working on the lowlevel setup, but then I forgot to add it (and I was
fine with the default)... Thank you for adding it!

Acked-by: Christian Riesch <christian.riesch@omicron.at>

Regards, Christian

^ permalink raw reply

* Re: [PATCH 2/5] ACPI processor: Avoid WARN message on processor driver removal
From: Len Brown @ 2012-01-17 11:02 UTC (permalink / raw)
  To: Thomas Renninger; +Cc: linux-acpi, Bjorn Helgaas
In-Reply-To: <1321569421-46220-3-git-send-email-trenn@suse.de>

On 11/17/2011 05:36 PM, Thomas Renninger wrote:

> Only unregister acpi_idle driver if acpi_idle driver got
> registered.
> 
> Also add a static acpi_idle_active variable for easy and nicer
> checking whether acpi_idle_driver is active (as suggested by
> Bjorn).
> 
> Signed-off-by: Thomas Renninger <trenn@suse.de>
> CC: Len Brown <lenb@kernel.org>
> CC: linux-acpi@vger.kernel.org
> CC: Bjorn Helgaas <bhelgaas@google.com>
> ---
>  drivers/acpi/processor_driver.c |   11 +++++++----
>  1 files changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
> index 3a4fc0c..790623f 100644
> --- a/drivers/acpi/processor_driver.c
> +++ b/drivers/acpi/processor_driver.c
> @@ -110,6 +110,7 @@ static struct cpuidle_driver acpi_idle_driver = {
>  	.name =		"acpi_idle",
>  	.owner =	THIS_MODULE,
>  };
> +static int acpi_idle_active;
>  
>  #define INSTALL_NOTIFY_HANDLER		1
>  #define UNINSTALL_NOTIFY_HANDLER	2
> @@ -508,8 +509,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
>  	acpi_processor_get_throttling_info(pr);
>  	acpi_processor_get_limit_info(pr);
>  
> -
> -	if (cpuidle_get_driver() == &acpi_idle_driver)
> +	if (acpi_idle_active)
>  		acpi_processor_power_init(pr, device);


I think the old cold reads better than the new code,
since I don't have to guess what "acpi_idle_active" means...

Perhaps you can use the existing mechanism where
it is missing to guard the unregister and re-fresh?

thanks,
-Len


^ permalink raw reply

* Re: Xen 4.2 TODO List Update
From: Ian Campbell @ 2012-01-17 11:02 UTC (permalink / raw)
  To: Olaf Hering
  Cc: xen-devel, Keir (Xen.org), Stefano Stabellini, George Dunlap,
	Ian Jackson, Tim (Xen.org), Roger Pau Monne, Andres Lagar-Cavilla,
	Jan Beulich, Anthony Perard
In-Reply-To: <20120117105321.GA11327@aepfle.de>

On Tue, 2012-01-17 at 10:53 +0000, Olaf Hering wrote:
> For libxl, it would be nice to have also libyajl2 support. OpenSuSE 11.4
> was the last version which shipped libyajl1, 12.1 and later seem to have
> just libyajl2.

Roger Pau Monet posted such a patch but it ended up depending on the
switch to autoconf. I will add those two to the next version of the TODO
list, as blockers unless someone objects.

Ian.

^ permalink raw reply

* Re: [PATCH RFC V4 4/5] kvm : pv-ticketlocks support for linux guests running on KVM hypervisor
From: Marcelo Tosatti @ 2012-01-17 11:02 UTC (permalink / raw)
  To: Raghavendra K T
  Cc: Jeremy Fitzhardinge, linux-doc, Peter Zijlstra, Jan Kiszka,
	Virtualization, Paul Mackerras, H. Peter Anvin,
	Stefano Stabellini, Xen, Dave Jiang, KVM, Glauber Costa, X86,
	Ingo Molnar, Avi Kivity, Rik van Riel, Konrad Rzeszutek Wilk,
	Srivatsa Vaddagiri, Sasha Levin, Sedat Dilek, Thomas Gleixner,
	Greg Kroah-Hartman, LKML, Dave Hansen
In-Reply-To: <20120114182645.8604.68884.sendpatchset@oc5400248562.ibm.com>

On Sat, Jan 14, 2012 at 11:56:46PM +0530, Raghavendra K T wrote:
> Extends Linux guest running on KVM hypervisor to support pv-ticketlocks. 
> 
> During smp_boot_cpus  paravirtualied KVM guest detects if the hypervisor has
> required feature (KVM_FEATURE_PVLOCK_KICK) to support pv-ticketlocks. If so,
>  support for pv-ticketlocks is registered via pv_lock_ops.
> 
> Use KVM_HC_KICK_CPU hypercall to wakeup waiting/halted vcpu.
> 
> Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
> Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
> Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
> ---
> diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
> index 7a94987..cf5327c 100644
> --- a/arch/x86/include/asm/kvm_para.h
> +++ b/arch/x86/include/asm/kvm_para.h
> @@ -195,10 +195,20 @@ void kvm_async_pf_task_wait(u32 token);
>  void kvm_async_pf_task_wake(u32 token);
>  u32 kvm_read_and_reset_pf_reason(void);
>  extern void kvm_disable_steal_time(void);
> -#else
> -#define kvm_guest_init() do { } while (0)
> +
> +#ifdef CONFIG_PARAVIRT_SPINLOCKS
> +void __init kvm_spinlock_init(void);
> +#else /* CONFIG_PARAVIRT_SPINLOCKS */
> +static void kvm_spinlock_init(void)
> +{
> +}
> +#endif /* CONFIG_PARAVIRT_SPINLOCKS */
> +
> +#else /* CONFIG_KVM_GUEST */
> +#define kvm_guest_init() do {} while (0)
>  #define kvm_async_pf_task_wait(T) do {} while(0)
>  #define kvm_async_pf_task_wake(T) do {} while(0)
> +
>  static inline u32 kvm_read_and_reset_pf_reason(void)
>  {
>  	return 0;
> diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
> index a9c2116..ec55a0b 100644
> --- a/arch/x86/kernel/kvm.c
> +++ b/arch/x86/kernel/kvm.c
> @@ -33,6 +33,7 @@
>  #include <linux/sched.h>
>  #include <linux/slab.h>
>  #include <linux/kprobes.h>
> +#include <linux/debugfs.h>
>  #include <asm/timer.h>
>  #include <asm/cpu.h>
>  #include <asm/traps.h>
> @@ -545,6 +546,7 @@ static void __init kvm_smp_prepare_boot_cpu(void)
>  #endif
>  	kvm_guest_cpu_init();
>  	native_smp_prepare_boot_cpu();
> +	kvm_spinlock_init();
>  }
>  
>  static void __cpuinit kvm_guest_cpu_online(void *dummy)
> @@ -627,3 +629,250 @@ static __init int activate_jump_labels(void)
>  	return 0;
>  }
>  arch_initcall(activate_jump_labels);
> +
> +#ifdef CONFIG_PARAVIRT_SPINLOCKS
> +
> +enum kvm_contention_stat {
> +	TAKEN_SLOW,
> +	TAKEN_SLOW_PICKUP,
> +	RELEASED_SLOW,
> +	RELEASED_SLOW_KICKED,
> +	NR_CONTENTION_STATS
> +};
> +
> +#ifdef CONFIG_KVM_DEBUG_FS
> +
> +static struct kvm_spinlock_stats
> +{
> +	u32 contention_stats[NR_CONTENTION_STATS];
> +
> +#define HISTO_BUCKETS	30
> +	u32 histo_spin_blocked[HISTO_BUCKETS+1];
> +
> +	u64 time_blocked;
> +} spinlock_stats;
> +
> +static u8 zero_stats;
> +
> +static inline void check_zero(void)
> +{
> +	u8 ret;
> +	u8 old = ACCESS_ONCE(zero_stats);
> +	if (unlikely(old)) {
> +		ret = cmpxchg(&zero_stats, old, 0);
> +		/* This ensures only one fellow resets the stat */
> +		if (ret == old)
> +			memset(&spinlock_stats, 0, sizeof(spinlock_stats));
> +	}
> +}
> +
> +static inline void add_stats(enum kvm_contention_stat var, u32 val)
> +{
> +	check_zero();
> +	spinlock_stats.contention_stats[var] += val;
> +}
> +
> +
> +static inline u64 spin_time_start(void)
> +{
> +	return sched_clock();
> +}
> +
> +static void __spin_time_accum(u64 delta, u32 *array)
> +{
> +	unsigned index = ilog2(delta);
> +
> +	check_zero();
> +
> +	if (index < HISTO_BUCKETS)
> +		array[index]++;
> +	else
> +		array[HISTO_BUCKETS]++;
> +}
> +
> +static inline void spin_time_accum_blocked(u64 start)
> +{
> +	u32 delta = sched_clock() - start;
> +
> +	__spin_time_accum(delta, spinlock_stats.histo_spin_blocked);
> +	spinlock_stats.time_blocked += delta;
> +}
> +
> +static struct dentry *d_spin_debug;
> +static struct dentry *d_kvm_debug;
> +
> +struct dentry *kvm_init_debugfs(void)
> +{
> +	d_kvm_debug = debugfs_create_dir("kvm", NULL);
> +	if (!d_kvm_debug)
> +		printk(KERN_WARNING "Could not create 'kvm' debugfs directory\n");
> +
> +	return d_kvm_debug;
> +}
> +
> +static int __init kvm_spinlock_debugfs(void)
> +{
> +	struct dentry *d_kvm = kvm_init_debugfs();
> +
> +	if (d_kvm == NULL)
> +		return -ENOMEM;
> +
> +	d_spin_debug = debugfs_create_dir("spinlocks", d_kvm);
> +
> +	debugfs_create_u8("zero_stats", 0644, d_spin_debug, &zero_stats);
> +
> +	debugfs_create_u32("taken_slow", 0444, d_spin_debug,
> +		   &spinlock_stats.contention_stats[TAKEN_SLOW]);
> +	debugfs_create_u32("taken_slow_pickup", 0444, d_spin_debug,
> +		   &spinlock_stats.contention_stats[TAKEN_SLOW_PICKUP]);
> +
> +	debugfs_create_u32("released_slow", 0444, d_spin_debug,
> +		   &spinlock_stats.contention_stats[RELEASED_SLOW]);
> +	debugfs_create_u32("released_slow_kicked", 0444, d_spin_debug,
> +		   &spinlock_stats.contention_stats[RELEASED_SLOW_KICKED]);
> +
> +	debugfs_create_u64("time_blocked", 0444, d_spin_debug,
> +			   &spinlock_stats.time_blocked);
> +
> +	debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
> +		     spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1);
> +
> +	return 0;
> +}
> +fs_initcall(kvm_spinlock_debugfs);
> +#else  /* !CONFIG_KVM_DEBUG_FS */
> +#define TIMEOUT			(1 << 10)
> +static inline void add_stats(enum kvm_contention_stat var, u32 val)
> +{
> +}
> +
> +static inline u64 spin_time_start(void)
> +{
> +	return 0;
> +}
> +
> +static inline void spin_time_accum_blocked(u64 start)
> +{
> +}
> +#endif  /* CONFIG_KVM_DEBUG_FS */
> +
> +struct kvm_lock_waiting {
> +	struct arch_spinlock *lock;
> +	__ticket_t want;
> +};
> +
> +/* cpus 'waiting' on a spinlock to become available */
> +static cpumask_t waiting_cpus;
> +
> +/* Track spinlock on which a cpu is waiting */
> +static DEFINE_PER_CPU(struct kvm_lock_waiting, lock_waiting);
> +
> +static void kvm_lock_spinning(struct arch_spinlock *lock, __ticket_t want)
> +{
> +	struct kvm_lock_waiting *w = &__get_cpu_var(lock_waiting);
> +	int cpu = smp_processor_id();
> +	u64 start;
> +	unsigned long flags;
> +
> +	start = spin_time_start();
> +
> +	/*
> +	 * Make sure an interrupt handler can't upset things in a
> +	 * partially setup state.
> +	 */
> +	local_irq_save(flags);
> +
> +	/*
> +	 * The ordering protocol on this is that the "lock" pointer
> +	 * may only be set non-NULL if the "want" ticket is correct.
> +	 * If we're updating "want", we must first clear "lock".
> +	 */
> +	w->lock = NULL;
> +	smp_wmb();
> +	w->want = want;
> +	smp_wmb();
> +	w->lock = lock;
> +
> +	add_stats(TAKEN_SLOW, 1);
> +
> +	/*
> +	 * This uses set_bit, which is atomic but we should not rely on its
> +	 * reordering gurantees. So barrier is needed after this call.
> +	 */
> +	cpumask_set_cpu(cpu, &waiting_cpus);
> +
> +	barrier();
> +
> +	/*
> +	 * Mark entry to slowpath before doing the pickup test to make
> +	 * sure we don't deadlock with an unlocker.
> +	 */
> +	__ticket_enter_slowpath(lock);
> +
> +	/*
> +	 * check again make sure it didn't become free while
> +	 * we weren't looking.
> +	 */
> +	if (ACCESS_ONCE(lock->tickets.head) == want) {
> +		add_stats(TAKEN_SLOW_PICKUP, 1);
> +		goto out;
> +	}
> +
> +	/* Allow interrupts while blocked */
> +	local_irq_restore(flags);
> +
> +	/* halt until it's our turn and kicked. */
> +	halt();
> +
> +	local_irq_save(flags);
> +out:
> +	cpumask_clear_cpu(cpu, &waiting_cpus);
> +	w->lock = NULL;
> +	local_irq_restore(flags);
> +	spin_time_accum_blocked(start);
> +}
> +PV_CALLEE_SAVE_REGS_THUNK(kvm_lock_spinning);
> +
> +/* Kick a cpu by its apicid*/
> +static inline void kvm_kick_cpu(int apicid)
> +{
> +	kvm_hypercall1(KVM_HC_KICK_CPU, apicid);
> +}
> +
> +/* Kick vcpu waiting on @lock->head to reach value @ticket */
> +static void kvm_unlock_kick(struct arch_spinlock *lock, __ticket_t ticket)
> +{
> +	int cpu;
> +	int apicid;
> +
> +	add_stats(RELEASED_SLOW, 1);
> +
> +	for_each_cpu(cpu, &waiting_cpus) {
> +		const struct kvm_lock_waiting *w = &per_cpu(lock_waiting, cpu);
> +		if (ACCESS_ONCE(w->lock) == lock &&
> +		    ACCESS_ONCE(w->want) == ticket) {
> +			add_stats(RELEASED_SLOW_KICKED, 1);
> +			apicid = per_cpu(x86_cpu_to_apicid, cpu);
> +			kvm_kick_cpu(apicid);
> +			break;
> +		}
> +	}

What prevents a kick from being lost here, if say, the waiter is at
local_irq_save in kvm_lock_spinning, before the lock/want assignments?

> +
> +/*
> + * Setup pv_lock_ops to exploit KVM_FEATURE_PVLOCK_KICK if present.
> + */
> +void __init kvm_spinlock_init(void)
> +{
> +	if (!kvm_para_available())
> +		return;
> +	/* Does host kernel support KVM_FEATURE_PVLOCK_KICK? */
> +	if (!kvm_para_has_feature(KVM_FEATURE_PVLOCK_KICK))
> +		return;
> +
> +	jump_label_inc(&paravirt_ticketlocks_enabled);
> +
> +	pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning);
> +	pv_lock_ops.unlock_kick = kvm_unlock_kick;
> +}
> +#endif	/* CONFIG_PARAVIRT_SPINLOCKS */
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index c7b05fc..4d7a950 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -5754,8 +5754,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
>  
>  	local_irq_disable();
>  
> -	if (vcpu->mode == EXITING_GUEST_MODE || vcpu->requests
> -	    || need_resched() || signal_pending(current)) {
> +	if (vcpu->mode == EXITING_GUEST_MODE
> +		 || (vcpu->requests & ~(1UL<<KVM_REQ_PVLOCK_KICK))
> +		 || need_resched() || signal_pending(current)) {
>  		vcpu->mode = OUTSIDE_GUEST_MODE;
>  		smp_wmb();
>  		local_irq_enable();
> @@ -6711,6 +6712,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
>  		!vcpu->arch.apf.halted)
>  		|| !list_empty_careful(&vcpu->async_pf.done)
>  		|| vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED
> +		|| kvm_check_request(KVM_REQ_PVLOCK_KICK, vcpu)

The bit should only be read here (kvm_arch_vcpu_runnable), but cleared
on vcpu entry (along with the other kvm_check_request processing).

Then the first hunk becomes unnecessary.

Please do not mix host/guest patches.

^ permalink raw reply

* Re: [PATCH RFC V4 4/5] kvm : pv-ticketlocks support for linux guests running on KVM hypervisor
From: Marcelo Tosatti @ 2012-01-17 11:02 UTC (permalink / raw)
  To: Raghavendra K T
  Cc: Jeremy Fitzhardinge, linux-doc, Peter Zijlstra, Jan Kiszka,
	Virtualization, Paul Mackerras, H. Peter Anvin,
	Stefano Stabellini, Xen, Dave Jiang, KVM, Glauber Costa, X86,
	Ingo Molnar, Avi Kivity, Rik van Riel, Konrad Rzeszutek Wilk,
	Srivatsa Vaddagiri, Sasha Levin, Sedat Dilek, Thomas Gleixner,
	Greg Kroah-Hartman, LKML, Dave Hansen
In-Reply-To: <20120114182645.8604.68884.sendpatchset@oc5400248562.ibm.com>

On Sat, Jan 14, 2012 at 11:56:46PM +0530, Raghavendra K T wrote:
> Extends Linux guest running on KVM hypervisor to support pv-ticketlocks. 
> 
> During smp_boot_cpus  paravirtualied KVM guest detects if the hypervisor has
> required feature (KVM_FEATURE_PVLOCK_KICK) to support pv-ticketlocks. If so,
>  support for pv-ticketlocks is registered via pv_lock_ops.
> 
> Use KVM_HC_KICK_CPU hypercall to wakeup waiting/halted vcpu.
> 
> Signed-off-by: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
> Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com>
> Signed-off-by: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
> ---
> diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
> index 7a94987..cf5327c 100644
> --- a/arch/x86/include/asm/kvm_para.h
> +++ b/arch/x86/include/asm/kvm_para.h
> @@ -195,10 +195,20 @@ void kvm_async_pf_task_wait(u32 token);
>  void kvm_async_pf_task_wake(u32 token);
>  u32 kvm_read_and_reset_pf_reason(void);
>  extern void kvm_disable_steal_time(void);
> -#else
> -#define kvm_guest_init() do { } while (0)
> +
> +#ifdef CONFIG_PARAVIRT_SPINLOCKS
> +void __init kvm_spinlock_init(void);
> +#else /* CONFIG_PARAVIRT_SPINLOCKS */
> +static void kvm_spinlock_init(void)
> +{
> +}
> +#endif /* CONFIG_PARAVIRT_SPINLOCKS */
> +
> +#else /* CONFIG_KVM_GUEST */
> +#define kvm_guest_init() do {} while (0)
>  #define kvm_async_pf_task_wait(T) do {} while(0)
>  #define kvm_async_pf_task_wake(T) do {} while(0)
> +
>  static inline u32 kvm_read_and_reset_pf_reason(void)
>  {
>  	return 0;
> diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
> index a9c2116..ec55a0b 100644
> --- a/arch/x86/kernel/kvm.c
> +++ b/arch/x86/kernel/kvm.c
> @@ -33,6 +33,7 @@
>  #include <linux/sched.h>
>  #include <linux/slab.h>
>  #include <linux/kprobes.h>
> +#include <linux/debugfs.h>
>  #include <asm/timer.h>
>  #include <asm/cpu.h>
>  #include <asm/traps.h>
> @@ -545,6 +546,7 @@ static void __init kvm_smp_prepare_boot_cpu(void)
>  #endif
>  	kvm_guest_cpu_init();
>  	native_smp_prepare_boot_cpu();
> +	kvm_spinlock_init();
>  }
>  
>  static void __cpuinit kvm_guest_cpu_online(void *dummy)
> @@ -627,3 +629,250 @@ static __init int activate_jump_labels(void)
>  	return 0;
>  }
>  arch_initcall(activate_jump_labels);
> +
> +#ifdef CONFIG_PARAVIRT_SPINLOCKS
> +
> +enum kvm_contention_stat {
> +	TAKEN_SLOW,
> +	TAKEN_SLOW_PICKUP,
> +	RELEASED_SLOW,
> +	RELEASED_SLOW_KICKED,
> +	NR_CONTENTION_STATS
> +};
> +
> +#ifdef CONFIG_KVM_DEBUG_FS
> +
> +static struct kvm_spinlock_stats
> +{
> +	u32 contention_stats[NR_CONTENTION_STATS];
> +
> +#define HISTO_BUCKETS	30
> +	u32 histo_spin_blocked[HISTO_BUCKETS+1];
> +
> +	u64 time_blocked;
> +} spinlock_stats;
> +
> +static u8 zero_stats;
> +
> +static inline void check_zero(void)
> +{
> +	u8 ret;
> +	u8 old = ACCESS_ONCE(zero_stats);
> +	if (unlikely(old)) {
> +		ret = cmpxchg(&zero_stats, old, 0);
> +		/* This ensures only one fellow resets the stat */
> +		if (ret == old)
> +			memset(&spinlock_stats, 0, sizeof(spinlock_stats));
> +	}
> +}
> +
> +static inline void add_stats(enum kvm_contention_stat var, u32 val)
> +{
> +	check_zero();
> +	spinlock_stats.contention_stats[var] += val;
> +}
> +
> +
> +static inline u64 spin_time_start(void)
> +{
> +	return sched_clock();
> +}
> +
> +static void __spin_time_accum(u64 delta, u32 *array)
> +{
> +	unsigned index = ilog2(delta);
> +
> +	check_zero();
> +
> +	if (index < HISTO_BUCKETS)
> +		array[index]++;
> +	else
> +		array[HISTO_BUCKETS]++;
> +}
> +
> +static inline void spin_time_accum_blocked(u64 start)
> +{
> +	u32 delta = sched_clock() - start;
> +
> +	__spin_time_accum(delta, spinlock_stats.histo_spin_blocked);
> +	spinlock_stats.time_blocked += delta;
> +}
> +
> +static struct dentry *d_spin_debug;
> +static struct dentry *d_kvm_debug;
> +
> +struct dentry *kvm_init_debugfs(void)
> +{
> +	d_kvm_debug = debugfs_create_dir("kvm", NULL);
> +	if (!d_kvm_debug)
> +		printk(KERN_WARNING "Could not create 'kvm' debugfs directory\n");
> +
> +	return d_kvm_debug;
> +}
> +
> +static int __init kvm_spinlock_debugfs(void)
> +{
> +	struct dentry *d_kvm = kvm_init_debugfs();
> +
> +	if (d_kvm == NULL)
> +		return -ENOMEM;
> +
> +	d_spin_debug = debugfs_create_dir("spinlocks", d_kvm);
> +
> +	debugfs_create_u8("zero_stats", 0644, d_spin_debug, &zero_stats);
> +
> +	debugfs_create_u32("taken_slow", 0444, d_spin_debug,
> +		   &spinlock_stats.contention_stats[TAKEN_SLOW]);
> +	debugfs_create_u32("taken_slow_pickup", 0444, d_spin_debug,
> +		   &spinlock_stats.contention_stats[TAKEN_SLOW_PICKUP]);
> +
> +	debugfs_create_u32("released_slow", 0444, d_spin_debug,
> +		   &spinlock_stats.contention_stats[RELEASED_SLOW]);
> +	debugfs_create_u32("released_slow_kicked", 0444, d_spin_debug,
> +		   &spinlock_stats.contention_stats[RELEASED_SLOW_KICKED]);
> +
> +	debugfs_create_u64("time_blocked", 0444, d_spin_debug,
> +			   &spinlock_stats.time_blocked);
> +
> +	debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
> +		     spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1);
> +
> +	return 0;
> +}
> +fs_initcall(kvm_spinlock_debugfs);
> +#else  /* !CONFIG_KVM_DEBUG_FS */
> +#define TIMEOUT			(1 << 10)
> +static inline void add_stats(enum kvm_contention_stat var, u32 val)
> +{
> +}
> +
> +static inline u64 spin_time_start(void)
> +{
> +	return 0;
> +}
> +
> +static inline void spin_time_accum_blocked(u64 start)
> +{
> +}
> +#endif  /* CONFIG_KVM_DEBUG_FS */
> +
> +struct kvm_lock_waiting {
> +	struct arch_spinlock *lock;
> +	__ticket_t want;
> +};
> +
> +/* cpus 'waiting' on a spinlock to become available */
> +static cpumask_t waiting_cpus;
> +
> +/* Track spinlock on which a cpu is waiting */
> +static DEFINE_PER_CPU(struct kvm_lock_waiting, lock_waiting);
> +
> +static void kvm_lock_spinning(struct arch_spinlock *lock, __ticket_t want)
> +{
> +	struct kvm_lock_waiting *w = &__get_cpu_var(lock_waiting);
> +	int cpu = smp_processor_id();
> +	u64 start;
> +	unsigned long flags;
> +
> +	start = spin_time_start();
> +
> +	/*
> +	 * Make sure an interrupt handler can't upset things in a
> +	 * partially setup state.
> +	 */
> +	local_irq_save(flags);
> +
> +	/*
> +	 * The ordering protocol on this is that the "lock" pointer
> +	 * may only be set non-NULL if the "want" ticket is correct.
> +	 * If we're updating "want", we must first clear "lock".
> +	 */
> +	w->lock = NULL;
> +	smp_wmb();
> +	w->want = want;
> +	smp_wmb();
> +	w->lock = lock;
> +
> +	add_stats(TAKEN_SLOW, 1);
> +
> +	/*
> +	 * This uses set_bit, which is atomic but we should not rely on its
> +	 * reordering gurantees. So barrier is needed after this call.
> +	 */
> +	cpumask_set_cpu(cpu, &waiting_cpus);
> +
> +	barrier();
> +
> +	/*
> +	 * Mark entry to slowpath before doing the pickup test to make
> +	 * sure we don't deadlock with an unlocker.
> +	 */
> +	__ticket_enter_slowpath(lock);
> +
> +	/*
> +	 * check again make sure it didn't become free while
> +	 * we weren't looking.
> +	 */
> +	if (ACCESS_ONCE(lock->tickets.head) == want) {
> +		add_stats(TAKEN_SLOW_PICKUP, 1);
> +		goto out;
> +	}
> +
> +	/* Allow interrupts while blocked */
> +	local_irq_restore(flags);
> +
> +	/* halt until it's our turn and kicked. */
> +	halt();
> +
> +	local_irq_save(flags);
> +out:
> +	cpumask_clear_cpu(cpu, &waiting_cpus);
> +	w->lock = NULL;
> +	local_irq_restore(flags);
> +	spin_time_accum_blocked(start);
> +}
> +PV_CALLEE_SAVE_REGS_THUNK(kvm_lock_spinning);
> +
> +/* Kick a cpu by its apicid*/
> +static inline void kvm_kick_cpu(int apicid)
> +{
> +	kvm_hypercall1(KVM_HC_KICK_CPU, apicid);
> +}
> +
> +/* Kick vcpu waiting on @lock->head to reach value @ticket */
> +static void kvm_unlock_kick(struct arch_spinlock *lock, __ticket_t ticket)
> +{
> +	int cpu;
> +	int apicid;
> +
> +	add_stats(RELEASED_SLOW, 1);
> +
> +	for_each_cpu(cpu, &waiting_cpus) {
> +		const struct kvm_lock_waiting *w = &per_cpu(lock_waiting, cpu);
> +		if (ACCESS_ONCE(w->lock) == lock &&
> +		    ACCESS_ONCE(w->want) == ticket) {
> +			add_stats(RELEASED_SLOW_KICKED, 1);
> +			apicid = per_cpu(x86_cpu_to_apicid, cpu);
> +			kvm_kick_cpu(apicid);
> +			break;
> +		}
> +	}

What prevents a kick from being lost here, if say, the waiter is at
local_irq_save in kvm_lock_spinning, before the lock/want assignments?

> +
> +/*
> + * Setup pv_lock_ops to exploit KVM_FEATURE_PVLOCK_KICK if present.
> + */
> +void __init kvm_spinlock_init(void)
> +{
> +	if (!kvm_para_available())
> +		return;
> +	/* Does host kernel support KVM_FEATURE_PVLOCK_KICK? */
> +	if (!kvm_para_has_feature(KVM_FEATURE_PVLOCK_KICK))
> +		return;
> +
> +	jump_label_inc(&paravirt_ticketlocks_enabled);
> +
> +	pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning);
> +	pv_lock_ops.unlock_kick = kvm_unlock_kick;
> +}
> +#endif	/* CONFIG_PARAVIRT_SPINLOCKS */
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index c7b05fc..4d7a950 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -5754,8 +5754,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
>  
>  	local_irq_disable();
>  
> -	if (vcpu->mode == EXITING_GUEST_MODE || vcpu->requests
> -	    || need_resched() || signal_pending(current)) {
> +	if (vcpu->mode == EXITING_GUEST_MODE
> +		 || (vcpu->requests & ~(1UL<<KVM_REQ_PVLOCK_KICK))
> +		 || need_resched() || signal_pending(current)) {
>  		vcpu->mode = OUTSIDE_GUEST_MODE;
>  		smp_wmb();
>  		local_irq_enable();
> @@ -6711,6 +6712,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
>  		!vcpu->arch.apf.halted)
>  		|| !list_empty_careful(&vcpu->async_pf.done)
>  		|| vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED
> +		|| kvm_check_request(KVM_REQ_PVLOCK_KICK, vcpu)

The bit should only be read here (kvm_arch_vcpu_runnable), but cleared
on vcpu entry (along with the other kvm_check_request processing).

Then the first hunk becomes unnecessary.

Please do not mix host/guest patches.

^ permalink raw reply

* Re: [patch v2, kernel version 3.2.1] net/ipv4/ip_gre: Ethernet multipoint GRE over IP
From: Štefan Gula @ 2012-01-17 11:00 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Alexey Kuznetsov, David S. Miller, James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy, netdev, linux-kernel
In-Reply-To: <1326797276.2259.3.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 17278 bytes --]

Dňa 17. januára 2012 11:47, Eric Dumazet <eric.dumazet@gmail.com> napísal/a:
> Le mardi 17 janvier 2012 à 11:43 +0100, Štefan Gula a écrit :
>
>> ok maybe I am getting it wrong, but I am little bit stuck here. I
>> recheck the original bridge code. The difference I recognize is that
>> in bridge code function:
>> br_fdb_init() and br_fdb_fini()
>> are called from module init and module exit functions:
>> br_init and br_deinit
>>
>> in my code they are called from functions:
>> ipgre_init_net and ipgre_exit_net
>> instead of:
>> ipgre_init and ipgre_fini
>>
>> To be honest I am not so familiar enough with kernel structure that I
>> see the difference on the first time. But I think that with your help
>> it can be done easily. The main idea was to create hash-table that is
>> used to determine the destination IPv4 address (part of the entry
>> structure). That hash-table should be different per each gretap
>> interface - I think that's the reason why I put those init and fini
>> inside ipgre_init_net and ipgre_exit_net. Am I right that the
>> placement of this calls is correct or not? If not where those calls
>> should be placed?
>>
>> On the other hand I have no idea how to substitute those two function
>> with a code that you are suggesting kmalloc()/kfree(). I would be glad
>> if you can help me here by providing me example how to substitute
>> those two functions with kmalloc/kfree for the future usage (I am more
>> reverse engineer learner type of person than manuals reading one)
>
> Something like the following ?
>
>
> Note : I also put the "orig_source = iph->saddr;"
> _after_ "iph = ip_hdr(skb);"
>
>                        iph = ip_hdr(skb);
> #ifdef CONFIG_NET_IPGRE_BRIDGE
>                        orig_source = iph->saddr;
> #endif
>
>
>
> diff --git a/include/net/ipip.h b/include/net/ipip.h
> index a32654d..6a06fc2 100644
> --- a/include/net/ipip.h
> +++ b/include/net/ipip.h
> @@ -27,6 +27,14 @@ struct ip_tunnel {
>        __u32                   o_seqno;        /* The last output seqno */
>        int                     hlen;           /* Precalculated GRE header length */
>        int                     mlink;
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +#define GRETAP_BR_HASH_BITS 8
> +#define GRETAP_BR_HASH_SIZE (1 << GRETAP_BR_HASH_BITS)
> +       struct hlist_head       hash[GRETAP_BR_HASH_SIZE];
> +       spinlock_t              hash_lock;
> +       unsigned long           ageing_time;
> +       struct timer_list       gc_timer;
> +#endif
>
>        struct ip_tunnel_parm   parms;
>
> diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
> index 1a8f93b..5b320a3 100644
> --- a/net/ipv4/Kconfig
> +++ b/net/ipv4/Kconfig
> @@ -211,6 +211,15 @@ config NET_IPGRE_BROADCAST
>          Network), but can be distributed all over the Internet. If you want
>          to do that, say Y here and to "IP multicast routing" below.
>
> +config NET_IPGRE_BRIDGE
> +       bool "IP: Ethernet over multipoint GRE over IP"
> +       depends on IP_MULTICAST && NET_IPGRE && NET_IPGRE_BROADCAST
> +       help
> +         Allows you to use multipoint GRE VPN as virtual switch and interconnect
> +         several L2 endpoints over L3 routed infrastructure. It is useful for
> +         creating multipoint L2 VPNs which can be later used inside bridge
> +         interfaces If you want to use. GRE multipoint L2 VPN feature say Y.
> +
>  config IP_MROUTE
>        bool "IP: multicast routing"
>        depends on IP_MULTICAST
> diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
> index 2b53a1f..df22565 100644
> --- a/net/ipv4/ip_gre.c
> +++ b/net/ipv4/ip_gre.c
> @@ -52,6 +52,11 @@
>  #include <net/ip6_route.h>
>  #endif
>
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +#include <linux/jhash.h>
> +#include <asm/unaligned.h>
> +#endif
> +
>  /*
>    Problems & solutions
>    --------------------
> @@ -134,6 +139,172 @@ struct ipgre_net {
>        struct net_device *fb_tunnel_dev;
>  };
>
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +       /*
> +        * This part of code includes codes to enable L2 ethernet
> +        * switch virtualization over IP routed infrastructure with
> +        * utilization of multicast capable endpoint using Ethernet
> +        * over GRE
> +        *
> +        * Author: Stefan Gula
> +        * Signed-off-by: Stefan Gula <steweg@gmail.com>
> +        */
> +struct ipgre_tap_bridge_entry {
> +       struct hlist_node       hlist;
> +       __be32                  raddr;
> +       unsigned char           addr[ETH_ALEN];
> +       unsigned long           updated;
> +       struct rcu_head         rcu;
> +};
> +
> +static u32 ipgre_salt __read_mostly;
> +
> +static inline int ipgre_tap_bridge_hash(const unsigned char *mac)
> +{
> +       u32 key = get_unaligned((u32 *)(mac + 2));
> +
> +       return jhash_1word(key, ipgre_salt) & (GRETAP_BR_HASH_SIZE - 1);
> +}
> +
> +static inline int ipgre_tap_bridge_has_expired(const struct ip_tunnel *tunnel,
> +                               const struct ipgre_tap_bridge_entry *entry)
> +{
> +       return time_before_eq(entry->updated + tunnel->ageing_time,
> +                             jiffies);
> +}
> +
> +static inline void ipgre_tap_bridge_delete(struct ipgre_tap_bridge_entry *entry)
> +{
> +       hlist_del_rcu(&entry->hlist);
> +       kfree_rcu(entry, rcu);
> +}
> +
> +static void ipgre_tap_bridge_cleanup(unsigned long _data)
> +{
> +       struct ip_tunnel *tunnel = (struct ip_tunnel *)_data;
> +       unsigned long delay = tunnel->ageing_time;
> +       unsigned long next_timer = jiffies + tunnel->ageing_time;
> +       int i;
> +
> +       spin_lock(&tunnel->hash_lock);
> +       for (i = 0; i < GRETAP_BR_HASH_SIZE; i++) {
> +               struct ipgre_tap_bridge_entry *entry;
> +               struct hlist_node *h, *n;
> +
> +               hlist_for_each_entry_safe(entry, h, n,
> +                       &tunnel->hash[i], hlist)
> +               {
> +                       unsigned long this_timer;
> +                       this_timer = entry->updated + delay;
> +                       if (time_before_eq(this_timer, jiffies))
> +                               ipgre_tap_bridge_delete(entry);
> +                       else if (time_before(this_timer, next_timer))
> +                               next_timer = this_timer;
> +               }
> +       }
> +       spin_unlock(&tunnel->hash_lock);
> +       mod_timer(&tunnel->gc_timer, round_jiffies_up(next_timer));
> +}
> +
> +static void ipgre_tap_bridge_flush(struct ip_tunnel *tunnel)
> +{
> +       int i;
> +
> +       spin_lock_bh(&tunnel->hash_lock);
> +       for (i = 0; i < GRETAP_BR_HASH_SIZE; i++) {
> +               struct ipgre_tap_bridge_entry *entry;
> +               struct hlist_node *h, *n;
> +
> +               hlist_for_each_entry_safe(entry, h, n,
> +                       &tunnel->hash[i], hlist)
> +               {
> +                       ipgre_tap_bridge_delete(entry);
> +               }
> +       }
> +       spin_unlock_bh(&tunnel->hash_lock);
> +}
> +
> +static struct ipgre_tap_bridge_entry *__ipgre_tap_bridge_get(
> +       struct ip_tunnel *tunnel, const unsigned char *addr)
> +{
> +       struct hlist_node *h;
> +       struct ipgre_tap_bridge_entry *entry;
> +
> +       hlist_for_each_entry_rcu(entry, h,
> +                       &tunnel->hash[ipgre_tap_bridge_hash(addr)], hlist) {
> +               if (!compare_ether_addr(entry->addr, addr)) {
> +                       if (unlikely(ipgre_tap_bridge_has_expired(tunnel,
> +                               entry)))
> +                               break;
> +                       return entry;
> +               }
> +       }
> +
> +       return NULL;
> +}
> +
> +static struct ipgre_tap_bridge_entry *ipgre_tap_bridge_find(
> +       struct hlist_head *head,
> +       const unsigned char *addr)
> +{
> +       struct hlist_node *h;
> +       struct ipgre_tap_bridge_entry *entry;
> +
> +       hlist_for_each_entry(entry, h, head, hlist) {
> +               if (!compare_ether_addr(entry->addr, addr))
> +                       return entry;
> +       }
> +       return NULL;
> +}
> +
> +
> +static struct ipgre_tap_bridge_entry *ipgre_tap_bridge_find_rcu(
> +       struct hlist_head *head,
> +       const unsigned char *addr)
> +{
> +       struct hlist_node *h;
> +       struct ipgre_tap_bridge_entry *entry;
> +
> +       hlist_for_each_entry_rcu(entry, h, head, hlist) {
> +               if (!compare_ether_addr(entry->addr, addr))
> +                       return entry;
> +       }
> +       return NULL;
> +}
> +
> +static struct ipgre_tap_bridge_entry *ipgre_tap_bridge_create(
> +       struct hlist_head *head,
> +       u32 source,
> +       const unsigned char *addr)
> +{
> +       struct ipgre_tap_bridge_entry *entry;
> +
> +       entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
> +       if (entry) {
> +               memcpy(entry->addr, addr, ETH_ALEN);
> +               entry->raddr = source;
> +               entry->updated = jiffies;
> +               hlist_add_head_rcu(&entry->hlist, head);
> +       }
> +       return entry;
> +}
> +
> +static __be32 ipgre_tap_bridge_get_raddr(struct ip_tunnel *tunnel,
> +       const unsigned char *addr)
> +{
> +       __be32 raddr = 0;
> +       struct ipgre_tap_bridge_entry *entry;
> +
> +       rcu_read_lock();
> +       entry = __ipgre_tap_bridge_get(tunnel, addr);
> +       if (entry)
> +               raddr = entry->raddr;
> +       rcu_read_unlock();
> +
> +       return raddr;
> +}
> +
> +#endif
>  /* Tunnel hash table */
>
>  /*
> @@ -562,6 +733,12 @@ static int ipgre_rcv(struct sk_buff *skb)
>        struct ip_tunnel *tunnel;
>        int    offset = 4;
>        __be16 gre_proto;
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +       __be32 orig_source;
> +       struct hlist_head *head;
> +       struct ipgre_tap_bridge_entry *entry;
> +       const struct ethhdr *tethhdr;
> +#endif
>
>        if (!pskb_may_pull(skb, 16))
>                goto drop_nolock;
> @@ -659,10 +836,38 @@ static int ipgre_rcv(struct sk_buff *skb)
>                                tunnel->dev->stats.rx_errors++;
>                                goto drop;
>                        }
> -
>                        iph = ip_hdr(skb);
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +                       orig_source = iph->saddr;
> +#endif
>                        skb->protocol = eth_type_trans(skb, tunnel->dev);
>                        skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +                       if (ipv4_is_multicast(tunnel->parms.iph.daddr)) {
> +                               tethhdr = eth_hdr(skb);
> +                               if (!is_multicast_ether_addr(
> +                                       tethhdr->h_source)) {
> +                                       head = &tunnel->hash[
> +                                               ipgre_tap_bridge_hash(
> +                                                       tethhdr->h_source)];
> +                                       entry = ipgre_tap_bridge_find_rcu(head,
> +                                               tethhdr->h_source);
> +                                       if (likely(entry)) {
> +                                               entry->raddr = orig_source;
> +                                               entry->updated = jiffies;
> +                                       } else {
> +                                         spin_lock(&tunnel->hash_lock);
> +                                         if (!ipgre_tap_bridge_find(head,
> +                                               tethhdr->h_source))
> +                                               ipgre_tap_bridge_create(
> +                                                       head,
> +                                                       orig_source,
> +                                                       tethhdr->h_source);
> +                                         spin_unlock(&tunnel->hash_lock);
> +                                       }
> +                               }
> +                       }
> +#endif
>                }
>
>                tstats = this_cpu_ptr(tunnel->dev->tstats);
> @@ -702,7 +907,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
>        struct iphdr  *iph;                     /* Our new IP header */
>        unsigned int max_headroom;              /* The extra header space needed */
>        int    gre_hlen;
> -       __be32 dst;
> +       __be32 dst = 0;
>        int    mtu;
>
>        if (dev->type == ARPHRD_ETHER)
> @@ -716,7 +921,15 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
>                tiph = &tunnel->parms.iph;
>        }
>
> -       if ((dst = tiph->daddr) == 0) {
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +       if ((dev->type == ARPHRD_ETHER) &&
> +               ipv4_is_multicast(tunnel->parms.iph.daddr))
> +               dst = ipgre_tap_bridge_get_raddr(tunnel,
> +                       ((struct ethhdr *)skb->data)->h_dest);
> +#endif
> +       if (dst == 0)
> +               dst = tiph->daddr;
> +       if (dst == 0) {
>                /* NBMA tunnel */
>
>                if (skb_dst(skb) == NULL) {
> @@ -1211,6 +1424,16 @@ static int ipgre_open(struct net_device *dev)
>                        return -EADDRNOTAVAIL;
>                t->mlink = dev->ifindex;
>                ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +               if (t->dev->type == ARPHRD_ETHER) {
> +                       INIT_HLIST_HEAD(t->hash);
> +                       spin_lock_init(&t->hash_lock);
> +                       t->ageing_time = 300 * HZ;
> +                       setup_timer(&t->gc_timer, ipgre_tap_bridge_cleanup,
> +                               (unsigned long) t);
> +                       mod_timer(&t->gc_timer, jiffies + t->ageing_time);
> +               }
> +#endif
>        }
>        return 0;
>  }
> @@ -1221,6 +1444,12 @@ static int ipgre_close(struct net_device *dev)
>
>        if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
>                struct in_device *in_dev;
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +               if (t->dev->type == ARPHRD_ETHER) {
> +                       ipgre_tap_bridge_flush(t);
> +                       del_timer_sync(&t->gc_timer);
> +               }
> +#endif
>                in_dev = inetdev_by_index(dev_net(dev), t->mlink);
>                if (in_dev)
>                        ip_mc_dec_group(in_dev, t->parms.iph.daddr);
> @@ -1707,6 +1936,9 @@ static int __init ipgre_init(void)
>
>        printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
>
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +       get_random_bytes(&ipgre_salt, sizeof(ipgre_salt));
> +#endif
>        err = register_pernet_device(&ipgre_net_ops);
>        if (err < 0)
>                return err;
>
>
looks good... I am just wondering whether my previous question about
the placement of calls for ipgre_tap_bridge_init and
ipgre_tap_bridge_fini? Would it be also possible to have this
done/fixed when I migrate those inside the ipgre_init and ipgre_fini ?
I would like to have much rather identical parts of code with standard
bridge code just in case somebody would start doing generalization of
bridge code which can be then reused anywhere inside the kernel space
- simpler migration process later.
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply

* Re: [patch v2, kernel version 3.2.1] net/ipv4/ip_gre: Ethernet multipoint GRE over IP
From: Štefan Gula @ 2012-01-17 11:00 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Alexey Kuznetsov, David S. Miller, James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy, netdev, linux-kernel
In-Reply-To: <1326797276.2259.3.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

Dňa 17. januára 2012 11:47, Eric Dumazet <eric.dumazet@gmail.com> napísal/a:
> Le mardi 17 janvier 2012 à 11:43 +0100, Štefan Gula a écrit :
>
>> ok maybe I am getting it wrong, but I am little bit stuck here. I
>> recheck the original bridge code. The difference I recognize is that
>> in bridge code function:
>> br_fdb_init() and br_fdb_fini()
>> are called from module init and module exit functions:
>> br_init and br_deinit
>>
>> in my code they are called from functions:
>> ipgre_init_net and ipgre_exit_net
>> instead of:
>> ipgre_init and ipgre_fini
>>
>> To be honest I am not so familiar enough with kernel structure that I
>> see the difference on the first time. But I think that with your help
>> it can be done easily. The main idea was to create hash-table that is
>> used to determine the destination IPv4 address (part of the entry
>> structure). That hash-table should be different per each gretap
>> interface - I think that's the reason why I put those init and fini
>> inside ipgre_init_net and ipgre_exit_net. Am I right that the
>> placement of this calls is correct or not? If not where those calls
>> should be placed?
>>
>> On the other hand I have no idea how to substitute those two function
>> with a code that you are suggesting kmalloc()/kfree(). I would be glad
>> if you can help me here by providing me example how to substitute
>> those two functions with kmalloc/kfree for the future usage (I am more
>> reverse engineer learner type of person than manuals reading one)
>
> Something like the following ?
>
>
> Note : I also put the "orig_source = iph->saddr;"
> _after_ "iph = ip_hdr(skb);"
>
>                        iph = ip_hdr(skb);
> #ifdef CONFIG_NET_IPGRE_BRIDGE
>                        orig_source = iph->saddr;
> #endif
>
>
>
> diff --git a/include/net/ipip.h b/include/net/ipip.h
> index a32654d..6a06fc2 100644
> --- a/include/net/ipip.h
> +++ b/include/net/ipip.h
> @@ -27,6 +27,14 @@ struct ip_tunnel {
>        __u32                   o_seqno;        /* The last output seqno */
>        int                     hlen;           /* Precalculated GRE header length */
>        int                     mlink;
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +#define GRETAP_BR_HASH_BITS 8
> +#define GRETAP_BR_HASH_SIZE (1 << GRETAP_BR_HASH_BITS)
> +       struct hlist_head       hash[GRETAP_BR_HASH_SIZE];
> +       spinlock_t              hash_lock;
> +       unsigned long           ageing_time;
> +       struct timer_list       gc_timer;
> +#endif
>
>        struct ip_tunnel_parm   parms;
>
> diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
> index 1a8f93b..5b320a3 100644
> --- a/net/ipv4/Kconfig
> +++ b/net/ipv4/Kconfig
> @@ -211,6 +211,15 @@ config NET_IPGRE_BROADCAST
>          Network), but can be distributed all over the Internet. If you want
>          to do that, say Y here and to "IP multicast routing" below.
>
> +config NET_IPGRE_BRIDGE
> +       bool "IP: Ethernet over multipoint GRE over IP"
> +       depends on IP_MULTICAST && NET_IPGRE && NET_IPGRE_BROADCAST
> +       help
> +         Allows you to use multipoint GRE VPN as virtual switch and interconnect
> +         several L2 endpoints over L3 routed infrastructure. It is useful for
> +         creating multipoint L2 VPNs which can be later used inside bridge
> +         interfaces If you want to use. GRE multipoint L2 VPN feature say Y.
> +
>  config IP_MROUTE
>        bool "IP: multicast routing"
>        depends on IP_MULTICAST
> diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
> index 2b53a1f..df22565 100644
> --- a/net/ipv4/ip_gre.c
> +++ b/net/ipv4/ip_gre.c
> @@ -52,6 +52,11 @@
>  #include <net/ip6_route.h>
>  #endif
>
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +#include <linux/jhash.h>
> +#include <asm/unaligned.h>
> +#endif
> +
>  /*
>    Problems & solutions
>    --------------------
> @@ -134,6 +139,172 @@ struct ipgre_net {
>        struct net_device *fb_tunnel_dev;
>  };
>
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +       /*
> +        * This part of code includes codes to enable L2 ethernet
> +        * switch virtualization over IP routed infrastructure with
> +        * utilization of multicast capable endpoint using Ethernet
> +        * over GRE
> +        *
> +        * Author: Stefan Gula
> +        * Signed-off-by: Stefan Gula <steweg@gmail.com>
> +        */
> +struct ipgre_tap_bridge_entry {
> +       struct hlist_node       hlist;
> +       __be32                  raddr;
> +       unsigned char           addr[ETH_ALEN];
> +       unsigned long           updated;
> +       struct rcu_head         rcu;
> +};
> +
> +static u32 ipgre_salt __read_mostly;
> +
> +static inline int ipgre_tap_bridge_hash(const unsigned char *mac)
> +{
> +       u32 key = get_unaligned((u32 *)(mac + 2));
> +
> +       return jhash_1word(key, ipgre_salt) & (GRETAP_BR_HASH_SIZE - 1);
> +}
> +
> +static inline int ipgre_tap_bridge_has_expired(const struct ip_tunnel *tunnel,
> +                               const struct ipgre_tap_bridge_entry *entry)
> +{
> +       return time_before_eq(entry->updated + tunnel->ageing_time,
> +                             jiffies);
> +}
> +
> +static inline void ipgre_tap_bridge_delete(struct ipgre_tap_bridge_entry *entry)
> +{
> +       hlist_del_rcu(&entry->hlist);
> +       kfree_rcu(entry, rcu);
> +}
> +
> +static void ipgre_tap_bridge_cleanup(unsigned long _data)
> +{
> +       struct ip_tunnel *tunnel = (struct ip_tunnel *)_data;
> +       unsigned long delay = tunnel->ageing_time;
> +       unsigned long next_timer = jiffies + tunnel->ageing_time;
> +       int i;
> +
> +       spin_lock(&tunnel->hash_lock);
> +       for (i = 0; i < GRETAP_BR_HASH_SIZE; i++) {
> +               struct ipgre_tap_bridge_entry *entry;
> +               struct hlist_node *h, *n;
> +
> +               hlist_for_each_entry_safe(entry, h, n,
> +                       &tunnel->hash[i], hlist)
> +               {
> +                       unsigned long this_timer;
> +                       this_timer = entry->updated + delay;
> +                       if (time_before_eq(this_timer, jiffies))
> +                               ipgre_tap_bridge_delete(entry);
> +                       else if (time_before(this_timer, next_timer))
> +                               next_timer = this_timer;
> +               }
> +       }
> +       spin_unlock(&tunnel->hash_lock);
> +       mod_timer(&tunnel->gc_timer, round_jiffies_up(next_timer));
> +}
> +
> +static void ipgre_tap_bridge_flush(struct ip_tunnel *tunnel)
> +{
> +       int i;
> +
> +       spin_lock_bh(&tunnel->hash_lock);
> +       for (i = 0; i < GRETAP_BR_HASH_SIZE; i++) {
> +               struct ipgre_tap_bridge_entry *entry;
> +               struct hlist_node *h, *n;
> +
> +               hlist_for_each_entry_safe(entry, h, n,
> +                       &tunnel->hash[i], hlist)
> +               {
> +                       ipgre_tap_bridge_delete(entry);
> +               }
> +       }
> +       spin_unlock_bh(&tunnel->hash_lock);
> +}
> +
> +static struct ipgre_tap_bridge_entry *__ipgre_tap_bridge_get(
> +       struct ip_tunnel *tunnel, const unsigned char *addr)
> +{
> +       struct hlist_node *h;
> +       struct ipgre_tap_bridge_entry *entry;
> +
> +       hlist_for_each_entry_rcu(entry, h,
> +                       &tunnel->hash[ipgre_tap_bridge_hash(addr)], hlist) {
> +               if (!compare_ether_addr(entry->addr, addr)) {
> +                       if (unlikely(ipgre_tap_bridge_has_expired(tunnel,
> +                               entry)))
> +                               break;
> +                       return entry;
> +               }
> +       }
> +
> +       return NULL;
> +}
> +
> +static struct ipgre_tap_bridge_entry *ipgre_tap_bridge_find(
> +       struct hlist_head *head,
> +       const unsigned char *addr)
> +{
> +       struct hlist_node *h;
> +       struct ipgre_tap_bridge_entry *entry;
> +
> +       hlist_for_each_entry(entry, h, head, hlist) {
> +               if (!compare_ether_addr(entry->addr, addr))
> +                       return entry;
> +       }
> +       return NULL;
> +}
> +
> +
> +static struct ipgre_tap_bridge_entry *ipgre_tap_bridge_find_rcu(
> +       struct hlist_head *head,
> +       const unsigned char *addr)
> +{
> +       struct hlist_node *h;
> +       struct ipgre_tap_bridge_entry *entry;
> +
> +       hlist_for_each_entry_rcu(entry, h, head, hlist) {
> +               if (!compare_ether_addr(entry->addr, addr))
> +                       return entry;
> +       }
> +       return NULL;
> +}
> +
> +static struct ipgre_tap_bridge_entry *ipgre_tap_bridge_create(
> +       struct hlist_head *head,
> +       u32 source,
> +       const unsigned char *addr)
> +{
> +       struct ipgre_tap_bridge_entry *entry;
> +
> +       entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
> +       if (entry) {
> +               memcpy(entry->addr, addr, ETH_ALEN);
> +               entry->raddr = source;
> +               entry->updated = jiffies;
> +               hlist_add_head_rcu(&entry->hlist, head);
> +       }
> +       return entry;
> +}
> +
> +static __be32 ipgre_tap_bridge_get_raddr(struct ip_tunnel *tunnel,
> +       const unsigned char *addr)
> +{
> +       __be32 raddr = 0;
> +       struct ipgre_tap_bridge_entry *entry;
> +
> +       rcu_read_lock();
> +       entry = __ipgre_tap_bridge_get(tunnel, addr);
> +       if (entry)
> +               raddr = entry->raddr;
> +       rcu_read_unlock();
> +
> +       return raddr;
> +}
> +
> +#endif
>  /* Tunnel hash table */
>
>  /*
> @@ -562,6 +733,12 @@ static int ipgre_rcv(struct sk_buff *skb)
>        struct ip_tunnel *tunnel;
>        int    offset = 4;
>        __be16 gre_proto;
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +       __be32 orig_source;
> +       struct hlist_head *head;
> +       struct ipgre_tap_bridge_entry *entry;
> +       const struct ethhdr *tethhdr;
> +#endif
>
>        if (!pskb_may_pull(skb, 16))
>                goto drop_nolock;
> @@ -659,10 +836,38 @@ static int ipgre_rcv(struct sk_buff *skb)
>                                tunnel->dev->stats.rx_errors++;
>                                goto drop;
>                        }
> -
>                        iph = ip_hdr(skb);
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +                       orig_source = iph->saddr;
> +#endif
>                        skb->protocol = eth_type_trans(skb, tunnel->dev);
>                        skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +                       if (ipv4_is_multicast(tunnel->parms.iph.daddr)) {
> +                               tethhdr = eth_hdr(skb);
> +                               if (!is_multicast_ether_addr(
> +                                       tethhdr->h_source)) {
> +                                       head = &tunnel->hash[
> +                                               ipgre_tap_bridge_hash(
> +                                                       tethhdr->h_source)];
> +                                       entry = ipgre_tap_bridge_find_rcu(head,
> +                                               tethhdr->h_source);
> +                                       if (likely(entry)) {
> +                                               entry->raddr = orig_source;
> +                                               entry->updated = jiffies;
> +                                       } else {
> +                                         spin_lock(&tunnel->hash_lock);
> +                                         if (!ipgre_tap_bridge_find(head,
> +                                               tethhdr->h_source))
> +                                               ipgre_tap_bridge_create(
> +                                                       head,
> +                                                       orig_source,
> +                                                       tethhdr->h_source);
> +                                         spin_unlock(&tunnel->hash_lock);
> +                                       }
> +                               }
> +                       }
> +#endif
>                }
>
>                tstats = this_cpu_ptr(tunnel->dev->tstats);
> @@ -702,7 +907,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
>        struct iphdr  *iph;                     /* Our new IP header */
>        unsigned int max_headroom;              /* The extra header space needed */
>        int    gre_hlen;
> -       __be32 dst;
> +       __be32 dst = 0;
>        int    mtu;
>
>        if (dev->type == ARPHRD_ETHER)
> @@ -716,7 +921,15 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
>                tiph = &tunnel->parms.iph;
>        }
>
> -       if ((dst = tiph->daddr) == 0) {
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +       if ((dev->type == ARPHRD_ETHER) &&
> +               ipv4_is_multicast(tunnel->parms.iph.daddr))
> +               dst = ipgre_tap_bridge_get_raddr(tunnel,
> +                       ((struct ethhdr *)skb->data)->h_dest);
> +#endif
> +       if (dst == 0)
> +               dst = tiph->daddr;
> +       if (dst == 0) {
>                /* NBMA tunnel */
>
>                if (skb_dst(skb) == NULL) {
> @@ -1211,6 +1424,16 @@ static int ipgre_open(struct net_device *dev)
>                        return -EADDRNOTAVAIL;
>                t->mlink = dev->ifindex;
>                ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +               if (t->dev->type == ARPHRD_ETHER) {
> +                       INIT_HLIST_HEAD(t->hash);
> +                       spin_lock_init(&t->hash_lock);
> +                       t->ageing_time = 300 * HZ;
> +                       setup_timer(&t->gc_timer, ipgre_tap_bridge_cleanup,
> +                               (unsigned long) t);
> +                       mod_timer(&t->gc_timer, jiffies + t->ageing_time);
> +               }
> +#endif
>        }
>        return 0;
>  }
> @@ -1221,6 +1444,12 @@ static int ipgre_close(struct net_device *dev)
>
>        if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
>                struct in_device *in_dev;
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +               if (t->dev->type == ARPHRD_ETHER) {
> +                       ipgre_tap_bridge_flush(t);
> +                       del_timer_sync(&t->gc_timer);
> +               }
> +#endif
>                in_dev = inetdev_by_index(dev_net(dev), t->mlink);
>                if (in_dev)
>                        ip_mc_dec_group(in_dev, t->parms.iph.daddr);
> @@ -1707,6 +1936,9 @@ static int __init ipgre_init(void)
>
>        printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
>
> +#ifdef CONFIG_NET_IPGRE_BRIDGE
> +       get_random_bytes(&ipgre_salt, sizeof(ipgre_salt));
> +#endif
>        err = register_pernet_device(&ipgre_net_ops);
>        if (err < 0)
>                return err;
>
>
looks good... I am just wondering whether my previous question about
the placement of calls for ipgre_tap_bridge_init and
ipgre_tap_bridge_fini? Would it be also possible to have this
done/fixed when I migrate those inside the ipgre_init and ipgre_fini ?
I would like to have much rather identical parts of code with standard
bridge code just in case somebody would start doing generalization of
bridge code which can be then reused anywhere inside the kernel space
- simpler migration process later.

^ permalink raw reply

* Re: [PATCH v9 3.2 7/9] tracing: uprobes trace_event interface
From: Ingo Molnar @ 2012-01-17 10:59 UTC (permalink / raw)
  To: Srikar Dronamraju
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Peter Zijlstra,
	Linus Torvalds, Oleg Nesterov, Andrew Morton, LKML, Linux-mm,
	Andi Kleen, Christoph Hellwig, Steven Rostedt, Roland McGrath,
	Thomas Gleixner, Masami Hiramatsu, Arnaldo Carvalho de Melo,
	Anton Arapov, Ananth N Mavinakayanahalli, Jim Keniston,
	Stephen Rothwell
In-Reply-To: <20120117102231.GB15447@linux.vnet.ibm.com>


btw., i'd write the CONFIG_UPROBE_EVENT .config help text:

 This allows the user to add tracing events on top of userspace
 dynamic events (similar to tracepoints) on the fly via the
 traceevents interface. Those events can be inserted wherever 
 uprobes can probe, and record various registers.

 This option is required if you plan to use perf-probe 
 subcommand of perf tools on user space applications.

In a clearer form:

 This allows the user to add user-space dynamic events on the 
 fly, similar to tracepoints. These events can be inserted
 into just about any user-space code transparently, and can 
 record register state there on the fly, which is then used by
 instrumentation tools.

 This option is required if you plan to use the "perf probe"
 subcommand of the perf tool on user space applications.

Thanks,

	Ingo

^ permalink raw reply

* Re: [PATCH v9 3.2 7/9] tracing: uprobes trace_event interface
From: Ingo Molnar @ 2012-01-17 10:59 UTC (permalink / raw)
  To: Srikar Dronamraju
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Peter Zijlstra,
	Linus Torvalds, Oleg Nesterov, Andrew Morton, LKML, Linux-mm,
	Andi Kleen, Christoph Hellwig, Steven Rostedt, Roland McGrath,
	Thomas Gleixner, Masami Hiramatsu, Arnaldo Carvalho de Melo,
	Anton Arapov, Ananth N Mavinakayanahalli, Jim Keniston,
	Stephen Rothwell
In-Reply-To: <20120117102231.GB15447@linux.vnet.ibm.com>


btw., i'd write the CONFIG_UPROBE_EVENT .config help text:

 This allows the user to add tracing events on top of userspace
 dynamic events (similar to tracepoints) on the fly via the
 traceevents interface. Those events can be inserted wherever 
 uprobes can probe, and record various registers.

 This option is required if you plan to use perf-probe 
 subcommand of perf tools on user space applications.

In a clearer form:

 This allows the user to add user-space dynamic events on the 
 fly, similar to tracepoints. These events can be inserted
 into just about any user-space code transparently, and can 
 record register state there on the fly, which is then used by
 instrumentation tools.

 This option is required if you plan to use the "perf probe"
 subcommand of the perf tool on user space applications.

Thanks,

	Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH] drm/i915: Mask the ring->head offset using the ring->size
From: Daniel Vetter @ 2012-01-17 10:59 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx, stable
In-Reply-To: <1320793992-2891-1-git-send-email-chris@chris-wilson.co.uk>

On Tue, Nov 08, 2011 at 11:13:12PM +0000, Chris Wilson wrote:
> Rather than relying on the hardware to do this correctly, we can
> trivially do it ourselves.
> 
> This fixes a very reliable crash on d-i-n with all bits enabled during a
> cairo-trace replay. The symptoms of the crash is that we continue to
> write commands into the render ring buffer past the active head
> position, leading to undefined operations.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: stable@kernel.org

I guess this is just the usual "snb doesn't like being pushed to hard bug"
resulting in random crashes with confusing error_states. So I think I'll
drop this. Correct?
-Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply

* Re: [git:v4l-dvb/for_v3.3] [media] V4L2 Spec: improve the G/S_INPUT/OUTPUT documentation
From: Hans Verkuil @ 2012-01-17 10:58 UTC (permalink / raw)
  To: Guennadi Liakhovetski
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List, Rupert Eibauer,
	Hans Verkuil
In-Reply-To: <Pine.LNX.4.64.1201171152210.21882@axis700.grange>

On Tuesday 17 January 2012 11:54:10 Guennadi Liakhovetski wrote:
> On Tue, 17 Jan 2012, Mauro Carvalho Chehab wrote:
> > Em 17-01-2012 08:16, Guennadi Liakhovetski escreveu:
> > > Hi Hans
> > > 
> > > On Tue, 17 Jan 2012, Hans Verkuil wrote:
> > >> On Monday 16 January 2012 23:16:31 Guennadi Liakhovetski wrote:
> > >>> On Mon, 16 Jan 2012, Mauro Carvalho Chehab wrote:
> > >>>> This is an automatic generated email to let you know that the
> > >>>> following patch were queued at the
> > >>>> http://git.linuxtv.org/media_tree.git tree:
> > >>>> 
> > >>>> Subject: [media] V4L2 Spec: improve the G/S_INPUT/OUTPUT
> > >>>> documentation Author:  Hans Verkuil <hans.verkuil@cisco.com>
> > >>>> Date:    Wed Jan 11 07:37:54 2012 -0300
> > >>> 
> > >>> [snip]
> > >>> 
> > >>>> diff --git a/Documentation/DocBook/media/v4l/vidioc-g-output.xml
> > >>>> b/Documentation/DocBook/media/v4l/vidioc-g-output.xml index
> > >>>> fd45f1c..4533068 100644
> > >>>> --- a/Documentation/DocBook/media/v4l/vidioc-g-output.xml
> > >>>> +++ b/Documentation/DocBook/media/v4l/vidioc-g-output.xml
> > >>>> @@ -61,8 +61,9 @@ desired output in an integer and call the
> > >>>> 
> > >>>>  <constant>VIDIOC_S_OUTPUT</constant> ioctl with a pointer to this
> > >>>>  integer. Side effects are possible. For example outputs may support
> > >>>>  different video standards, so the driver may implicitly switch the
> > >>>>  current
> > >>>> 
> > >>>> -standard. It is good practice to select an output before querying
> > >>>> or -negotiating any other parameters.</para>
> > >>>> +standard.
> > >>>> +standard. Because of these possible side effects applications
> > >>>> +must select an output before querying or negotiating any other
> > >>>> parameters.</para>
> > >>> 
> > >>> something seems to be wrong here.
> > >> 
> > >> Hi Guennadi!
> > >> 
> > >> What's wrong here? I've no idea what you mean.
> > >> 
> > >>>> +standard.
> > >>>> +standard. Because of these possible side effects applications
> > > 
> > > doesn't seem to make much sense?
> > 
> > Are you referring to grammar?
> 
> Sorry, am I being blind? The above seems to produce
> 
> <quote>
> different video standards, so the driver may implicitly switch the
> current standard. standard. Because of these possible side effects
> applications
> </quote>
> 
> i.e., double "standard." - one too many.

LOL! You are right, and I completely missed that :-)
I'm the one that's blind.

Mauro, can you fix this?

Thanks,

	Hans

> 
> Thanks
> Guennadi
> 
> > I think that a comma is missing there [1]:
> > 	Because of these possible side effects, applications
> > 	must select an output before querying or negotiating any other
> > 	parameters.
> > 
> > IMO, reverting the order of the explanation clause is semantically
> > better, as it bolds the need to select an output, and put the phrase at
> > the
> > 
> > cause-effect order:
> > 	Applications must select an output before querying or negotiating
> > 	any other parameters, because of these possible side effects.
> > 
> > But this is really a matter of choice. In any case, except for the
> > comma, that makes sense for me.
> > 
> > [1] Rule 4 of http://grammar.ccc.commnet.edu/grammar/commas.htm
> > 
> > 
> > Regards,
> > Mauro
> 
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> http://www.open-technology.de/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" 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

* Re: [PATCH] drm/i915: kill i915_mem.c
From: Dave Airlie @ 2012-01-17 10:58 UTC (permalink / raw)
  To: Keith Whitwell; +Cc: Daniel Vetter, intel-gfx, dri-devel
In-Reply-To: <1326797153.4628.6.camel@keithw-laptop>

On Tue, Jan 17, 2012 at 10:45 AM, Keith Whitwell <keithw@vmware.com> wrote:
>
> On Mon, 2012-01-16 at 21:56 +0100, Daniel Vetter wrote:
>> On Thu, Dec 22, 2011 at 10:23:14PM +0100, Daniel Vetter wrote:
>> > Some decent history digging indicates that this was to be used for the
>> > GLX_MESA_allocate_memory extension but never actually implemented for
>> > any released i915 userspace code.
>> >
>> > So just rip it out.
>> >
>> > Cc: Dave Airlie <airlied@gmail.com>
>> > Cc: Keith Whitwell <keithw@vmware.com>
>> > Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>>
>> Can some bored soul take a look at this and do the history
>> double-checking? And maybe notice that the Makefile change is missing ...
>>
>> /me would like to kill this cruft

All sounds good to me, kill it with fire. I've never known this code
to be used in anything.

Dave.

^ permalink raw reply

* Re: [Qemu-devel] [PATCH 2/2] qemu-ga: Add the guest-suspend command
From: Jamie Lokier @ 2012-01-17 10:57 UTC (permalink / raw)
  To: Eric Blake; +Cc: mdroth, jcody, qemu-devel, Luiz Capitulino
In-Reply-To: <4F14496F.8020500@redhat.com>

Eric Blake wrote:
> On 01/16/2012 03:51 AM, Jamie Lokier wrote:
> > I'm not sure if it's relevant to the this code, but on Glibc fork() is
> > not async-signal-safe and has been known to crash in signal handlers.
> > This is why fork() was removed from SUS async-signal-safe functions.
> 
> fork() is still in the list of async-signal-safe functions [1];

You're right, but it looks like it may be removed in the next edition:

   https://www.opengroup.org/austin/docs/austin_446.txt

> it was only pthread_atfork() which was removed.

I didn't think pthread_atfork() ever was async-signal-safe.

> That is, fork() is _required_
> to be async-signal-safe (and usable from signal handlers), provided that
> the actions following the fork also follow safety rules.

Nonethless, Glibc fork() isn't async-signal-safe even if it should be:

    http://sourceware.org/bugzilla/show_bug.cgi?id=4737
> > In general, why is multithreadedness relevant to async-signal-safety here?
> 
> Because POSIX 2008 (SUS inherits from POSIX, so it has the same
> restriction) states that if a multithreaded app calls fork, the child
> can only portably use async-signal-safe functions up until a successful
> exec or _exit.  Even though the child is _not_ operating in a signal
> handler context, it _is_ operating in a context of a single thread where
> other threads from the parent may have been holding locks, and thus
> calling any unsafe function (that is, any function that tries to obtain
> a lock) may deadlock.

Somewhat confusing, when you have pthread_atfork() existing for the
entire purpose of allowing non-async-signal-safe functions, provided
the application isn't multithreaded, but libraries can be (I'm not
sure what the difference between application and library is in this
context).

http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_atfork.html

    It is suggested that programs that use fork() call an exec function
    very soon afterwards in the child process, thus resetting all
    states. In the meantime, only a short list of async-signal-safe
    library routines are promised to be available.

    Unfortunately, this solution does not address the needs of
    multi-threaded libraries. Application programs may not be aware that a
    multi-threaded library is in use, and they feel free to call any
    number of library routines between the fork() and exec calls, just as
    they always have. Indeed, they may be extant single-threaded programs
    and cannot, therefore, be expected to obey new restrictions imposed by
    the threads library.

> I don't know if qemu-ga is intended to be a multi-threaded app, so I
> don't know if being paranoid about async-signal-safety matters in this
> particular case, but I _do_ know that libvirt has encountered issues
> with using non-safe functions prior to exec, which is why it always
> raises red flags when I see unsafe code between fork and exec.

Quite right, I agree. :-)

-- Jamie

^ permalink raw reply

* Re: [PATCH] drm/i915:: Disable FBC on SandyBridge
From: Daniel Vetter @ 2012-01-17 10:57 UTC (permalink / raw)
  To: Chris Wilson, Eugeni Dodonov; +Cc: intel-gfx
In-Reply-To: <1320794254-3114-1-git-send-email-chris@chris-wilson.co.uk>

On Tue, Nov 08, 2011 at 11:17:34PM +0000, Chris Wilson wrote:
> Enabling FBC is causing the BLT ring to run between 10-100x slower than
> normal and frequently lockup. The interim solution is disable FBC once
> more until we know why.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

Iirc fbc isn't really worth it power-wise on snb and we don't implement it on
ivb. So shouldn't we just disable it completely? Eugeni, any opinions - I
think you're most up to speed on power saving figures for snb?
-Daniel
> ---
>  drivers/gpu/drm/i915/intel_display.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 9fa342e..f972a09 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1864,7 +1864,7 @@ static void intel_update_fbc(struct drm_device *dev)
>  	if (enable_fbc < 0) {
>  		DRM_DEBUG_KMS("fbc set to per-chip default\n");
>  		enable_fbc = 1;
> -		if (INTEL_INFO(dev)->gen <= 5)
> +		if (INTEL_INFO(dev)->gen <= 6)
>  			enable_fbc = 0;
>  	}
>  	if (!enable_fbc) {
> -- 
> 1.7.7.2
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply

* Re: White Balance Temperature
From: Laurent Pinchart @ 2012-01-17 10:56 UTC (permalink / raw)
  To: Aurel; +Cc: linux-media
In-Reply-To: <loom.20120115T210838-546@post.gmane.org>

Hi Aurel,

On Sunday 15 January 2012 21:25:53 Aurel wrote:
> Laurent Pinchart <laurent.pinchart <at> ideasonboard.com> writes:
> > On Sunday 15 January 2012 11:16:30 Aurel wrote:
> > > Hi there
> > > 
> > > my "Live! Cam Socialize HD VF0610", Device ID: 041e:4080, Driver:
> > > uvcvideo is running perfectly on Fedora 16 Linux, except one thing:
> > > When I try to switch on "White Balance Temperature, Auto" or just try
> > > to change "White Balance Temperature" slider I get a failure message
> > > and it won't work. All other controls, like contrast, gamma, etc. are
> > > working. "v4l2-ctl -d 1 --set-ctrl=white_balance_temperature_auto=1"
> > > produces an error message:
> > > "VIDIOC_S_CTRL: failed: Input/output error
> > > white_balance_temperature_auto: Input/output error"
> > > 
> > > As soon as I boot Windows (inside Linux out of a Virtual Box), start
> > > the camera there and go back to Linux, I am able to adjust and switch
> > > on the White Balance things in Linux.
> > > "v4l2-ctl -d 1 --set-ctrl=white_balance_temperature_auto=1" working
> > > fine after running the camera in Windows.
> > > 
> > > Everytime I switch off my computer or disconnect the camera, I have to
> > > run the camera in Windows again, bevor I can adjust White Balance in
> > > Linux.
> > > 
> > > What can I do to get White Balance controls working in Linux, without
> > > having to run the camera in Windows every time?
> > > Is there a special command I have to send to the camera for
> > > initializing or so?
> > 
> > Not that I know of. If you use the stock UVC driver in Windows, without
> > having installed a custom driver for your device, that's quite unlikely.
> > 
> > Could you dump the value of all controls in Linux before and after
> > booting Windows ?

[snip]

> Here are the values before...
[snip]
>            saturation (int)    : min=0 max=255 step=1 default=128 value=128
>                 gamma (int)    : min=72 max=500 step=1 default=100 value=128
[snip]
> ...and after Windows...
[snip]
>            saturation (int)    : min=0 max=255 step=1 default=128 value=137
>                 gamma (int)    : min=72 max=500 step=1 default=100 value=100
[snip]
> ...not so much difference.

Indeed, only saturation and gamma differ. Have you tried setting saturation to 
137 and gamma to 100 in Linux (without booting Windows) and then changing the 
white balance controls ? I don't expect that to make any difference, but just 
in case...

> And may be I didn't tell right before: I did install the original Live!
> Central 3 software by Creative in Windows. All I do is just start it and
> switch off again.

Ah, that can play a role. The software might configure the camera when you 
plug it in using vendor-specific requests or extension units. Sniffing USB 
traffic in Windows could help verifying that.

> The interesting thing here is the "exposure_absolute" value. Much too high,
> but can also be changed before Windows.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* I2C_RDRW_IOCTL_MAX_MSGS
From: Srinivasan, Nageswari @ 2012-01-17 10:56 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org

Hi,

Is there any specific reason to limit no of i2c messages 
to 42 in i2c-dev.c file

/* Put an arbitrary limit on the number of messages that can
         * be sent at once */
        if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
                return -EINVAL;

Regards,
Nageswari

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.