Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH v2 2/7] net-tcp: Fast Open client - cookie cache
From: Eric Dumazet @ 2012-07-18 21:54 UTC (permalink / raw)
  To: Yuchung Cheng; +Cc: davem, hkchu, edumazet, ncardwell, sivasankar, netdev
In-Reply-To: <1342646166.2626.3692.camel@edumazet-glaptop>

On Wed, 2012-07-18 at 23:16 +0200, Eric Dumazet wrote:

> Hmm, this rcu_read_lock() in cache_set() gives a false sense of
> security ;)
> 
> I suggest using a seqlock instead ?
> 

Please find an updated version for your next submission :

 include/net/tcp.h      |    4 +++
 net/ipv4/tcp_metrics.c |   51 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 5aed371..e601da1 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -405,6 +405,10 @@ extern void tcp_metrics_init(void);
 extern bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool paws_check);
 extern bool tcp_remember_stamp(struct sock *sk);
 extern bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw);
+extern void tcp_fastopen_cache_get(struct sock *sk, u16 *mss,
+				   struct tcp_fastopen_cookie *cookie);
+extern void tcp_fastopen_cache_set(struct sock *sk, u16 mss,
+				   struct tcp_fastopen_cookie *cookie);
 extern void tcp_fetch_timewait_stamp(struct sock *sk, struct dst_entry *dst);
 extern void tcp_disable_fack(struct tcp_sock *tp);
 extern void tcp_close(struct sock *sk, long timeout);
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
index 1a115b6..d02ff37 100644
--- a/net/ipv4/tcp_metrics.c
+++ b/net/ipv4/tcp_metrics.c
@@ -30,6 +30,11 @@ enum tcp_metric_index {
 	TCP_METRIC_MAX,
 };
 
+struct tcp_fastopen_metrics {
+	u16	mss;
+	struct	tcp_fastopen_cookie	cookie;
+};
+
 struct tcp_metrics_block {
 	struct tcp_metrics_block __rcu	*tcpm_next;
 	struct inetpeer_addr		tcpm_addr;
@@ -38,6 +43,7 @@ struct tcp_metrics_block {
 	u32				tcpm_ts_stamp;
 	u32				tcpm_lock;
 	u32				tcpm_vals[TCP_METRIC_MAX];
+	struct tcp_fastopen_metrics	tcpm_fastopen;
 };
 
 static bool tcp_metric_locked(struct tcp_metrics_block *tm,
@@ -118,6 +124,8 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst)
 	tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING);
 	tm->tcpm_ts = 0;
 	tm->tcpm_ts_stamp = 0;
+	tm->tcpm_fastopen.mss = 0;
+	tm->tcpm_fastopen.cookie.len = 0;
 }
 
 static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
@@ -633,6 +641,49 @@ bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw)
 	return ret;
 }
 
+static DEFINE_SEQLOCK(fastopen_seqlock);
+
+void tcp_fastopen_cache_get(struct sock *sk, u16 *mss,
+			    struct tcp_fastopen_cookie *cookie)
+{
+	struct tcp_metrics_block *tm;
+
+	rcu_read_lock();
+	tm = tcp_get_metrics(sk, __sk_dst_get(sk), false);
+	if (tm) {
+		struct tcp_fastopen_metrics *tfom = &tm->tcpm_fastopen;
+		unsigned int seq;
+
+		do {
+			seq = read_seqbegin(&fastopen_seqlock);
+			if (tfom->mss)
+				*mss = tfom->mss;
+			*cookie = tfom->cookie;
+		} while (read_seqretry(&fastopen_seqlock, seq));
+	}
+	rcu_read_unlock();
+}
+
+
+void tcp_fastopen_cache_set(struct sock *sk, u16 mss,
+			    struct tcp_fastopen_cookie *cookie)
+{
+	struct tcp_metrics_block *tm;
+
+	rcu_read_lock();
+	tm = tcp_get_metrics(sk, __sk_dst_get(sk), true);
+	if (tm) {
+		struct tcp_fastopen_metrics *tfom = &tm->tcpm_fastopen;
+
+		write_seqlock_bh(&fastopen_seqlock);
+		tfom->mss = mss;
+		if (cookie->len > 0)
+			tfom->cookie = *cookie;
+		write_sequnlock_bh(&fastopen_seqlock);
+	}
+	rcu_read_unlock();
+}
+
 static unsigned long tcpmhash_entries;
 static int __init set_tcpmhash_entries(char *str)
 {

^ permalink raw reply related

* Re: [PATCH] net: Statically initialize init_net.dev_base_head
From: John Fastabend @ 2012-07-18 21:56 UTC (permalink / raw)
  To: David Miller; +Cc: nhorman, mark.d.rustad, netdev, gaofeng, eric.dumazet
In-Reply-To: <20120718.133243.1384365436939730847.davem@davemloft.net>

On 7/18/2012 1:32 PM, David Miller wrote:
> From: John Fastabend <john.r.fastabend@intel.com>
> Date: Wed, 18 Jul 2012 13:31:13 -0700
>
>> On 7/18/2012 1:21 PM, Neil Horman wrote:
>>> On Wed, Jul 18, 2012 at 01:20:10PM -0700, David Miller wrote:
>>>> From: Neil Horman <nhorman@tuxdriver.com>
>>>> Date: Wed, 18 Jul 2012 16:11:49 -0400
>>>>
>>>>> On Wed, Jul 18, 2012 at 12:06:07PM -0700, Mark Rustad wrote:
>>>>>> This change eliminates an initialization-order hazard most
>>>>>> recently seen when netprio_cgroup is built into the kernel.
>>>>>>
>>>>>> With thanks to Eric Dumazet for catching a bug.
>>>>>>
>>>>>> Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
>>>>    ...
>>>>> I think dave was going to take John Fastabends patch from earlier
>>>>> today, but
>>>>> this works just as well.  Long term I'm going to look into delaying
>>>>> initzlization for cgroups, as it creates a strange initialization
>>>>> state when you
>>>>> have a module_init routine registered.
>>>>
>>>> Neil, any particular preference between John's and Mark's version
>>>> of the fix?
>>>>
>>> I think they're both perfectly good.  If I had to choose I'd say
>>> Marks, just
>>> because its done by initializing data, rather than adding more code to
>>> run every
>>> time we create a cgroup.
>>>
>>> Neil
>>>
>>
>> Fine by me if we take this version instead.
>
> I think that's what I'll do, sorry for all the trouble John :)
>

No problem. For what its worth verified this resolved the netprio
issue on my system as expected.

^ permalink raw reply

* Re: [RFC] r8169 : why SG / TX checksum are default disabled
From: Francois Romieu @ 2012-07-18 21:44 UTC (permalink / raw)
  To: David Miller; +Cc: hayeswang, eric.dumazet, netdev
In-Reply-To: <20120718.132840.1571938255177607234.davem@davemloft.net>

David Miller <davem@davemloft.net> :
[...]
> A NETDEV_TX_OK return means we accepted the SKB, it doesn't look like
> that's what you are doing in the skb_padto() failure path.

?

- skb_padto fails
  (original skb is implicitely freed)
- skb_padto returns error status (!= 0)
- rtl8169_tso_csum returns false
- start_xmit returns NETDEV_TX_OK. 

I'll search the missing "!" after some sleep if that's what you are talking
about. Otherwise than that, I don't get it.

-- 
Ueimor

^ permalink raw reply

* Re: [RFC] r8169 : why SG / TX checksum are default disabled
From: Eric Dumazet @ 2012-07-18 22:05 UTC (permalink / raw)
  To: Francois Romieu; +Cc: David Miller, hayeswang, netdev
In-Reply-To: <20120718214422.GA18207@electric-eye.fr.zoreil.com>

On Wed, 2012-07-18 at 23:44 +0200, Francois Romieu wrote:
> David Miller <davem@davemloft.net> :
> [...]
> > A NETDEV_TX_OK return means we accepted the SKB, it doesn't look like
> > that's what you are doing in the skb_padto() failure path.
> 
> ?
> 
> - skb_padto fails
>   (original skb is implicitely freed)
> - skb_padto returns error status (!= 0)
> - rtl8169_tso_csum returns false
> - start_xmit returns NETDEV_TX_OK. 
> 
> I'll search the missing "!" after some sleep if that's what you are talking
> about. Otherwise than that, I don't get it.
> 


Yes, I believe your patch is fine.

In fact many drivers dont account the error in their stats.

Thanks

^ permalink raw reply

* Re: [PATCH net-next V1 1/9] IB/ipoib: Add support for clones / multiple childs on the same partition
From: John Fastabend @ 2012-07-18 22:11 UTC (permalink / raw)
  To: David Miller, or.gerlitz; +Cc: roland, netdev, ali, sean.hefty, shlomop, erezsh
In-Reply-To: <20120718.143608.2101579052587289420.davem@davemloft.net>

On 7/18/2012 2:36 PM, David Miller wrote:
> From: Or Gerlitz <or.gerlitz@gmail.com>
> Date: Thu, 19 Jul 2012 00:24:58 +0300
>
>> On Wed, Jul 18, 2012 at 9:38 PM, David Miller <davem@davemloft.net> wrote:
>>> From: Or Gerlitz <ogerlitz@mellanox.com>
>>
>>>> All sorts of childs are still created/deleted through sysfs, in a
>>>> similar manner to the way legacy child interfaces are.
>>
>>> Network device instantiation of this type is the domain of
>>> rtnl_link_ops rather than ugly sysfs interfaces.
>>
>> Didn't add any **new** sysfs interfaces in this patch. The IPoIB sysfs
>> entries to create child devices are there from IPoIB's day one, and
>> we're only extending them a tiny bit.
>
> That's extremely unfortunate, having private ways of instantiating
> networking devices leads to an extremely poor user experience.
>
> Would you like to have to train every single user in the case
> where each and every driver author makes his own unique way
> of configuring his hardware?
> --

Or,

I've got a rough patch to use rtnl_link_ops to add what we've been
calling 'virtual machine device queues' or VMDq. This looks a lot
like macvlan with offloaded switching and I believe similar to your
child case above.

Also what is a "pkey"

I'll post it as a use at your own risk shortly although this week I'm
short on time so maybe next week I can get something more "real" out.
Been stealing cycles between other work things today.

If you want to do complete it more power to you.

.John

^ permalink raw reply

* [RFC PATCH] net: Add support for virtual machine device queues (VMDQ)
From: John Fastabend @ 2012-07-18 22:05 UTC (permalink / raw)
  To: or.gerlitz, davem; +Cc: roland, netdev, ali, sean.hefty, shlomop

This adds support to allow virtual net devices to be created. These
devices can be managed independtly of the physical function but
use the same physical link.

This is analagous to an offloaded macvlan device. The primary
advantage to VMDQ net devices over virtual functions is they can
be added and removed dynamically as needed.

Sending this for Or Gerlitz to take a peak at and see if this
could be used for his ipoib bits. Its not pretty as is and
likely needs some work its just an idea at this point use at
your own risk I believe it compiles.
---

 drivers/net/Kconfig       |    7 ++
 drivers/net/Makefile      |    1 
 drivers/net/vmdq.c        |  130 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/netdevice.h |    6 ++
 include/net/rtnetlink.h   |    2 +
 net/core/rtnetlink.c      |   10 +++
 6 files changed, 155 insertions(+), 1 deletions(-)
 create mode 100644 drivers/net/vmdq.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 0c2bd80..f28d951 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -337,6 +337,13 @@ config VMXNET3
 	  To compile this driver as a module, choose M here: the
 	  module will be called vmxnet3.
 
+config VMDQ 
+	tristate "Support Embedded bridge devices and child devices"
+	help
+	  This supports chipsets with embedded switching components and
+	  allows us to create more net_devices that are logically slaves
+	  of a master net device.
+
 source "drivers/net/hyperv/Kconfig"
 
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 3d375ca..1eb5605 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_NET_TEAM) += team/
 obj-$(CONFIG_TUN) += tun.o
 obj-$(CONFIG_VETH) += veth.o
 obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
+obj-$(CONFIG_VMDQ) += vmdq.o
 
 #
 # Networking Drivers
diff --git a/drivers/net/vmdq.c b/drivers/net/vmdq.c
new file mode 100644
index 0000000..9acc429
--- /dev/null
+++ b/drivers/net/vmdq.c
@@ -0,0 +1,130 @@
+/*******************************************************************************
+
+  vmdq - Support virtual machine device queues (VMDQ)
+  Copyright(c) 2012 Intel Corporation.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope 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.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Contact Information:
+  John Fastabend <john.r.fastabend@intel.com>
+
+*******************************************************************************/
+
+#include <linux/module.h>
+#include <net/rtnetlink.h>
+#include <linux/etherdevice.h>
+
+static int vmdq_newlink(struct net *src_net, struct net_device *dev,
+		       struct nlattr *tb[], struct nlattr *data[])
+{
+	struct net_device *lowerdev;
+	int err = -EOPNOTSUPP;
+
+	if (!tb[IFLA_LINK])
+		return -EINVAL;
+
+	lowerdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
+	if (!lowerdev)
+		return -ENODEV;
+
+	if (!tb[IFLA_MTU])
+		dev->mtu = lowerdev->mtu;
+	else if (dev->mtu > lowerdev->mtu)
+		return -EINVAL;
+
+	if (lowerdev->netdev_ops->ndo_add_vmdq)
+		err = lowerdev->netdev_ops->ndo_add_vmdq(lowerdev, dev);
+
+	if (err < 0)
+		return err;
+
+	err = register_netdevice(dev);
+	if (err < 0)
+		lowerdev->netdev_ops->ndo_del_vmdq(lowerdev, dev);
+	else
+		netif_stacked_transfer_operstate(lowerdev, dev);
+
+	return err;
+}
+
+void vmdq_dellink(struct net_device *dev, struct list_head *head)
+{
+	struct net_device *lowerdev = __dev_get_by_index(dev_net(dev), dev->iflink);
+
+	if (lowerdev && lowerdev->netdev_ops->ndo_del_vmdq)
+		lowerdev->netdev_ops->ndo_del_vmdq(lowerdev, dev);		
+}
+
+static void vmdq_setup(struct net_device *dev)
+{
+	ether_setup(dev);
+}
+
+size_t vmdq_getpriv_size(struct net *src_net, struct nlattr *tb[])
+{
+	struct net_device *lowerdev;
+
+	if (!tb[IFLA_LINK])
+		return -EINVAL;
+
+	lowerdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
+	if (!lowerdev)
+		return -ENODEV;
+
+	return sizeof(netdev_priv(lowerdev));
+}
+
+int vmdq_get_tx_queues(struct net *net, struct nlattr *tb[])
+{
+	struct net_device *lowerdev;
+
+	if (!tb[IFLA_LINK])
+		return -EINVAL;
+
+	lowerdev = __dev_get_by_index(net, nla_get_u32(tb[IFLA_LINK]));
+	if (!lowerdev)
+		return -ENODEV;
+
+	return lowerdev->num_tx_queues;
+}
+
+static struct rtnl_link_ops vmdq_link_ops __read_mostly = {
+	.kind		= "vmdq",
+	.setup		= vmdq_setup,
+	.newlink	= vmdq_newlink,
+	.dellink	= vmdq_dellink,
+	.get_priv_size	= vmdq_getpriv_size,
+	.get_tx_queues	= vmdq_get_tx_queues,
+};
+
+static int __init vmdq_init_module(void)
+{
+	return rtnl_link_register(&vmdq_link_ops);
+}
+
+static void __exit vmdq_cleanup_module(void)
+{
+	rtnl_link_unregister(&vmdq_link_ops);
+}
+
+module_init(vmdq_init_module);
+module_exit(vmdq_cleanup_module);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Fastabend <john.r.fastabend@intel.com>");
+MODULE_DESCRIPTION("Driver for embedded switch chipsets");
+MODULE_ALIAS_RTNL_LINK("vmdq");
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ab0251d..d879c4d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -972,6 +972,12 @@ struct net_device_ops {
 						   struct nlattr *port[]);
 	int			(*ndo_get_vf_port)(struct net_device *dev,
 						   int vf, struct sk_buff *skb);
+
+	int			(*ndo_add_vmdq)(struct net_device *lowerdev,
+						struct net_device *dev);
+	int			(*ndo_del_vmdq)(struct net_device *lowerdev,
+						struct net_device *dev);
+
 	int			(*ndo_setup_tc)(struct net_device *dev, u8 tc);
 #if IS_ENABLED(CONFIG_FCOE)
 	int			(*ndo_fcoe_enable)(struct net_device *dev);
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index bbcfd09..e9f903c 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -79,6 +79,8 @@ struct rtnl_link_ops {
 					       const struct net_device *dev);
 	int			(*get_tx_queues)(struct net *net,
 						 struct nlattr *tb[]);
+	size_t			(*get_priv_size)(struct net *net,
+						 struct nlattr *tb[]);
 };
 
 extern int	__rtnl_link_register(struct rtnl_link_ops *ops);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 2b325c3..2e33b9a 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1627,6 +1627,7 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
 	int err;
 	struct net_device *dev;
 	unsigned int num_queues = 1;
+	size_t priv_size = ops->priv_size;
 
 	if (ops->get_tx_queues) {
 		err = ops->get_tx_queues(src_net, tb);
@@ -1635,8 +1636,15 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
 		num_queues = err;
 	}
 
+	if (ops->get_priv_size) {
+		err = ops->get_priv_size(src_net, tb);
+		if (err < 0)
+			goto err;
+		priv_size = err;
+	}
+
 	err = -ENOMEM;
-	dev = alloc_netdev_mq(ops->priv_size, ifname, ops->setup, num_queues);
+	dev = alloc_netdev_mq(priv_size, ifname, ops->setup, num_queues);
 	if (!dev)
 		goto err;
 

^ permalink raw reply related

* Re: [RFC] r8169 : why SG / TX checksum are default disabled
From: David Miller @ 2012-07-18 22:24 UTC (permalink / raw)
  To: eric.dumazet; +Cc: romieu, hayeswang, netdev
In-Reply-To: <1342649136.2626.3757.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu, 19 Jul 2012 00:05:36 +0200

> On Wed, 2012-07-18 at 23:44 +0200, Francois Romieu wrote:
>> David Miller <davem@davemloft.net> :
>> [...]
>> > A NETDEV_TX_OK return means we accepted the SKB, it doesn't look like
>> > that's what you are doing in the skb_padto() failure path.
>> 
>> ?
>> 
>> - skb_padto fails
>>   (original skb is implicitely freed)
>> - skb_padto returns error status (!= 0)
>> - rtl8169_tso_csum returns false
>> - start_xmit returns NETDEV_TX_OK. 
>> 
>> I'll search the missing "!" after some sleep if that's what you are talking
>> about. Otherwise than that, I don't get it.
>> 
> 
> 
> Yes, I believe your patch is fine.
> 
> In fact many drivers dont account the error in their stats.

My bad, I forgot that skb_padto() frees the SKB on failure.

^ permalink raw reply

* [PATCHv1] net: stmmac: Add ip version to dts bindings
From: dinguyen @ 2012-07-18 23:28 UTC (permalink / raw)
  To: netdev
  Cc: dinh.linux, peppe.cavallaro, sr, shiraz.hashim, deepak.sikri,
	pavel, arnd, Dinh Nguyen

From: Dinh Nguyen <dinguyen@altera.com>

Because there are multiple variants to the stmmac/dwmac driver, the
dts bindings should be updated to include version of the IP used.

Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
---
 Documentation/devicetree/bindings/net/stmmac.txt   |    3 ++-
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |    8 ++++++--
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index 1f62623..060bbf0 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -1,7 +1,8 @@
 * STMicroelectronics 10/100/1000 Ethernet driver (GMAC)
 
 Required properties:
-- compatible: Should be "st,spear600-gmac"
+- compatible: Should be "snps,dwmac-<ip_version>" "snps,dwmac"
+	For backwards compatibility: "st,spear600-gmac" is also supported.
 - reg: Address and length of the register set for the device
 - interrupt-parent: Should be the phandle for the interrupt controller
   that services interrupts for this device
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 680d2b8..87cadcf 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -49,7 +49,9 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
 	 * are provided. All other properties should be added
 	 * once needed on other platforms.
 	 */
-	if (of_device_is_compatible(np, "st,spear600-gmac")) {
+	if (of_device_is_compatible(np, "st,spear600-gmac") ||
+		of_device_is_compatible(np, "snps,dwmac-3.70a") ||
+		of_device_is_compatible(np, "snps,dwmac")) {
 		plat->has_gmac = 1;
 		plat->pmt = 1;
 	}
@@ -250,7 +252,9 @@ static const struct dev_pm_ops stmmac_pltfr_pm_ops;
 #endif /* CONFIG_PM */
 
 static const struct of_device_id stmmac_dt_ids[] = {
-	{ .compatible = "st,spear600-gmac", },
+	{ .compatible = "st,spear600-gmac"},
+	{ .compatible = "snps,dwmac-3.70a"},
+	{ .compatible = "snps,dwmac"},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
-- 
1.7.9.5

^ permalink raw reply related

* Re: [PATCH] SUNRPC: Prevent kernel stack corruption on long values of flush
From: Jim Rees @ 2012-07-18 23:04 UTC (permalink / raw)
  To: Sasha Levin
  Cc: J. Bruce Fields, Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q, davej-H+wXaHxf7aLQT0dZR+AlfA,
	linux-nfs-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <50072DEE.2000205-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Sasha Levin wrote:

  > Learning from what happened in this specific case, there are actually 2 issues here:
  > 
  >  - Array size was constant and too small, which is solved by the patch above.
  >  - We were blindly trying to sprintf() into that array, this issue may pop back up if someone decides to change the format string forgetting to modify the array declaration.
  > 

The original patch changed the sprintf to snprintf, and that still seems
like a good idea.
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH firmware] rtl_nic: update firmware for RTL8168G
From: Ben Hutchings @ 2012-07-19  0:59 UTC (permalink / raw)
  To: Hayes Wang; +Cc: dwmw2, romieu, netdev, linux-kernel
In-Reply-To: <1342008603-1279-1-git-send-email-hayeswang@realtek.com>

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

On Wed, 2012-07-11 at 20:10 +0800, Hayes Wang wrote:
> File: rtl_nic/rtl8168g-1.fw
> Version: 0.0.2
> 
> Change the ocp_base of linux driver to OCP_STD_PHY_BASE after setting
> firmware. The firmware would modify the ocp_base, and that results the
> driver uses the wrong ocp_base to access standard phy after setting
> firmware.
> 
> Signed-off-by: Hayes Wang <hayeswang@realtek.com>
[...]

Applied, thanks.

Ben.

-- 
Ben Hutchings
DNRC Motto:  I can please only one person per day.
Today is not your day.  Tomorrow isn't looking good either.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply

* Re: [PATCH v4] net: cgroup: fix access the unallocated memory in netprio cgroup
From: Li Zefan @ 2012-07-19  1:00 UTC (permalink / raw)
  To: Neil Horman
  Cc: John Fastabend, Gao feng, eric.dumazet, linux-kernel, netdev,
	davem, Eric Dumazet, Rustad, Mark D
In-Reply-To: <20120718142632.GF25563@hmsreliant.think-freely.org>

>>>>>  static struct cgroup_subsys_state *cgrp_create(struct cgroup *cgrp)

>>>>>  {
>>>>>  	struct cgroup_netprio_state *cs;
>>>>> -	int ret;
>>>>> +	int ret = -EINVAL;
>>>>>
>>>>>  	cs = kzalloc(sizeof(*cs), GFP_KERNEL);
>>>>>  	if (!cs)
>>>>>  		return ERR_PTR(-ENOMEM);
>>>>>
>>>>> -	if (cgrp->parent && cgrp_netprio_state(cgrp->parent)->prioidx) {
>>>>> -		kfree(cs);
>>>>> -		return ERR_PTR(-EINVAL);
>>>>> -	}
>>>>> +	if (cgrp->parent && cgrp_netprio_state(cgrp->parent)->prioidx)
>>>>> +		goto out;
>>>>>
>>>>>  	ret = get_prioidx(&cs->prioidx);
>>>>> -	if (ret != 0) {
>>>>> +	if (ret < 0) {
>>>>>  		pr_warn("No space in priority index array\n");
>>>>> -		kfree(cs);
>>>>> -		return ERR_PTR(ret);
>>>>> +		goto out;
>>>>> +	}
>>>>> +
>>>>> +	ret = update_netdev_tables();
>>>>> +	if (ret < 0) {
>>>>> +		put_prioidx(cs->prioidx);
>>>>> +		goto out;
>>>>>  	}
>>>>
>>>> Gao,
>>>>
>>>> This introduces a null ptr dereference when netprio_cgroup is built
>>>> into the kernel because update_netdev_tables() depends on init_net.
>>>> However cgrp_create is being called by cgroup_init before
>>>> do_initcalls() is called and before net_dev_init().
>>>>
>>>> .John
>>>>
>>> Not sure I follow here John.  Shouldn't init_net be initialized prior to any
>>> network devices getting registered?  In other words, shouldn't for_each_netdev
>>> just result in zero iterations through the loop?
>>> Neil
>>>
>>
>> init_net _is_ initialized prior to any network devices getting
>> registered but not before cgrp_create called via cgroup_init.
>>
>> #define for_each_netdev(net, d)         \
>>                 list_for_each_entry(d, &(net)->dev_base_head, dev_list)
>>
>> but dev_base_head is zeroed at this time. In netdev_init we have,
>>
>>         INIT_LIST_HEAD(&net->dev_base_head);
>>
>> but we haven't got that far yet because cgroup_init is called
>> before do_initcalls().
>>
> ok, I see that, and it makes sense, but at this point I'm more concerned with
> cgroups getting initalized twice.  The early_init flag is clear in the
> cgroup_subsystem for netprio, so we really shouldn't be getting initalized from
> cgroup_init. We should be getting initalized from the module_init() call that

> we register

If the early_init flag is set, a cgroup subsys will be initialized from
cgroup_early_init(), otherwise cgroup_init().

If netprio is built as a module, the subsys will be initailized from module_init(),
otherwise cgroup_init() (in this case cgroup_load_subsys() called in module_init()
is a no-op).

So it won't get initialized twice.

^ permalink raw reply

* linux-next: manual merge of the net-next tree with Linus' tree
From: Stephen Rothwell @ 2012-07-19  1:15 UTC (permalink / raw)
  To: David Miller, netdev
  Cc: linux-next, linux-kernel, Narendra K, Jeff Kirsher,
	Alexander Duyck

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

Hi all,

Today's linux-next merge of the net-next tree got a conflict in
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c between commit
936597631dd3 ("ixgbevf: Prevent RX/TX statistics getting reset to zero")
from Linus' tree and various commits from the net-next tree.

I just used the version from the net tree.
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: linux-next: manual merge of the net-next tree with Linus' tree
From: Jeff Kirsher @ 2012-07-19  1:18 UTC (permalink / raw)
  To: Stephen Rothwell
  Cc: David Miller, netdev, linux-next, linux-kernel, Narendra K,
	Alexander Duyck
In-Reply-To: <20120719111510.478d62e4f0778bd0de1f4c66@canb.auug.org.au>

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

On Thu, 2012-07-19 at 11:15 +1000, Stephen Rothwell wrote:
> Hi all,
> 
> Today's linux-next merge of the net-next tree got a conflict in
> drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c between commit
> 936597631dd3 ("ixgbevf: Prevent RX/TX statistics getting reset to zero")
> from Linus' tree and various commits from the net-next tree.
> 
> I just used the version from the net tree.

I will take a look at it later tonight to verify the conflict resolution
is correct.

Thanks Stephen.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* [PATCH] Crash in tun
From: Mikulas Patocka @ 2012-07-19  1:12 UTC (permalink / raw)
  To: Maxim Krasnyansky, vtun; +Cc: netdev, davem

Hi

I want to report a crash when using the tun driver. The crash can be 
reproduced by starting and stopping miredo in the loop:

while ! dmesg | grep -q BUG; do
	/etc/init.d/miredo start;/etc/init.d/miredo stop
done

The crash happens in iput_final because inode->i_sb->s_op is NULL.

The crash happens in 3.4, 3.4.5, 3.5-rc7. The crash does not happen in 
3.3. When I attempted to bisect, unrelated changes in completely different 
driver regarding memory allocation triggered the crash --- so it is 
likely buggy even in 3.3 and before, it just didn't show up.


What is obviously wrong:
in the tun driver "struct socket" is embedded in "struct tun_struct".

The backtrace goes through:
netdev_run_todo -> tun_free_netdev -> sk_release_kernel -> sock_release.

sock_release calls iput(SOCK_INODE(sock)). SOCK_INODE assumes that struct 
socket is embedded in "struct socket_alloc" (which is not true, it is 
embedded in "struct tun_struct"), gets a pointer to non-existing inode --- 
and there goes the crash.


The crash can be fixed by writing any non-NULL value to tun->socket.file 
to prevent sock_release from calling iput(SOCK_INODE(sock)). Or maybe you 
come up with a better fix.


Note another bug - when you are repeatedly starting and stopping miredo, 
even if it doesn't crash, the value "sockets: used" in 
/proc/*/net/sockstat keeps on decreasing. That's because sock_release 
decrements sockets_in_use, but there was no sock_alloc to increment it.


Mikulas

---

Signed-off-by: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>

---
 drivers/net/tun.c |    2 ++
 net/socket.c      |    4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

Index: linux-3.4.5-fast/drivers/net/tun.c
===================================================================
--- linux-3.4.5-fast.orig/drivers/net/tun.c	2012-07-19 02:42:56.000000000 +0200
+++ linux-3.4.5-fast/drivers/net/tun.c	2012-07-19 02:50:13.000000000 +0200
@@ -358,6 +358,8 @@ static void tun_free_netdev(struct net_d
 {
 	struct tun_struct *tun = netdev_priv(dev);
 
+	/* Prevent the code in sock_release from calling iput. */
+	tun->socket.file = (void *)1;
 	sk_release_kernel(tun->socket.sk);
 }
 
Index: linux-3.4.5-fast/net/socket.c
===================================================================
--- linux-3.4.5-fast.orig/net/socket.c	2012-07-19 03:00:30.000000000 +0200
+++ linux-3.4.5-fast/net/socket.c	2012-07-19 03:05:36.000000000 +0200
@@ -522,7 +522,9 @@ void sock_release(struct socket *sock)
 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
 
-	percpu_sub(sockets_in_use, 1);
+	/* a hack - sockets_in_use should not be decremented when tun calls this */
+	if (sock->file != (void *)1)
+		percpu_sub(sockets_in_use, 1);
 	if (!sock->file) {
 		iput(SOCK_INODE(sock));
 		return;
 
--- 

BUG: unable to handle kernel NULL pointer dereference at 0000000000000020
IP: [<ffffffff81113246>] iput+0x76/0x230
PGD 43e5e9067 PUD 4468d5067 PMD 0
Oops: 0000 [#1] PREEMPT SMP
CPU 1
Modules linked in: ip6table_filter ip6_tables iptable_filter ip_tables 
ebtable_nat ebtables x_tables kvm_amd kvm tun cpufreq_userspace 
cpufreq_stats cpufreq_powersave cpufreq_ondemand cpufreq_conservative ipv6 
fuse raid0 md_mod lm85 hwmon_vid snd_usb_audio snd_pcm_oss snd_mixer_oss 
snd_pcm snd_timer snd_page_alloc snd_hwdep snd_usbmidi_lib snd_rawmidi snd 
soundcore ide_cd_mod cdrom ohci_hcd sata_svw libata serverworks ide_core 
powernow_k8 ehci_hcd usbcore tg3 usb_common floppy freq_table e100 skge 
mii i2c_piix4 libphy mperf k10temp rtc_cmos processor button hwmon 
microcode unix

Pid: 10826, comm: miredo Not tainted 3.4.5 #85 empty empty/S3992-E
RIP: 0010:[<ffffffff81113246>]  [<ffffffff81113246>] iput+0x76/0x230
RSP: 0018:ffff88043dc73e48  EFLAGS: 00010246
RAX: 0000000000000001 RBX: ffff88023eba3f20 RCX: ffff880447d80000
RDX: 0000000000000001 RSI: ffff88023eba3f98 RDI: ffff88023eba3f98
RBP: ffff88023eba3f98 R08: ffffffff814804d8 R09: 0000000000000000
R10: 0000000000000096 R11: dead000000100100 R12: ffff88023eba3f48
R13: 0000000000000000 R14: ffff88043dc73e88 R15: 00000000ffffad3a
FS:  00007fe71bbb9700(0000) GS:ffff880247c80000(0000) 
knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000020 CR3: 000000043dcf0000 CR4: 00000000000007f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process miredo (pid: 10826, threadinfo ffff88043dc72000, task 
ffff88043dc1b8d0) Stack:
 ffff88043dc73e88 ffff88023efef000 ffff88023eba3800 ffff88023eba3c00
 ffff88024749ecc0 ffffffff81281d93 ffff88023e8fa500 ffffffff81295438
 ffff88043dc73e88 ffff88043dc73e88 ffff88023eba38f8 ffff88023e8fa500
Call Trace:
 [<ffffffff81281d93>] ? sk_release_kernel+0x23/0x40
 [<ffffffff81295438>] ? netdev_run_todo+0x1a8/0x260
 [<ffffffffa02522a3>] ? tun_chr_close+0x93/0xb0 [tun]
 [<ffffffff810fc3ed>] ? fput+0xdd/0x260
 [<ffffffff810f8aff>] ? filp_close+0x5f/0x90
 [<ffffffff810f8bc7>] ? sys_close+0x97/0x100
 [<ffffffff81311f22>] ? system_call_fastpath+0x16/0x1b
Code: 6c 24 10 4c 8b 64 24 18 4c 8b 6c 24 20 48 83 c4 28 c3 0f 1f 00 f6 83 
90 00 00 00 08 4c 8b 63 28 4d 8b 6c 24 30 0f 85 7d 01 00 00 <49> 8b 45 20 
48 85 c0 0f 84 9d 00 00 00 48 89 df ff d0 85 c0 0f
RIP  [<ffffffff81113246>] iput+0x76/0x230
 RSP <ffff88043dc73e48>
CR2: 0000000000000020
---[ end trace 6bd5160ffd3ba7a2 ]---
note: miredo[10826] exited with preempt_count 1

^ permalink raw reply

* [PATCH 0/9] OLPC: create a generic OLPC EC driver
From: Andres Salomon @ 2012-07-19  1:21 UTC (permalink / raw)
  To: Andrew Morton
  Cc: devel, Daniel Drake, libertas-dev, Dan Williams, netdev,
	Jon Nettleton, x86, linux-wireless, linux-kernel,
	platform-driver-x86, Richard A. Smith, Paul Fox,
	Greg Kroah-Hartman, Anton Vorontsov, H. Peter Anvin,
	Thomas Gleixner, Chris Ball, David Woodhouse, Ingo Molnar,
	John W. Linville, Matthew Garrett

The OLPC EC (Embedded Controller) code that is currently upstream is
x86-only, originally written for the XO-1.  Since then, we've had the
XO-1.5 (also x86), and XO-1.75 (arm-based) enter mass production.  The
1.75 uses a vastly different EC protocol, and future hardware revisions
are likely to change it even further.

However, the drivers do share quite a bit of code, so it makes sense to
have a platform-agnostic driver that calls into platform-specific hooks
for each XO's EC driver.  This is the first stab and creating such a
beast (with further patches pending).  Aside from the lack of code
duplication, this is helpful for fixing bugs in one place (for example,
we fixed an EC suspend/resume bug in 1.75 that I've just seen happen on
1.5 without these patches.  With these patches, the problem goes away).

These patches are against Linus's current HEAD; let me know if they
don't apply somewhere, and I'll happily redo them against the -next
tree.  I'm assuming that these changes (which touch places like x86,
wireless, and staging) should go through either the x86 tree, or
through akpm's tree.

Alternatively, if the reviews are positive and I can get SOBs from the
relevant maintainers, I can set up a platform-olpc tree somewhere and
request a pull from Linus.

^ permalink raw reply

* [PATCH 1/9] Platform: OLPC: add a stub to drivers/platform/ for the OLPC EC driver
From: Andres Salomon @ 2012-07-19  1:25 UTC (permalink / raw)
  To: Andrew Morton
  Cc: devel, Daniel Drake, libertas-dev, Dan Williams, netdev,
	Jon Nettleton, x86, linux-wireless, linux-kernel,
	platform-driver-x86, Richard A. Smith, Paul Fox,
	Greg Kroah-Hartman, Anton Vorontsov, H. Peter Anvin,
	Thomas Gleixner, Chris Ball, David Woodhouse, Ingo Molnar,
	John W. Linville, Matthew Garrett
In-Reply-To: <20120718182144.2d7b0b50@dev.queued.net>

The OLPC EC driver has outgrown arch/x86/platform/.  It's time to both
share common code amongst different architectures, as well as move it out
of arch/x86/.  The XO-1.75 is ARM-based, and the EC driver shares a lot of
code with the x86 code.

Signed-off-by: Andres Salomon <dilinger@queued.net>
---
 arch/x86/include/asm/olpc.h     |   19 +++----------------
 arch/x86/platform/olpc/olpc.c   |    4 ++--
 drivers/platform/Makefile       |    1 +
 drivers/platform/olpc/olpc-ec.c |   16 ++++++++++++++++
 include/linux/olpc-ec.h         |   29 +++++++++++++++++++++++++++++
 5 files changed, 51 insertions(+), 18 deletions(-)
 create mode 100644 drivers/platform/olpc/olpc-ec.c
 create mode 100644 include/linux/olpc-ec.h

diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h
index 87bdbca..513e999 100644
--- a/arch/x86/include/asm/olpc.h
+++ b/arch/x86/include/asm/olpc.h
@@ -4,6 +4,7 @@
 #define _ASM_X86_OLPC_H
 
 #include <asm/geode.h>
+#include <linux/olpc-ec.h>
 
 struct olpc_platform_t {
 	int flags;
@@ -102,22 +103,8 @@ extern int pci_olpc_init(void);
 
 /* EC related functions */
 
-extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
-		unsigned char *outbuf, size_t outlen);
-
-/* EC commands */
-
-#define EC_FIRMWARE_REV			0x08
-#define EC_WRITE_SCI_MASK		0x1b
-#define EC_WAKE_UP_WLAN			0x24
-#define EC_WLAN_LEAVE_RESET		0x25
-#define EC_READ_EB_MODE			0x2a
-#define EC_SET_SCI_INHIBIT		0x32
-#define EC_SET_SCI_INHIBIT_RELEASE	0x34
-#define EC_WLAN_ENTER_RESET		0x35
-#define EC_WRITE_EXT_SCI_MASK		0x38
-#define EC_SCI_QUERY			0x84
-#define EC_EXT_SCI_QUERY		0x85
+extern int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf,
+		size_t inlen, unsigned char *outbuf, size_t outlen);
 
 /* SCI source values */
 
diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c
index a4bee53..796e199 100644
--- a/arch/x86/platform/olpc/olpc.c
+++ b/arch/x86/platform/olpc/olpc.c
@@ -125,7 +125,7 @@ static int __wait_on_obf(unsigned int line, unsigned int port, int desired)
  * <http://wiki.laptop.org/go/Ec_specification>.  Unfortunately, while
  * OpenFirmware's source is available, the EC's is not.
  */
-int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
+int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf, size_t inlen,
 		unsigned char *outbuf,  size_t outlen)
 {
 	unsigned long flags;
@@ -201,7 +201,7 @@ err:
 	spin_unlock_irqrestore(&ec_lock, flags);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(olpc_ec_cmd);
+EXPORT_SYMBOL_GPL(olpc_ec_cmd_x86);
 
 void olpc_ec_wakeup_set(u16 value)
 {
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index 782953a..b17c16c 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_X86)		+= x86/
+obj-$(CONFIG_OLPC)		+= olpc/
diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c
new file mode 100644
index 0000000..4202603
--- /dev/null
+++ b/drivers/platform/olpc/olpc-ec.c
@@ -0,0 +1,16 @@
+/*
+ * Generic driver for the OLPC Embedded Controller.
+ *
+ * Copyright (C) 2011-2012 One Laptop per Child Foundation.
+ *
+ * Licensed under the GPL v2 or later.
+ */
+#include <linux/module.h>
+#include <asm/olpc.h>
+
+int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen)
+{
+	/* Currently a stub; this will be expanded upon later. */
+	return olpc_ec_cmd_x86(cmd, inbuf, inlen, outbuf, outlen);
+}
+EXPORT_SYMBOL_GPL(olpc_ec_cmd);
diff --git a/include/linux/olpc-ec.h b/include/linux/olpc-ec.h
new file mode 100644
index 0000000..6d4e426
--- /dev/null
+++ b/include/linux/olpc-ec.h
@@ -0,0 +1,29 @@
+#ifndef _LINUX_OLPC_EC_H
+#define _LINUX_OLPC_EC_H
+
+/* XO-1 EC commands */
+#define EC_FIRMWARE_REV			0x08
+#define EC_WRITE_SCI_MASK		0x1b
+#define EC_WAKE_UP_WLAN			0x24
+#define EC_WLAN_LEAVE_RESET		0x25
+#define EC_READ_EB_MODE			0x2a
+#define EC_SET_SCI_INHIBIT		0x32
+#define EC_SET_SCI_INHIBIT_RELEASE	0x34
+#define EC_WLAN_ENTER_RESET		0x35
+#define EC_WRITE_EXT_SCI_MASK		0x38
+#define EC_SCI_QUERY			0x84
+#define EC_EXT_SCI_QUERY		0x85
+
+#ifdef CONFIG_OLPC
+
+extern int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf,
+		size_t outlen);
+
+#else
+
+static inline int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf,
+		size_t outlen) { return -ENODEV; }
+
+#endif /* CONFIG_OLPC */
+
+#endif /* _LINUX_OLPC_EC_H */
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 2/9] drivers: OLPC: update various drivers to include olpc-ec.h
From: Andres Salomon @ 2012-07-19  1:26 UTC (permalink / raw)
  To: Andrew Morton
  Cc: devel, Daniel Drake, libertas-dev, Dan Williams, netdev,
	Jon Nettleton, x86, linux-wireless, linux-kernel,
	platform-driver-x86, Richard A. Smith, Paul Fox,
	Greg Kroah-Hartman, Anton Vorontsov, H. Peter Anvin,
	Thomas Gleixner, Chris Ball, David Woodhouse, Ingo Molnar,
	John W. Linville, Matthew Garrett
In-Reply-To: <20120718182144.2d7b0b50@dev.queued.net>

Switch over to using olpc-ec.h in multiple steps, so as not to break builds.
This covers every driver that calls olpc_ec_cmd().

Signed-off-by: Andres Salomon <dilinger@queued.net>
---
 arch/x86/include/asm/olpc.h            |    1 -
 arch/x86/platform/olpc/olpc-xo1-pm.c   |    1 +
 arch/x86/platform/olpc/olpc-xo1-sci.c  |    1 +
 arch/x86/platform/olpc/olpc-xo15-sci.c |    1 +
 arch/x86/platform/olpc/olpc.c          |    1 +
 drivers/net/wireless/libertas/if_usb.c |    1 +
 drivers/platform/x86/xo1-rfkill.c      |    3 +--
 drivers/power/olpc_battery.c           |    1 +
 drivers/staging/olpc_dcon/olpc_dcon.c  |    1 +
 9 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h
index 513e999..5b28f3e 100644
--- a/arch/x86/include/asm/olpc.h
+++ b/arch/x86/include/asm/olpc.h
@@ -4,7 +4,6 @@
 #define _ASM_X86_OLPC_H
 
 #include <asm/geode.h>
-#include <linux/olpc-ec.h>
 
 struct olpc_platform_t {
 	int flags;
diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c
index 0ce8616c..8054b64 100644
--- a/arch/x86/platform/olpc/olpc-xo1-pm.c
+++ b/arch/x86/platform/olpc/olpc-xo1-pm.c
@@ -18,6 +18,7 @@
 #include <linux/pm.h>
 #include <linux/mfd/core.h>
 #include <linux/suspend.h>
+#include <linux/olpc-ec.h>
 
 #include <asm/io.h>
 #include <asm/olpc.h>
diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c
index 04b8c73..63d4aa4 100644
--- a/arch/x86/platform/olpc/olpc-xo1-sci.c
+++ b/arch/x86/platform/olpc/olpc-xo1-sci.c
@@ -23,6 +23,7 @@
 #include <linux/power_supply.h>
 #include <linux/suspend.h>
 #include <linux/workqueue.h>
+#include <linux/olpc-ec.h>
 
 #include <asm/io.h>
 #include <asm/msr.h>
diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c
index 23e5b9d..9899fef 100644
--- a/arch/x86/platform/olpc/olpc-xo15-sci.c
+++ b/arch/x86/platform/olpc/olpc-xo15-sci.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/power_supply.h>
+#include <linux/olpc-ec.h>
 
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c
index 796e199..a3fa180 100644
--- a/arch/x86/platform/olpc/olpc.c
+++ b/arch/x86/platform/olpc/olpc.c
@@ -22,6 +22,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/debugfs.h>
 #include <linux/mutex.h>
+#include <linux/olpc-ec.h>
 
 #include <asm/geode.h>
 #include <asm/setup.h>
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index cd3b0d4..a9828b1 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -10,6 +10,7 @@
 #include <linux/netdevice.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
+#include <linux/olpc-ec.h>
 
 #ifdef CONFIG_OLPC
 #include <asm/olpc.h>
diff --git a/drivers/platform/x86/xo1-rfkill.c b/drivers/platform/x86/xo1-rfkill.c
index b57ad86..1da13ed 100644
--- a/drivers/platform/x86/xo1-rfkill.c
+++ b/drivers/platform/x86/xo1-rfkill.c
@@ -12,8 +12,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/rfkill.h>
-
-#include <asm/olpc.h>
+#include <linux/olpc-ec.h>
 
 static bool card_blocked;
 
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index 7385092..eaf917d 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -17,6 +17,7 @@
 #include <linux/power_supply.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
+#include <linux/olpc-ec.h>
 #include <asm/olpc.h>
 
 
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index 992275c..2c4bd74 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -27,6 +27,7 @@
 #include <linux/uaccess.h>
 #include <linux/ctype.h>
 #include <linux/reboot.h>
+#include <linux/olpc-ec.h>
 #include <asm/tsc.h>
 #include <asm/olpc.h>
 
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 3/9] Platform: OLPC: allow EC cmd to be overridden, and create a workqueue to call it
From: Andres Salomon @ 2012-07-19  1:26 UTC (permalink / raw)
  To: Andrew Morton
  Cc: devel, Daniel Drake, libertas-dev, Dan Williams, netdev,
	Jon Nettleton, x86, linux-wireless, linux-kernel,
	platform-driver-x86, Richard A. Smith, Paul Fox,
	Greg Kroah-Hartman, Anton Vorontsov, H. Peter Anvin,
	Thomas Gleixner, Chris Ball, David Woodhouse, Ingo Molnar,
	John W. Linville, Matthew Garrett
In-Reply-To: <20120718182144.2d7b0b50@dev.queued.net>

This provides a new API allows different OLPC architectures to override the
EC driver.  x86 and ARM OLPC machines use completely different EC backends.

The olpc_ec_cmd is synchronous, and waits for the workqueue to send the
command to the EC.  Multiple callers can run olpc_ec_cmd() at once, and
they will by serialized and sleep while only one executes on the EC at a time.

We don't provide an unregister function, as that doesn't make sense within
the context of OLPC machines - there's only ever 1 EC, it's critical to
functionality, and it certainly not hotpluggable.

Signed-off-by: Andres Salomon <dilinger@queued.net>
---
 drivers/platform/olpc/olpc-ec.c |  112 ++++++++++++++++++++++++++++++++++++++-
 include/linux/olpc-ec.h         |    6 ++
 2 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c
index 4202603..44e6a4f 100644
--- a/drivers/platform/olpc/olpc-ec.c
+++ b/drivers/platform/olpc/olpc-ec.c
@@ -5,12 +5,120 @@
  *
  * Licensed under the GPL v2 or later.
  */
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
 #include <linux/module.h>
+#include <linux/list.h>
+#include <linux/olpc-ec.h>
 #include <asm/olpc.h>
 
+struct ec_cmd_desc {
+	u8 cmd;
+	u8 *inbuf, *outbuf;
+	size_t inlen, outlen;
+
+	int err;
+	struct completion finished;
+	struct list_head node;
+
+	void *priv;
+};
+
+static void olpc_ec_worker(struct work_struct *w);
+
+static DECLARE_WORK(ec_worker, olpc_ec_worker);
+static LIST_HEAD(ec_cmd_q);
+static DEFINE_SPINLOCK(ec_cmd_q_lock);
+
+static struct olpc_ec_driver *ec_driver;
+static void *ec_cb_arg;
+static DEFINE_MUTEX(ec_cb_lock);
+
+void olpc_ec_driver_register(struct olpc_ec_driver *drv, void *arg)
+{
+	ec_driver = drv;
+	ec_cb_arg = arg;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_driver_register);
+
+static void olpc_ec_worker(struct work_struct *w)
+{
+	struct ec_cmd_desc *desc = NULL;
+	unsigned long flags;
+
+	/* Grab the first pending command from the queue */
+	spin_lock_irqsave(&ec_cmd_q_lock, flags);
+	if (!list_empty(&ec_cmd_q)) {
+		desc = list_first_entry(&ec_cmd_q, struct ec_cmd_desc, node);
+		list_del(&desc->node);
+	}
+	spin_unlock_irqrestore(&ec_cmd_q_lock, flags);
+
+	/* Do we actually have anything to do? */
+	if (!desc)
+		return;
+
+	/* Protect the EC hw with a mutex; only run one cmd at a time */
+	mutex_lock(&ec_cb_lock);
+	desc->err = ec_driver->ec_cmd(desc->cmd, desc->inbuf, desc->inlen,
+			desc->outbuf, desc->outlen, ec_cb_arg);
+	mutex_unlock(&ec_cb_lock);
+
+	/* Finished, wake up olpc_ec_cmd() */
+	complete(&desc->finished);
+
+	/* Run the worker thread again in case there are more cmds pending */
+	schedule_work(&ec_worker);
+}
+
+/*
+ * Throw a cmd descripter onto the list.  We now have SMP OLPC machines, so
+ * locking is pretty critical.
+ */
+static void queue_ec_descriptor(struct ec_cmd_desc *desc)
+{
+	unsigned long flags;
+
+	INIT_LIST_HEAD(&desc->node);
+
+	spin_lock_irqsave(&ec_cmd_q_lock, flags);
+	list_add_tail(&desc->node, &ec_cmd_q);
+	spin_unlock_irqrestore(&ec_cmd_q_lock, flags);
+
+	schedule_work(&ec_worker);
+}
+
 int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen)
 {
-	/* Currently a stub; this will be expanded upon later. */
-	return olpc_ec_cmd_x86(cmd, inbuf, inlen, outbuf, outlen);
+	struct ec_cmd_desc desc;
+
+	/* XXX: this will be removed in later patches */
+	/* Are we using old-style callers? */
+	if (!ec_driver || !ec_driver->ec_cmd)
+		return olpc_ec_cmd_x86(cmd, inbuf, inlen, outbuf, outlen);
+
+	/* Ensure a driver and ec hook have been registered */
+	if (WARN_ON(!ec_driver || !ec_driver->ec_cmd))
+		return -ENODEV;
+
+	might_sleep();
+
+	desc.cmd = cmd;
+	desc.inbuf = inbuf;
+	desc.outbuf = outbuf;
+	desc.inlen = inlen;
+	desc.outlen = outlen;
+	desc.err = 0;
+	init_completion(&desc.finished);
+
+	queue_ec_descriptor(&desc);
+
+	/* Timeouts must be handled in the platform-specific EC hook */
+	wait_for_completion(&desc.finished);
+
+	/* The worker thread dequeues the cmd; no need to do anything here */
+	return desc.err;
 }
 EXPORT_SYMBOL_GPL(olpc_ec_cmd);
diff --git a/include/linux/olpc-ec.h b/include/linux/olpc-ec.h
index 6d4e426..231e96f 100644
--- a/include/linux/olpc-ec.h
+++ b/include/linux/olpc-ec.h
@@ -14,8 +14,14 @@
 #define EC_SCI_QUERY			0x84
 #define EC_EXT_SCI_QUERY		0x85
 
+struct olpc_ec_driver {
+	int (*ec_cmd)(u8, u8 *, size_t, u8 *, size_t, void *);
+};
+
 #ifdef CONFIG_OLPC
 
+extern void olpc_ec_driver_register(struct olpc_ec_driver *drv, void *arg);
+
 extern int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf,
 		size_t outlen);
 
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 4/9] Platform: OLPC: turn EC driver into a platform_driver
From: Andres Salomon @ 2012-07-19  1:27 UTC (permalink / raw)
  To: Andrew Morton
  Cc: devel, Daniel Drake, libertas-dev, Dan Williams, netdev,
	Jon Nettleton, x86, linux-wireless, linux-kernel,
	platform-driver-x86, Richard A. Smith, Paul Fox,
	Greg Kroah-Hartman, Anton Vorontsov, H. Peter Anvin,
	Thomas Gleixner, Chris Ball, David Woodhouse, Ingo Molnar,
	John W. Linville, Matthew Garrett
In-Reply-To: <20120718182144.2d7b0b50@dev.queued.net>

The 1.75-based OLPC EC driver already does this; let's do it for all EC
drivers.  This gives us nice suspend/resume hooks, amongst other things.

We want to run the EC's suspend hooks later than other drivers (which may
be setting wakeup masks or be running EC commands).  We also want to run
the EC's resume hooks earlier than other drivers (which may want to run EC
commands).

Signed-off-by: Andres Salomon <dilinger@queued.net>
---
 drivers/platform/olpc/olpc-ec.c |   48 +++++++++++++++++++++++++++++++++++++++
 include/linux/olpc-ec.h         |    6 +++++
 2 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c
index 44e6a4f..d00523c 100644
--- a/drivers/platform/olpc/olpc-ec.c
+++ b/drivers/platform/olpc/olpc-ec.c
@@ -8,6 +8,7 @@
 #include <linux/completion.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
+#include <linux/platform_device.h>
 #include <linux/workqueue.h>
 #include <linux/module.h>
 #include <linux/list.h>
@@ -122,3 +123,50 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen)
 	return desc.err;
 }
 EXPORT_SYMBOL_GPL(olpc_ec_cmd);
+
+static int olpc_ec_probe(struct platform_device *pdev)
+{
+	int err;
+
+	if (!ec_driver)
+		return -ENODEV;
+
+	err = ec_driver->probe ? ec_driver->probe(pdev) : 0;
+
+	return err;
+}
+
+static int olpc_ec_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	return ec_driver->suspend ? ec_driver->suspend(pdev) : 0;
+}
+
+static int olpc_ec_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	return ec_driver->resume ? ec_driver->resume(pdev) : 0;
+}
+
+static const struct dev_pm_ops olpc_ec_pm_ops = {
+	.suspend_late = olpc_ec_suspend,
+	.resume_early = olpc_ec_resume,
+};
+
+static struct platform_driver olpc_ec_plat_driver = {
+	.probe = olpc_ec_probe,
+	.driver = {
+		.name = "olpc-ec",
+		.pm = &olpc_ec_pm_ops,
+	},
+};
+
+static int __init olpc_ec_init_module(void)
+{
+	return platform_driver_register(&olpc_ec_plat_driver);
+}
+
+module_init(olpc_ec_init_module);
+
+MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/olpc-ec.h b/include/linux/olpc-ec.h
index 231e96f..5bb6e76 100644
--- a/include/linux/olpc-ec.h
+++ b/include/linux/olpc-ec.h
@@ -14,7 +14,13 @@
 #define EC_SCI_QUERY			0x84
 #define EC_EXT_SCI_QUERY		0x85
 
+struct platform_device;
+
 struct olpc_ec_driver {
+	int (*probe)(struct platform_device *);
+	int (*suspend)(struct platform_device *);
+	int (*resume)(struct platform_device *);
+
 	int (*ec_cmd)(u8, u8 *, size_t, u8 *, size_t, void *);
 };
 
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 5/9] Platform: OLPC: add a suspended flag to the EC driver
From: Andres Salomon @ 2012-07-19  1:29 UTC (permalink / raw)
  To: Andrew Morton
  Cc: devel, Daniel Drake, libertas-dev, Dan Williams, netdev,
	Jon Nettleton, x86, linux-wireless, linux-kernel,
	platform-driver-x86, Richard A. Smith, Paul Fox,
	Greg Kroah-Hartman, Anton Vorontsov, H. Peter Anvin,
	Thomas Gleixner, Chris Ball, David Woodhouse, Ingo Molnar,
	John W. Linville, Matthew Garrett
In-Reply-To: <20120718182144.2d7b0b50@dev.queued.net>

A problem we've noticed on XO-1.75 is when we suspend in the middle of
an EC command.  Don't allow that.

In the process, create a private object for the generic EC driver to use;
we have a framework for passing around a struct, use that rather than a
proliferation of global variables.

Signed-off-by: Andres Salomon <dilinger@queued.net>
---
 drivers/platform/olpc/olpc-ec.c |   46 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 45 insertions(+), 1 deletions(-)

diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c
index d00523c..cfba41f 100644
--- a/drivers/platform/olpc/olpc-ec.c
+++ b/drivers/platform/olpc/olpc-ec.c
@@ -9,6 +9,7 @@
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/module.h>
 #include <linux/list.h>
@@ -27,6 +28,21 @@ struct ec_cmd_desc {
 	void *priv;
 };
 
+struct olpc_ec_priv {
+	struct olpc_ec_driver *drv;
+
+	/*
+	 * Running an EC command while suspending means we don't always finish
+	 * the command before the machine suspends.  This means that the EC
+	 * is expecting the command protocol to finish, but we after a period
+	 * of time (while the OS is asleep) the EC times out and restarts its
+	 * idle loop.  Meanwhile, the OS wakes up, thinks it's still in the
+	 * middle of the command protocol, starts throwing random things at
+	 * the EC... and everyone's uphappy.
+	 */
+	bool suspended;
+};
+
 static void olpc_ec_worker(struct work_struct *w);
 
 static DECLARE_WORK(ec_worker, olpc_ec_worker);
@@ -34,6 +50,7 @@ static LIST_HEAD(ec_cmd_q);
 static DEFINE_SPINLOCK(ec_cmd_q_lock);
 
 static struct olpc_ec_driver *ec_driver;
+static struct olpc_ec_priv *ec_priv;
 static void *ec_cb_arg;
 static DEFINE_MUTEX(ec_cb_lock);
 
@@ -93,6 +110,7 @@ static void queue_ec_descriptor(struct ec_cmd_desc *desc)
 
 int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen)
 {
+	struct olpc_ec_priv *ec = ec_priv;
 	struct ec_cmd_desc desc;
 
 	/* XXX: this will be removed in later patches */
@@ -104,6 +122,13 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen)
 	if (WARN_ON(!ec_driver || !ec_driver->ec_cmd))
 		return -ENODEV;
 
+	if (!ec)
+		return -ENOMEM;
+
+	/* Suspending in the middle of a command hoses things really badly */
+	if (WARN_ON(ec->suspended))
+		return -EBUSY;
+
 	might_sleep();
 
 	desc.cmd = cmd;
@@ -126,11 +151,19 @@ EXPORT_SYMBOL_GPL(olpc_ec_cmd);
 
 static int olpc_ec_probe(struct platform_device *pdev)
 {
+	struct olpc_ec_priv *ec;
 	int err;
 
 	if (!ec_driver)
 		return -ENODEV;
 
+	ec = kzalloc(sizeof(*ec), GFP_KERNEL);
+	if (!ec)
+		return -ENOMEM;
+	ec->drv = ec_driver;
+	ec_priv = ec;
+	platform_set_drvdata(pdev, ec);
+
 	err = ec_driver->probe ? ec_driver->probe(pdev) : 0;
 
 	return err;
@@ -139,12 +172,23 @@ static int olpc_ec_probe(struct platform_device *pdev)
 static int olpc_ec_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	return ec_driver->suspend ? ec_driver->suspend(pdev) : 0;
+	struct olpc_ec_priv *ec = platform_get_drvdata(pdev);
+	int err = 0;
+
+	if (ec_driver->suspend)
+		err = ec_driver->suspend(pdev);
+	if (!err)
+		ec->suspended = true;
+
+	return err;
 }
 
 static int olpc_ec_resume(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
+	struct olpc_ec_priv *ec = platform_get_drvdata(pdev);
+
+	ec->suspended = false;
 	return ec_driver->resume ? ec_driver->resume(pdev) : 0;
 }
 
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 6/9] x86: OLPC: switch over to using new EC driver on x86
From: Andres Salomon @ 2012-07-19  1:31 UTC (permalink / raw)
  To: Andrew Morton
  Cc: devel, Daniel Drake, libertas-dev, Dan Williams, netdev,
	Jon Nettleton, x86, linux-wireless, linux-kernel,
	platform-driver-x86, Richard A. Smith, Paul Fox,
	Greg Kroah-Hartman, Anton Vorontsov, H. Peter Anvin,
	Thomas Gleixner, Chris Ball, David Woodhouse, Ingo Molnar,
	John W. Linville, Matthew Garrett
In-Reply-To: <20120718182144.2d7b0b50@dev.queued.net>

This uses the new EC driver framework in drivers/platform/olpc.  The
XO-1 and XO-1.5-specific code is still in arch/x86, but the generic stuff
(including a new workqueue; no more running EC commands with IRQs disabled!)
can be shared with other architectures.

Signed-off-by: Andres Salomon <dilinger@queued.net>
---
 arch/x86/include/asm/olpc.h     |    5 ---
 arch/x86/platform/olpc/olpc.c   |   53 ++++++++++++++++++++-------------------
 drivers/platform/olpc/olpc-ec.c |    5 ---
 3 files changed, 27 insertions(+), 36 deletions(-)

diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h
index 5b28f3e..72f9adf6 100644
--- a/arch/x86/include/asm/olpc.h
+++ b/arch/x86/include/asm/olpc.h
@@ -100,11 +100,6 @@ extern void olpc_xo1_pm_wakeup_clear(u16 value);
 
 extern int pci_olpc_init(void);
 
-/* EC related functions */
-
-extern int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf,
-		size_t inlen, unsigned char *outbuf, size_t outlen);
-
 /* SCI source values */
 
 #define EC_SCI_SRC_EMPTY	0x00
diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c
index a3fa180..4590096 100644
--- a/arch/x86/platform/olpc/olpc.c
+++ b/arch/x86/platform/olpc/olpc.c
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/string.h>
 #include <linux/platform_device.h>
@@ -32,8 +31,6 @@
 struct olpc_platform_t olpc_platform_info;
 EXPORT_SYMBOL_GPL(olpc_platform_info);
 
-static DEFINE_SPINLOCK(ec_lock);
-
 /* debugfs interface to EC commands */
 #define EC_MAX_CMD_ARGS (5 + 1)	/* cmd byte + 5 args */
 #define EC_MAX_CMD_REPLY (8)
@@ -126,16 +123,13 @@ static int __wait_on_obf(unsigned int line, unsigned int port, int desired)
  * <http://wiki.laptop.org/go/Ec_specification>.  Unfortunately, while
  * OpenFirmware's source is available, the EC's is not.
  */
-int olpc_ec_cmd_x86(unsigned char cmd, unsigned char *inbuf, size_t inlen,
-		unsigned char *outbuf,  size_t outlen)
+static int olpc_xo1_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf,
+		size_t outlen, void *arg)
 {
-	unsigned long flags;
 	int ret = -EIO;
 	int i;
 	int restarts = 0;
 
-	spin_lock_irqsave(&ec_lock, flags);
-
 	/* Clear OBF */
 	for (i = 0; i < 10 && (obf_status(0x6c) == 1); i++)
 		inb(0x68);
@@ -199,10 +193,8 @@ restart:
 
 	ret = 0;
 err:
-	spin_unlock_irqrestore(&ec_lock, flags);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(olpc_ec_cmd_x86);
 
 void olpc_ec_wakeup_set(u16 value)
 {
@@ -366,7 +358,7 @@ static void setup_debugfs(void)
 			    &ec_debugfs_genops);
 }
 
-static int olpc_ec_suspend(void)
+static int olpc_ec_suspend(struct platform_device *pdev)
 {
 	return olpc_ec_mask_write(ec_wakeup_mask);
 }
@@ -425,8 +417,28 @@ static int __init add_xo1_platform_devices(void)
 	return 0;
 }
 
-static struct syscore_ops olpc_syscore_ops = {
+static int olpc_xo1_ec_probe(struct platform_device *pdev)
+{
+	/* get the EC revision */
+	olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0,
+			(unsigned char *) &olpc_platform_info.ecver, 1);
+
+	/* EC version 0x5f adds support for wide SCI mask */
+	if (olpc_platform_info.ecver >= 0x5f)
+		olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI;
+
+	pr_info("OLPC board revision %s%X (EC=%x)\n",
+			((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
+			olpc_platform_info.boardrev >> 4,
+			olpc_platform_info.ecver);
+
+	return 0;
+}
+
+static struct olpc_ec_driver ec_xo1_driver = {
 	.suspend = olpc_ec_suspend,
+	.probe = olpc_xo1_ec_probe,
+	.ec_cmd = olpc_xo1_ec_cmd,
 };
 
 static int __init olpc_init(void)
@@ -436,16 +448,14 @@ static int __init olpc_init(void)
 	if (!olpc_ofw_present() || !platform_detect())
 		return 0;
 
-	spin_lock_init(&ec_lock);
+	/* register the XO-1 and 1.5-specific EC handler */
+	olpc_ec_driver_register(&ec_xo1_driver, NULL);
+	platform_device_register_simple("olpc-ec", -1, NULL, 0);
 
 	/* assume B1 and above models always have a DCON */
 	if (olpc_board_at_least(olpc_board(0xb1)))
 		olpc_platform_info.flags |= OLPC_F_DCON;
 
-	/* get the EC revision */
-	olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0,
-			(unsigned char *) &olpc_platform_info.ecver, 1);
-
 #ifdef CONFIG_PCI_OLPC
 	/* If the VSA exists let it emulate PCI, if not emulate in kernel.
 	 * XO-1 only. */
@@ -453,14 +463,6 @@ static int __init olpc_init(void)
 			!cs5535_has_vsa2())
 		x86_init.pci.arch_init = pci_olpc_init;
 #endif
-	/* EC version 0x5f adds support for wide SCI mask */
-	if (olpc_platform_info.ecver >= 0x5f)
-		olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI;
-
-	printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n",
-			((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
-			olpc_platform_info.boardrev >> 4,
-			olpc_platform_info.ecver);
 
 	if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) { /* XO-1 */
 		r = add_xo1_platform_devices();
@@ -468,7 +470,6 @@ static int __init olpc_init(void)
 			return r;
 	}
 
-	register_syscore_ops(&olpc_syscore_ops);
 	setup_debugfs();
 
 	return 0;
diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c
index cfba41f..a3d32c2 100644
--- a/drivers/platform/olpc/olpc-ec.c
+++ b/drivers/platform/olpc/olpc-ec.c
@@ -113,11 +113,6 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen)
 	struct olpc_ec_priv *ec = ec_priv;
 	struct ec_cmd_desc desc;
 
-	/* XXX: this will be removed in later patches */
-	/* Are we using old-style callers? */
-	if (!ec_driver || !ec_driver->ec_cmd)
-		return olpc_ec_cmd_x86(cmd, inbuf, inlen, outbuf, outlen);
-
 	/* Ensure a driver and ec hook have been registered */
 	if (WARN_ON(!ec_driver || !ec_driver->ec_cmd))
 		return -ENODEV;
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 7/9] Platform: OLPC: move debugfs support from x86 EC driver
From: Andres Salomon @ 2012-07-19  1:31 UTC (permalink / raw)
  To: Andrew Morton
  Cc: devel, Daniel Drake, libertas-dev, Dan Williams, netdev,
	Jon Nettleton, x86, linux-wireless, linux-kernel,
	platform-driver-x86, Richard A. Smith, Paul Fox,
	Greg Kroah-Hartman, Anton Vorontsov, H. Peter Anvin,
	Thomas Gleixner, Chris Ball, David Woodhouse, Ingo Molnar,
	John W. Linville, Matthew Garrett
In-Reply-To: <20120718182144.2d7b0b50@dev.queued.net>

There's nothing about the debugfs interface for the EC driver that is
architecture-specific, so move it into the arch-independent driver.

The code is mostly unchanged with the exception of renamed variables, coding
style changes, and API updates.

Signed-off-by: Andres Salomon <dilinger@queued.net>
---
 arch/x86/platform/olpc/olpc.c   |   97 --------------------------------
 drivers/platform/olpc/olpc-ec.c |  117 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+), 97 deletions(-)

diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c
index 4590096..ed41b43 100644
--- a/arch/x86/platform/olpc/olpc.c
+++ b/arch/x86/platform/olpc/olpc.c
@@ -19,7 +19,6 @@
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/syscore_ops.h>
-#include <linux/debugfs.h>
 #include <linux/mutex.h>
 #include <linux/olpc-ec.h>
 
@@ -31,15 +30,6 @@
 struct olpc_platform_t olpc_platform_info;
 EXPORT_SYMBOL_GPL(olpc_platform_info);
 
-/* debugfs interface to EC commands */
-#define EC_MAX_CMD_ARGS (5 + 1)	/* cmd byte + 5 args */
-#define EC_MAX_CMD_REPLY (8)
-
-static struct dentry *ec_debugfs_dir;
-static DEFINE_MUTEX(ec_debugfs_cmd_lock);
-static unsigned char ec_debugfs_resp[EC_MAX_CMD_REPLY];
-static unsigned int ec_debugfs_resp_bytes;
-
 /* EC event mask to be applied during suspend (defining wakeup sources). */
 static u16 ec_wakeup_mask;
 
@@ -273,91 +263,6 @@ int olpc_ec_sci_query(u16 *sci_value)
 }
 EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
 
-static ssize_t ec_debugfs_cmd_write(struct file *file, const char __user *buf,
-				    size_t size, loff_t *ppos)
-{
-	int i, m;
-	unsigned char ec_cmd[EC_MAX_CMD_ARGS];
-	unsigned int ec_cmd_int[EC_MAX_CMD_ARGS];
-	char cmdbuf[64];
-	int ec_cmd_bytes;
-
-	mutex_lock(&ec_debugfs_cmd_lock);
-
-	size = simple_write_to_buffer(cmdbuf, sizeof(cmdbuf), ppos, buf, size);
-
-	m = sscanf(cmdbuf, "%x:%u %x %x %x %x %x", &ec_cmd_int[0],
-		   &ec_debugfs_resp_bytes,
-		   &ec_cmd_int[1], &ec_cmd_int[2], &ec_cmd_int[3],
-		   &ec_cmd_int[4], &ec_cmd_int[5]);
-	if (m < 2 || ec_debugfs_resp_bytes > EC_MAX_CMD_REPLY) {
-		/* reset to prevent overflow on read */
-		ec_debugfs_resp_bytes = 0;
-
-		printk(KERN_DEBUG "olpc-ec: bad ec cmd:  "
-		       "cmd:response-count [arg1 [arg2 ...]]\n");
-		size = -EINVAL;
-		goto out;
-	}
-
-	/* convert scanf'd ints to char */
-	ec_cmd_bytes = m - 2;
-	for (i = 0; i <= ec_cmd_bytes; i++)
-		ec_cmd[i] = ec_cmd_int[i];
-
-	printk(KERN_DEBUG "olpc-ec: debugfs cmd 0x%02x with %d args "
-	       "%02x %02x %02x %02x %02x, want %d returns\n",
-	       ec_cmd[0], ec_cmd_bytes, ec_cmd[1], ec_cmd[2], ec_cmd[3],
-	       ec_cmd[4], ec_cmd[5], ec_debugfs_resp_bytes);
-
-	olpc_ec_cmd(ec_cmd[0], (ec_cmd_bytes == 0) ? NULL : &ec_cmd[1],
-		    ec_cmd_bytes, ec_debugfs_resp, ec_debugfs_resp_bytes);
-
-	printk(KERN_DEBUG "olpc-ec: response "
-	       "%02x %02x %02x %02x %02x %02x %02x %02x (%d bytes expected)\n",
-	       ec_debugfs_resp[0], ec_debugfs_resp[1], ec_debugfs_resp[2],
-	       ec_debugfs_resp[3], ec_debugfs_resp[4], ec_debugfs_resp[5],
-	       ec_debugfs_resp[6], ec_debugfs_resp[7], ec_debugfs_resp_bytes);
-
-out:
-	mutex_unlock(&ec_debugfs_cmd_lock);
-	return size;
-}
-
-static ssize_t ec_debugfs_cmd_read(struct file *file, char __user *buf,
-				   size_t size, loff_t *ppos)
-{
-	unsigned int i, r;
-	char *rp;
-	char respbuf[64];
-
-	mutex_lock(&ec_debugfs_cmd_lock);
-	rp = respbuf;
-	rp += sprintf(rp, "%02x", ec_debugfs_resp[0]);
-	for (i = 1; i < ec_debugfs_resp_bytes; i++)
-		rp += sprintf(rp, ", %02x", ec_debugfs_resp[i]);
-	mutex_unlock(&ec_debugfs_cmd_lock);
-	rp += sprintf(rp, "\n");
-
-	r = rp - respbuf;
-	return simple_read_from_buffer(buf, size, ppos, respbuf, r);
-}
-
-static const struct file_operations ec_debugfs_genops = {
-	.write	 = ec_debugfs_cmd_write,
-	.read	 = ec_debugfs_cmd_read,
-};
-
-static void setup_debugfs(void)
-{
-	ec_debugfs_dir = debugfs_create_dir("olpc-ec", 0);
-	if (ec_debugfs_dir == ERR_PTR(-ENODEV))
-		return;
-
-	debugfs_create_file("cmd", 0600, ec_debugfs_dir, NULL,
-			    &ec_debugfs_genops);
-}
-
 static int olpc_ec_suspend(struct platform_device *pdev)
 {
 	return olpc_ec_mask_write(ec_wakeup_mask);
@@ -470,8 +375,6 @@ static int __init olpc_init(void)
 			return r;
 	}
 
-	setup_debugfs();
-
 	return 0;
 }
 
diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c
index a3d32c2..1a15a79 100644
--- a/drivers/platform/olpc/olpc-ec.c
+++ b/drivers/platform/olpc/olpc-ec.c
@@ -6,6 +6,7 @@
  * Licensed under the GPL v2 or later.
  */
 #include <linux/completion.h>
+#include <linux/debugfs.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
@@ -31,6 +32,8 @@ struct ec_cmd_desc {
 struct olpc_ec_priv {
 	struct olpc_ec_driver *drv;
 
+	struct dentry *dbgfs_dir;
+
 	/*
 	 * Running an EC command while suspending means we don't always finish
 	 * the command before the machine suspends.  This means that the EC
@@ -144,6 +147,114 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen)
 }
 EXPORT_SYMBOL_GPL(olpc_ec_cmd);
 
+#ifdef CONFIG_DEBUG_FS
+
+/*
+ * debugfs support for "generic commands", to allow sending
+ * arbitrary EC commands from userspace.
+ */
+
+#define EC_MAX_CMD_ARGS (5 + 1)		/* cmd byte + 5 args */
+#define EC_MAX_CMD_REPLY (8)
+
+static DEFINE_MUTEX(ec_dbgfs_lock);
+static unsigned char ec_dbgfs_resp[EC_MAX_CMD_REPLY];
+static unsigned int ec_dbgfs_resp_bytes;
+
+static ssize_t ec_dbgfs_cmd_write(struct file *file, const char __user *buf,
+		size_t size, loff_t *ppos)
+{
+	int i, m;
+	unsigned char ec_cmd[EC_MAX_CMD_ARGS];
+	unsigned int ec_cmd_int[EC_MAX_CMD_ARGS];
+	char cmdbuf[64];
+	int ec_cmd_bytes;
+
+	mutex_lock(&ec_dbgfs_lock);
+
+	size = simple_write_to_buffer(cmdbuf, sizeof(cmdbuf), ppos, buf, size);
+
+	m = sscanf(cmdbuf, "%x:%u %x %x %x %x %x", &ec_cmd_int[0],
+			&ec_dbgfs_resp_bytes, &ec_cmd_int[1], &ec_cmd_int[2],
+			&ec_cmd_int[3], &ec_cmd_int[4], &ec_cmd_int[5]);
+	if (m < 2 || ec_dbgfs_resp_bytes > EC_MAX_CMD_REPLY) {
+		/* reset to prevent overflow on read */
+		ec_dbgfs_resp_bytes = 0;
+
+		pr_debug("olpc-ec: bad ec cmd:  cmd:response-count [arg1 [arg2 ...]]\n");
+		size = -EINVAL;
+		goto out;
+	}
+
+	/* convert scanf'd ints to char */
+	ec_cmd_bytes = m - 2;
+	for (i = 0; i <= ec_cmd_bytes; i++)
+		ec_cmd[i] = ec_cmd_int[i];
+
+	pr_debug("olpc-ec: debugfs cmd 0x%02x with %d args %02x %02x %02x %02x %02x, want %d returns\n",
+			ec_cmd[0], ec_cmd_bytes, ec_cmd[1], ec_cmd[2],
+			ec_cmd[3], ec_cmd[4], ec_cmd[5], ec_dbgfs_resp_bytes);
+
+	olpc_ec_cmd(ec_cmd[0], (ec_cmd_bytes == 0) ? NULL : &ec_cmd[1],
+			ec_cmd_bytes, ec_dbgfs_resp, ec_dbgfs_resp_bytes);
+
+	pr_debug("olpc-ec: response %02x %02x %02x %02x %02x %02x %02x %02x (%d bytes expected)\n",
+			ec_dbgfs_resp[0], ec_dbgfs_resp[1], ec_dbgfs_resp[2],
+			ec_dbgfs_resp[3], ec_dbgfs_resp[4], ec_dbgfs_resp[5],
+			ec_dbgfs_resp[6], ec_dbgfs_resp[7],
+			ec_dbgfs_resp_bytes);
+
+out:
+	mutex_unlock(&ec_dbgfs_lock);
+	return size;
+}
+
+static ssize_t ec_dbgfs_cmd_read(struct file *file, char __user *buf,
+		size_t size, loff_t *ppos)
+{
+	unsigned int i, r;
+	char *rp;
+	char respbuf[64];
+
+	mutex_lock(&ec_dbgfs_lock);
+	rp = respbuf;
+	rp += sprintf(rp, "%02x", ec_dbgfs_resp[0]);
+	for (i = 1; i < ec_dbgfs_resp_bytes; i++)
+		rp += sprintf(rp, ", %02x", ec_dbgfs_resp[i]);
+	mutex_unlock(&ec_dbgfs_lock);
+	rp += sprintf(rp, "\n");
+
+	r = rp - respbuf;
+	return simple_read_from_buffer(buf, size, ppos, respbuf, r);
+}
+
+static const struct file_operations ec_dbgfs_ops = {
+	.write = ec_dbgfs_cmd_write,
+	.read = ec_dbgfs_cmd_read,
+};
+
+static struct dentry *olpc_ec_setup_debugfs(void)
+{
+	struct dentry *dbgfs_dir;
+
+	dbgfs_dir = debugfs_create_dir("olpc-ec", NULL);
+	if (IS_ERR_OR_NULL(dbgfs_dir))
+		return NULL;
+
+	debugfs_create_file("cmd", 0600, dbgfs_dir, NULL, &ec_dbgfs_ops);
+
+	return dbgfs_dir;
+}
+
+#else
+
+static struct dentry *olpc_ec_setup_debugfs(void)
+{
+	return NULL;
+}
+
+#endif /* CONFIG_DEBUG_FS */
+
 static int olpc_ec_probe(struct platform_device *pdev)
 {
 	struct olpc_ec_priv *ec;
@@ -160,6 +271,12 @@ static int olpc_ec_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, ec);
 
 	err = ec_driver->probe ? ec_driver->probe(pdev) : 0;
+	if (err) {
+		ec_priv = NULL;
+		kfree(ec);
+	} else {
+		ec->dbgfs_dir = olpc_ec_setup_debugfs();
+	}
 
 	return err;
 }
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 8/9] Platform: OLPC: move global variables into priv struct
From: Andres Salomon @ 2012-07-19  1:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: devel, Daniel Drake, libertas-dev, Dan Williams, netdev,
	Jon Nettleton, x86, linux-wireless, linux-kernel,
	platform-driver-x86, Richard A. Smith, Paul Fox,
	Greg Kroah-Hartman, Anton Vorontsov, H. Peter Anvin,
	Thomas Gleixner, Chris Ball, David Woodhouse, Ingo Molnar,
	John W. Linville, Matthew Garrett
In-Reply-To: <20120718182144.2d7b0b50@dev.queued.net>

Populate olpc_ec_priv.

Signed-off-by: Andres Salomon <dilinger@queued.net>
---
 drivers/platform/olpc/olpc-ec.c |   48 ++++++++++++++++++++++----------------
 1 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/drivers/platform/olpc/olpc-ec.c b/drivers/platform/olpc/olpc-ec.c
index 1a15a79..0f9f859 100644
--- a/drivers/platform/olpc/olpc-ec.c
+++ b/drivers/platform/olpc/olpc-ec.c
@@ -31,6 +31,12 @@ struct ec_cmd_desc {
 
 struct olpc_ec_priv {
 	struct olpc_ec_driver *drv;
+	struct work_struct worker;
+	struct mutex cmd_lock;
+
+	/* Pending EC commands */
+	struct list_head cmd_q;
+	spinlock_t cmd_q_lock;
 
 	struct dentry *dbgfs_dir;
 
@@ -46,16 +52,9 @@ struct olpc_ec_priv {
 	bool suspended;
 };
 
-static void olpc_ec_worker(struct work_struct *w);
-
-static DECLARE_WORK(ec_worker, olpc_ec_worker);
-static LIST_HEAD(ec_cmd_q);
-static DEFINE_SPINLOCK(ec_cmd_q_lock);
-
 static struct olpc_ec_driver *ec_driver;
 static struct olpc_ec_priv *ec_priv;
 static void *ec_cb_arg;
-static DEFINE_MUTEX(ec_cb_lock);
 
 void olpc_ec_driver_register(struct olpc_ec_driver *drv, void *arg)
 {
@@ -66,49 +65,51 @@ EXPORT_SYMBOL_GPL(olpc_ec_driver_register);
 
 static void olpc_ec_worker(struct work_struct *w)
 {
+	struct olpc_ec_priv *ec = container_of(w, struct olpc_ec_priv, worker);
 	struct ec_cmd_desc *desc = NULL;
 	unsigned long flags;
 
 	/* Grab the first pending command from the queue */
-	spin_lock_irqsave(&ec_cmd_q_lock, flags);
-	if (!list_empty(&ec_cmd_q)) {
-		desc = list_first_entry(&ec_cmd_q, struct ec_cmd_desc, node);
+	spin_lock_irqsave(&ec->cmd_q_lock, flags);
+	if (!list_empty(&ec->cmd_q)) {
+		desc = list_first_entry(&ec->cmd_q, struct ec_cmd_desc, node);
 		list_del(&desc->node);
 	}
-	spin_unlock_irqrestore(&ec_cmd_q_lock, flags);
+	spin_unlock_irqrestore(&ec->cmd_q_lock, flags);
 
 	/* Do we actually have anything to do? */
 	if (!desc)
 		return;
 
 	/* Protect the EC hw with a mutex; only run one cmd at a time */
-	mutex_lock(&ec_cb_lock);
+	mutex_lock(&ec->cmd_lock);
 	desc->err = ec_driver->ec_cmd(desc->cmd, desc->inbuf, desc->inlen,
 			desc->outbuf, desc->outlen, ec_cb_arg);
-	mutex_unlock(&ec_cb_lock);
+	mutex_unlock(&ec->cmd_lock);
 
 	/* Finished, wake up olpc_ec_cmd() */
 	complete(&desc->finished);
 
 	/* Run the worker thread again in case there are more cmds pending */
-	schedule_work(&ec_worker);
+	schedule_work(&ec->worker);
 }
 
 /*
  * Throw a cmd descripter onto the list.  We now have SMP OLPC machines, so
  * locking is pretty critical.
  */
-static void queue_ec_descriptor(struct ec_cmd_desc *desc)
+static void queue_ec_descriptor(struct ec_cmd_desc *desc,
+		struct olpc_ec_priv *ec)
 {
 	unsigned long flags;
 
 	INIT_LIST_HEAD(&desc->node);
 
-	spin_lock_irqsave(&ec_cmd_q_lock, flags);
-	list_add_tail(&desc->node, &ec_cmd_q);
-	spin_unlock_irqrestore(&ec_cmd_q_lock, flags);
+	spin_lock_irqsave(&ec->cmd_q_lock, flags);
+	list_add_tail(&desc->node, &ec->cmd_q);
+	spin_unlock_irqrestore(&ec->cmd_q_lock, flags);
 
-	schedule_work(&ec_worker);
+	schedule_work(&ec->worker);
 }
 
 int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen)
@@ -137,7 +138,7 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen)
 	desc.err = 0;
 	init_completion(&desc.finished);
 
-	queue_ec_descriptor(&desc);
+	queue_ec_descriptor(&desc, ec);
 
 	/* Timeouts must be handled in the platform-specific EC hook */
 	wait_for_completion(&desc.finished);
@@ -266,7 +267,14 @@ static int olpc_ec_probe(struct platform_device *pdev)
 	ec = kzalloc(sizeof(*ec), GFP_KERNEL);
 	if (!ec)
 		return -ENOMEM;
+
 	ec->drv = ec_driver;
+	INIT_WORK(&ec->worker, olpc_ec_worker);
+	mutex_init(&ec->cmd_lock);
+
+	INIT_LIST_HEAD(&ec->cmd_q);
+	spin_lock_init(&ec->cmd_q_lock);
+
 	ec_priv = ec;
 	platform_set_drvdata(pdev, ec);
 
-- 
1.7.2.5

^ permalink raw reply related

* [PATCH 9/9] x86: OLPC: move s/r-related EC cmds to EC driver
From: Andres Salomon @ 2012-07-19  1:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: devel, Daniel Drake, libertas-dev, Dan Williams, netdev,
	Jon Nettleton, x86, linux-wireless, linux-kernel,
	platform-driver-x86, Richard A. Smith, Paul Fox,
	Greg Kroah-Hartman, Anton Vorontsov, H. Peter Anvin,
	Thomas Gleixner, Chris Ball, David Woodhouse, Ingo Molnar,
	John W. Linville, Matthew Garrett
In-Reply-To: <20120718182144.2d7b0b50@dev.queued.net>

The new EC driver calls platform-specific suspend and resume hooks; run
XO-1-specific EC commands from there, rather than deep in s/r code.  If we
attempt to run EC commands after the new EC driver has suspended, it is
refused by the ec->suspended checks.

Signed-off-by: Andres Salomon <dilinger@queued.net>
---
 arch/x86/platform/olpc/olpc-xo1-pm.c |   15 ------------
 arch/x86/platform/olpc/olpc.c        |   43 ++++++++++++++++++++++++++++-----
 2 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/arch/x86/platform/olpc/olpc-xo1-pm.c b/arch/x86/platform/olpc/olpc-xo1-pm.c
index 8054b64..d75582d 100644
--- a/arch/x86/platform/olpc/olpc-xo1-pm.c
+++ b/arch/x86/platform/olpc/olpc-xo1-pm.c
@@ -52,16 +52,11 @@ EXPORT_SYMBOL_GPL(olpc_xo1_pm_wakeup_clear);
 static int xo1_power_state_enter(suspend_state_t pm_state)
 {
 	unsigned long saved_sci_mask;
-	int r;
 
 	/* Only STR is supported */
 	if (pm_state != PM_SUSPEND_MEM)
 		return -EINVAL;
 
-	r = olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0);
-	if (r)
-		return r;
-
 	/*
 	 * Save SCI mask (this gets lost since PM1_EN is used as a mask for
 	 * wakeup events, which is not necessarily the same event set)
@@ -77,16 +72,6 @@ static int xo1_power_state_enter(suspend_state_t pm_state)
 	/* Restore SCI mask (using dword access to CS5536_PM1_EN) */
 	outl(saved_sci_mask, acpi_base + CS5536_PM1_STS);
 
-	/* Tell the EC to stop inhibiting SCIs */
-	olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0);
-
-	/*
-	 * Tell the wireless module to restart USB communication.
-	 * Must be done twice.
-	 */
-	olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
-	olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
-
 	return 0;
 }
 
diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c
index ed41b43..2737608 100644
--- a/arch/x86/platform/olpc/olpc.c
+++ b/arch/x86/platform/olpc/olpc.c
@@ -263,11 +263,6 @@ int olpc_ec_sci_query(u16 *sci_value)
 }
 EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
 
-static int olpc_ec_suspend(struct platform_device *pdev)
-{
-	return olpc_ec_mask_write(ec_wakeup_mask);
-}
-
 static bool __init check_ofw_architecture(struct device_node *root)
 {
 	const char *olpc_arch;
@@ -339,9 +334,40 @@ static int olpc_xo1_ec_probe(struct platform_device *pdev)
 
 	return 0;
 }
+static int olpc_xo1_ec_suspend(struct platform_device *pdev)
+{
+	olpc_ec_mask_write(ec_wakeup_mask);
+
+	/*
+	 * Squelch SCIs while suspended.  This is a fix for
+	 * <http://dev.laptop.org/ticket/1835>.
+	 */
+	return olpc_ec_cmd(EC_SET_SCI_INHIBIT, NULL, 0, NULL, 0);
+}
+
+static int olpc_xo1_ec_resume(struct platform_device *pdev)
+{
+	/* Tell the EC to stop inhibiting SCIs */
+	olpc_ec_cmd(EC_SET_SCI_INHIBIT_RELEASE, NULL, 0, NULL, 0);
+
+	/*
+	 * Tell the wireless module to restart USB communication.
+	 * Must be done twice.
+	 */
+	olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
+	olpc_ec_cmd(EC_WAKE_UP_WLAN, NULL, 0, NULL, 0);
+
+	return 0;
+}
 
 static struct olpc_ec_driver ec_xo1_driver = {
-	.suspend = olpc_ec_suspend,
+	.probe = olpc_xo1_ec_probe,
+	.suspend = olpc_xo1_ec_suspend,
+	.resume = olpc_xo1_ec_resume,
+	.ec_cmd = olpc_xo1_ec_cmd,
+};
+
+static struct olpc_ec_driver ec_xo1_5_driver = {
 	.probe = olpc_xo1_ec_probe,
 	.ec_cmd = olpc_xo1_ec_cmd,
 };
@@ -354,7 +380,10 @@ static int __init olpc_init(void)
 		return 0;
 
 	/* register the XO-1 and 1.5-specific EC handler */
-	olpc_ec_driver_register(&ec_xo1_driver, NULL);
+	if (olpc_platform_info.boardrev < olpc_board_pre(0xd0))	/* XO-1 */
+		olpc_ec_driver_register(&ec_xo1_driver, NULL);
+	else
+		olpc_ec_driver_register(&ec_xo1_5_driver, NULL);
 	platform_device_register_simple("olpc-ec", -1, NULL, 0);
 
 	/* assume B1 and above models always have a DCON */
-- 
1.7.2.5

^ permalink raw reply related

* Re: [PATCH v2] ipvs: fixed sparse warning
From: Simon Horman @ 2012-07-19  1:43 UTC (permalink / raw)
  To: Claudiu Ghioc
  Cc: netdev, davem, netfilter-devel, linux-kernel, wensong, ja, pablo,
	kaber, claudiu.ghioc, daniel.baluta
In-Reply-To: <1342602622-2728-1-git-send-email-claudiu.ghioc@gmail.com>

On Wed, Jul 18, 2012 at 12:10:22PM +0300, Claudiu Ghioc wrote:
> Removed the following sparse warnings, wether CONFIG_SYSCTL
> is defined or not:
> *       warning: symbol 'ip_vs_control_net_init_sysctl' was not
> 	declared. Should it be static?
> *       warning: symbol 'ip_vs_control_net_cleanup_sysctl' was
> 	not declared. Should it be static?
> 
> Signed-off-by: Claudiu Ghioc <claudiu.ghioc@gmail.com>

Thanks, I have queued this up for 3.6.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox