Re: [PATCH 4.9 27/75] net: igmp: Use correct source address on IGMPv3 reports

2018-01-16 Thread Kevin Cernekee
On Tue, Jan 16, 2018 at 1:18 AM, Sebastian Gottschall
 wrote:
>
>> According to my understanding of igmpv3_newpack(), the destination
>> address should always be IGMPV3_ALL_MCR = 224.0.0.22.  That is what I
>> see in my testing.
>>
>> However, your packet trace says 239.35.100.8.  I don't know how the
>> code that we touched would be generating an IGMPv2 packet with that
>> destination address.
>
> easy answer from wikipedia. 224.0.x.x is not the only multicast block

AFAICT the code that was changed by this patch should not have
anything to do with other multicast blocks.  It generates an IGMPv3
report with destination address 224.0.0.22.  So it would be useful to
get more information on how exactly it is causing a failure, so we can
find the root cause.

>> Would it be possible to get a stack trace for the case where the
>> source address is being cleared to 0.0.0.0 in your configuration?
>
> you mean something like dumpstack and watching the flood comes over me?

I would just add something like this into my local tree for testing:

WARN_ON_ONCE(pip->saddr == htonl(INADDR_ANY));


Re: [PATCH 4.9 27/75] net: igmp: Use correct source address on IGMPv3 reports

2018-01-16 Thread Kevin Cernekee
On Tue, Jan 16, 2018 at 1:18 AM, Sebastian Gottschall
 wrote:
>
>> According to my understanding of igmpv3_newpack(), the destination
>> address should always be IGMPV3_ALL_MCR = 224.0.0.22.  That is what I
>> see in my testing.
>>
>> However, your packet trace says 239.35.100.8.  I don't know how the
>> code that we touched would be generating an IGMPv2 packet with that
>> destination address.
>
> easy answer from wikipedia. 224.0.x.x is not the only multicast block

AFAICT the code that was changed by this patch should not have
anything to do with other multicast blocks.  It generates an IGMPv3
report with destination address 224.0.0.22.  So it would be useful to
get more information on how exactly it is causing a failure, so we can
find the root cause.

>> Would it be possible to get a stack trace for the case where the
>> source address is being cleared to 0.0.0.0 in your configuration?
>
> you mean something like dumpstack and watching the flood comes over me?

I would just add something like this into my local tree for testing:

WARN_ON_ONCE(pip->saddr == htonl(INADDR_ANY));


Re: [PATCH 4.9 27/75] net: igmp: Use correct source address on IGMPv3 reports

2018-01-15 Thread Kevin Cernekee
On Mon, Jan 15, 2018 at 8:44 PM, Sebastian Gottschall
<s.gottsch...@dd-wrt.com> wrote:
> Am 16.01.2018 um 05:32 schrieb Kevin Cernekee:
>>
>> On Mon, Jan 15, 2018 at 8:26 PM, Sebastian Gottschall
>> <s.gottsch...@dd-wrt.com> wrote:
>>>
>>> havent check the source addresses right now. i basicly discovered that
>>> this
>>> patch breaks the igmp routing and all traffic stops
>>> this here is from a working system with the reverted patch. if you really
>>> need that i break it again using the patch you need to wait a little bit
>>>
>>> 05:14:22.697962 IP 10.88.195.138 > 239.35.100.8: igmp v2 report
>>> 239.35.100.8
>>
>> The patch should only affect IGMPv3 behavior.  I did not intend to
>> change IGMPv2 behavior.  If it does, that might be a bug.
>
> it does change the behaviour indeed. i dont know the reason. but i while
> discovering the issue on 4.14 last week and newly on 4.9 this week while
> testing
> (my latest firmware i builded was from 30. december and worked) i got
> tracked it down to this small patch and it immediatly worked after reverting
> it
>>
>> Is it possible that the kernel is using a source IP of 0.0.0.0, but
>> another host does not recognize it because it does not comply with RFC
>> 3376?
>
> this is possible yes, but i cannot look into the "deutsche telekom" host
>>
>>
>> Before/after packet traces would be the best way to see if the kernel
>> change is causing it to violate the standard.
>
> let me just take a look into our patch
> + for_ifa(in_dev) {
> + if (inet_ifa_match(fl4->saddr, ifa))
> + return fl4->saddr;
> + } endfor_ifa(in_dev);
> this looks like you're checking if the source address matches to a local
> interface, if not you return 0.0.0.0 instead of the source address
>
> (193.158.35.251, 239.35.20.4)Iif: ppp0   Oifs: briptv
>
> our first source address here 193.158.35.251 is from a remote network. so
> your patch also will change the behaviour since the source address will get
> ignored

According to my understanding of igmpv3_newpack(), the destination
address should always be IGMPV3_ALL_MCR = 224.0.0.22.  That is what I
see in my testing.

However, your packet trace says 239.35.100.8.  I don't know how the
code that we touched would be generating an IGMPv2 packet with that
destination address.

Would it be possible to get a stack trace for the case where the
source address is being cleared to 0.0.0.0 in your configuration?


Re: [PATCH 4.9 27/75] net: igmp: Use correct source address on IGMPv3 reports

2018-01-15 Thread Kevin Cernekee
On Mon, Jan 15, 2018 at 8:44 PM, Sebastian Gottschall
 wrote:
> Am 16.01.2018 um 05:32 schrieb Kevin Cernekee:
>>
>> On Mon, Jan 15, 2018 at 8:26 PM, Sebastian Gottschall
>>  wrote:
>>>
>>> havent check the source addresses right now. i basicly discovered that
>>> this
>>> patch breaks the igmp routing and all traffic stops
>>> this here is from a working system with the reverted patch. if you really
>>> need that i break it again using the patch you need to wait a little bit
>>>
>>> 05:14:22.697962 IP 10.88.195.138 > 239.35.100.8: igmp v2 report
>>> 239.35.100.8
>>
>> The patch should only affect IGMPv3 behavior.  I did not intend to
>> change IGMPv2 behavior.  If it does, that might be a bug.
>
> it does change the behaviour indeed. i dont know the reason. but i while
> discovering the issue on 4.14 last week and newly on 4.9 this week while
> testing
> (my latest firmware i builded was from 30. december and worked) i got
> tracked it down to this small patch and it immediatly worked after reverting
> it
>>
>> Is it possible that the kernel is using a source IP of 0.0.0.0, but
>> another host does not recognize it because it does not comply with RFC
>> 3376?
>
> this is possible yes, but i cannot look into the "deutsche telekom" host
>>
>>
>> Before/after packet traces would be the best way to see if the kernel
>> change is causing it to violate the standard.
>
> let me just take a look into our patch
> + for_ifa(in_dev) {
> + if (inet_ifa_match(fl4->saddr, ifa))
> + return fl4->saddr;
> + } endfor_ifa(in_dev);
> this looks like you're checking if the source address matches to a local
> interface, if not you return 0.0.0.0 instead of the source address
>
> (193.158.35.251, 239.35.20.4)Iif: ppp0   Oifs: briptv
>
> our first source address here 193.158.35.251 is from a remote network. so
> your patch also will change the behaviour since the source address will get
> ignored

According to my understanding of igmpv3_newpack(), the destination
address should always be IGMPV3_ALL_MCR = 224.0.0.22.  That is what I
see in my testing.

However, your packet trace says 239.35.100.8.  I don't know how the
code that we touched would be generating an IGMPv2 packet with that
destination address.

Would it be possible to get a stack trace for the case where the
source address is being cleared to 0.0.0.0 in your configuration?


Re: [PATCH 4.9 27/75] net: igmp: Use correct source address on IGMPv3 reports

2018-01-15 Thread Kevin Cernekee
On Mon, Jan 15, 2018 at 8:26 PM, Sebastian Gottschall
 wrote:
> havent check the source addresses right now. i basicly discovered that this
> patch breaks the igmp routing and all traffic stops
> this here is from a working system with the reverted patch. if you really
> need that i break it again using the patch you need to wait a little bit
>
> 05:14:22.697962 IP 10.88.195.138 > 239.35.100.8: igmp v2 report 239.35.100.8

The patch should only affect IGMPv3 behavior.  I did not intend to
change IGMPv2 behavior.  If it does, that might be a bug.

Is it possible that the kernel is using a source IP of 0.0.0.0, but
another host does not recognize it because it does not comply with RFC
3376?

Before/after packet traces would be the best way to see if the kernel
change is causing it to violate the standard.


Re: [PATCH 4.9 27/75] net: igmp: Use correct source address on IGMPv3 reports

2018-01-15 Thread Kevin Cernekee
On Mon, Jan 15, 2018 at 8:26 PM, Sebastian Gottschall
 wrote:
> havent check the source addresses right now. i basicly discovered that this
> patch breaks the igmp routing and all traffic stops
> this here is from a working system with the reverted patch. if you really
> need that i break it again using the patch you need to wait a little bit
>
> 05:14:22.697962 IP 10.88.195.138 > 239.35.100.8: igmp v2 report 239.35.100.8

The patch should only affect IGMPv3 behavior.  I did not intend to
change IGMPv2 behavior.  If it does, that might be a bug.

Is it possible that the kernel is using a source IP of 0.0.0.0, but
another host does not recognize it because it does not comply with RFC
3376?

Before/after packet traces would be the best way to see if the kernel
change is causing it to violate the standard.


Re: [PATCH 4.9 27/75] net: igmp: Use correct source address on IGMPv3 reports

2018-01-15 Thread Kevin Cernekee
On Mon, Jan 15, 2018 at 7:50 PM, Sebastian Gottschall
 wrote:
> please revert that on 4.9 and 4.14
> it breaks igmp routing. it can be reproduced with any iptv connection using
> igmp-proxy. reverting this patch fixes the issue.

Hi Sebastian,

Is this the correct igmp-proxy (based on mrouted)?

https://github.com/mirror/dd-wrt/tree/master/src/router/igmp-proxy

What is the actual vs. expected source address you are seeing on the
IGMP packets?


Re: [PATCH 4.9 27/75] net: igmp: Use correct source address on IGMPv3 reports

2018-01-15 Thread Kevin Cernekee
On Mon, Jan 15, 2018 at 7:50 PM, Sebastian Gottschall
 wrote:
> please revert that on 4.9 and 4.14
> it breaks igmp routing. it can be reproduced with any iptv connection using
> igmp-proxy. reverting this patch fixes the issue.

Hi Sebastian,

Is this the correct igmp-proxy (based on mrouted)?

https://github.com/mirror/dd-wrt/tree/master/src/router/igmp-proxy

What is the actual vs. expected source address you are seeing on the
IGMP packets?


[PATCH] net: igmp: Use correct source address on IGMPv3 reports

2017-12-11 Thread Kevin Cernekee
Closing a multicast socket after the final IPv4 address is deleted
from an interface can generate a membership report that uses the
source IP from a different interface.  The following test script, run
from an isolated netns, reproduces the issue:

#!/bin/bash

ip link add dummy0 type dummy
ip link add dummy1 type dummy
ip link set dummy0 up
ip link set dummy1 up
ip addr add 10.1.1.1/24 dev dummy0
ip addr add 192.168.99.99/24 dev dummy1

tcpdump -U -i dummy0 &
socat EXEC:"sleep 2" \
UDP4-DATAGRAM:239.101.1.68:8889,ip-add-membership=239.0.1.68:10.1.1.1 &

sleep 1
ip addr del 10.1.1.1/24 dev dummy0
sleep 5
kill %tcpdump

RFC 3376 specifies that the report must be sent with a valid IP source
address from the destination subnet, or from address 0.0.0.0.  Add an
extra check to make sure this is the case.

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 net/ipv4/igmp.c | 20 +++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index d1f8f302dbf3..0672264c9d93 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -89,6 +89,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -321,6 +322,23 @@ igmp_scount(struct ip_mc_list *pmc, int type, int 
gdeleted, int sdeleted)
return scount;
 }
 
+/* source address selection per RFC 3376 section 4.2.13 */
+static __be32 igmpv3_get_srcaddr(struct net_device *dev,
+const struct flowi4 *fl4)
+{
+   struct in_device *in_dev = __in_dev_get_rcu(dev);
+
+   if (!in_dev)
+   return htonl(INADDR_ANY);
+
+   for_ifa(in_dev) {
+   if (inet_ifa_match(fl4->saddr, ifa))
+   return fl4->saddr;
+   } endfor_ifa(in_dev);
+
+   return htonl(INADDR_ANY);
+}
+
 static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu)
 {
struct sk_buff *skb;
@@ -368,7 +386,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device 
*dev, unsigned int mtu)
pip->frag_off = htons(IP_DF);
pip->ttl  = 1;
pip->daddr= fl4.daddr;
-   pip->saddr= fl4.saddr;
+   pip->saddr= igmpv3_get_srcaddr(dev, );
pip->protocol = IPPROTO_IGMP;
pip->tot_len  = 0;  /* filled in later */
ip_select_ident(net, skb, NULL);
-- 
2.15.1.424.g9478a66081-goog



[PATCH] net: igmp: Use correct source address on IGMPv3 reports

2017-12-11 Thread Kevin Cernekee
Closing a multicast socket after the final IPv4 address is deleted
from an interface can generate a membership report that uses the
source IP from a different interface.  The following test script, run
from an isolated netns, reproduces the issue:

#!/bin/bash

ip link add dummy0 type dummy
ip link add dummy1 type dummy
ip link set dummy0 up
ip link set dummy1 up
ip addr add 10.1.1.1/24 dev dummy0
ip addr add 192.168.99.99/24 dev dummy1

tcpdump -U -i dummy0 &
socat EXEC:"sleep 2" \
UDP4-DATAGRAM:239.101.1.68:8889,ip-add-membership=239.0.1.68:10.1.1.1 &

sleep 1
ip addr del 10.1.1.1/24 dev dummy0
sleep 5
kill %tcpdump

RFC 3376 specifies that the report must be sent with a valid IP source
address from the destination subnet, or from address 0.0.0.0.  Add an
extra check to make sure this is the case.

Signed-off-by: Kevin Cernekee 
---
 net/ipv4/igmp.c | 20 +++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index d1f8f302dbf3..0672264c9d93 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -89,6 +89,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -321,6 +322,23 @@ igmp_scount(struct ip_mc_list *pmc, int type, int 
gdeleted, int sdeleted)
return scount;
 }
 
+/* source address selection per RFC 3376 section 4.2.13 */
+static __be32 igmpv3_get_srcaddr(struct net_device *dev,
+const struct flowi4 *fl4)
+{
+   struct in_device *in_dev = __in_dev_get_rcu(dev);
+
+   if (!in_dev)
+   return htonl(INADDR_ANY);
+
+   for_ifa(in_dev) {
+   if (inet_ifa_match(fl4->saddr, ifa))
+   return fl4->saddr;
+   } endfor_ifa(in_dev);
+
+   return htonl(INADDR_ANY);
+}
+
 static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu)
 {
struct sk_buff *skb;
@@ -368,7 +386,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device 
*dev, unsigned int mtu)
pip->frag_off = htons(IP_DF);
pip->ttl  = 1;
pip->daddr= fl4.daddr;
-   pip->saddr= fl4.saddr;
+   pip->saddr= igmpv3_get_srcaddr(dev, );
pip->protocol = IPPROTO_IGMP;
pip->tot_len  = 0;  /* filled in later */
ip_select_ident(net, skb, NULL);
-- 
2.15.1.424.g9478a66081-goog



[PATCH V2] netlink: Add netns check on taps

2017-12-06 Thread Kevin Cernekee
Currently, a nlmon link inside a child namespace can observe systemwide
netlink activity.  Filter the traffic so that nlmon can only sniff
netlink messages from its own netns.

Test case:

vpnns -- bash -c "ip link add nlmon0 type nlmon; \
  ip link set nlmon0 up; \
  tcpdump -i nlmon0 -q -w /tmp/nlmon.pcap -U" &
sudo ip xfrm state add src 10.1.1.1 dst 10.1.1.2 proto esp \
spi 0x1 mode transport \
auth sha1 0x616263313233 \
enc aes 0x
grep --binary abc123 /tmp/nlmon.pcap

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 net/netlink/af_netlink.c | 3 +++
 1 file changed, 3 insertions(+)


V1->V2: Drop the special exception for init_net.
Compile-tested only, will retest later today.


diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index b9e0ee4..79cc1bf 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -253,6 +253,9 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb,
struct sock *sk = skb->sk;
int ret = -ENOMEM;
 
+   if (!net_eq(dev_net(dev), sock_net(sk)))
+   return 0;
+
dev_hold(dev);
 
if (is_vmalloc_addr(skb->head))
-- 
2.7.4



[PATCH V2] netlink: Add netns check on taps

2017-12-06 Thread Kevin Cernekee
Currently, a nlmon link inside a child namespace can observe systemwide
netlink activity.  Filter the traffic so that nlmon can only sniff
netlink messages from its own netns.

Test case:

vpnns -- bash -c "ip link add nlmon0 type nlmon; \
  ip link set nlmon0 up; \
  tcpdump -i nlmon0 -q -w /tmp/nlmon.pcap -U" &
sudo ip xfrm state add src 10.1.1.1 dst 10.1.1.2 proto esp \
spi 0x1 mode transport \
auth sha1 0x616263313233 \
enc aes 0x
grep --binary abc123 /tmp/nlmon.pcap

Signed-off-by: Kevin Cernekee 
---
 net/netlink/af_netlink.c | 3 +++
 1 file changed, 3 insertions(+)


V1->V2: Drop the special exception for init_net.
Compile-tested only, will retest later today.


diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index b9e0ee4..79cc1bf 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -253,6 +253,9 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb,
struct sock *sk = skb->sk;
int ret = -ENOMEM;
 
+   if (!net_eq(dev_net(dev), sock_net(sk)))
+   return 0;
+
dev_hold(dev);
 
if (is_vmalloc_addr(skb->head))
-- 
2.7.4



Re: [PATCH] netlink: Add netns check on taps

2017-12-05 Thread Kevin Cernekee
On Tue, Dec 5, 2017 at 6:19 PM, David Ahern  wrote:
>> + if (!net_eq(dev_net(dev), sock_net(sk)) &&
>> + !net_eq(dev_net(dev), _net)) {
>
> Why is init_net special? Seems like snooping should be limited to the
> namespace you are in.

Depends how important it is to preserve the current "typical use case"
behavior, where the root user in the init netns can see all netlink
traffic on the system.


Re: [PATCH] netlink: Add netns check on taps

2017-12-05 Thread Kevin Cernekee
On Tue, Dec 5, 2017 at 6:19 PM, David Ahern  wrote:
>> + if (!net_eq(dev_net(dev), sock_net(sk)) &&
>> + !net_eq(dev_net(dev), _net)) {
>
> Why is init_net special? Seems like snooping should be limited to the
> namespace you are in.

Depends how important it is to preserve the current "typical use case"
behavior, where the root user in the init netns can see all netlink
traffic on the system.


[PATCH] netfilter: xt_osf: Add missing permission checks

2017-12-05 Thread Kevin Cernekee
The capability check in nfnetlink_rcv() verifies that the caller
has CAP_NET_ADMIN in the namespace that "owns" the netlink socket.
However, xt_osf_fingers is shared by all net namespaces on the
system.  An unprivileged user can create user and net namespaces
in which he holds CAP_NET_ADMIN to bypass the netlink_net_capable()
check:

vpnns -- nfnl_osf -f /tmp/pf.os

vpnns -- nfnl_osf -f /tmp/pf.os -d

These non-root operations successfully modify the systemwide OS
fingerprint list.  Add new capable() checks so that they can't.

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 net/netfilter/xt_osf.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index 36e14b1..a34f314 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -70,6 +71,9 @@ static int xt_osf_add_callback(struct net *net, struct sock 
*ctnl,
struct xt_osf_finger *kf = NULL, *sf;
int err = 0;
 
+   if (!capable(CAP_NET_ADMIN))
+   return -EPERM;
+
if (!osf_attrs[OSF_ATTR_FINGER])
return -EINVAL;
 
@@ -115,6 +119,9 @@ static int xt_osf_remove_callback(struct net *net, struct 
sock *ctnl,
struct xt_osf_finger *sf;
int err = -ENOENT;
 
+   if (!capable(CAP_NET_ADMIN))
+   return -EPERM;
+
if (!osf_attrs[OSF_ATTR_FINGER])
return -EINVAL;
 
-- 
2.7.4



[PATCH] netfilter: xt_osf: Add missing permission checks

2017-12-05 Thread Kevin Cernekee
The capability check in nfnetlink_rcv() verifies that the caller
has CAP_NET_ADMIN in the namespace that "owns" the netlink socket.
However, xt_osf_fingers is shared by all net namespaces on the
system.  An unprivileged user can create user and net namespaces
in which he holds CAP_NET_ADMIN to bypass the netlink_net_capable()
check:

vpnns -- nfnl_osf -f /tmp/pf.os

vpnns -- nfnl_osf -f /tmp/pf.os -d

These non-root operations successfully modify the systemwide OS
fingerprint list.  Add new capable() checks so that they can't.

Signed-off-by: Kevin Cernekee 
---
 net/netfilter/xt_osf.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index 36e14b1..a34f314 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -70,6 +71,9 @@ static int xt_osf_add_callback(struct net *net, struct sock 
*ctnl,
struct xt_osf_finger *kf = NULL, *sf;
int err = 0;
 
+   if (!capable(CAP_NET_ADMIN))
+   return -EPERM;
+
if (!osf_attrs[OSF_ATTR_FINGER])
return -EINVAL;
 
@@ -115,6 +119,9 @@ static int xt_osf_remove_callback(struct net *net, struct 
sock *ctnl,
struct xt_osf_finger *sf;
int err = -ENOENT;
 
+   if (!capable(CAP_NET_ADMIN))
+   return -EPERM;
+
if (!osf_attrs[OSF_ATTR_FINGER])
return -EINVAL;
 
-- 
2.7.4



[PATCH] netlink: Add netns check on taps

2017-12-05 Thread Kevin Cernekee
Currently, a nlmon link inside a child namespace can observe systemwide
netlink activity.  Filter the traffic so that in a non-init netns,
nlmon can only sniff netlink messages from its own netns.

Test case:

vpnns -- bash -c "ip link add nlmon0 type nlmon; \
  ip link set nlmon0 up; \
  tcpdump -i nlmon0 -q -w /tmp/nlmon.pcap -U" &
sudo ip xfrm state add src 10.1.1.1 dst 10.1.1.2 proto esp \
spi 0x1 mode transport \
auth sha1 0x616263313233 \
enc aes 0x
grep abc123 /tmp/nlmon.pcap

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 net/netlink/af_netlink.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index b9e0ee4..88381a2 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -253,6 +253,11 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb,
struct sock *sk = skb->sk;
int ret = -ENOMEM;
 
+   if (!net_eq(dev_net(dev), sock_net(sk)) &&
+   !net_eq(dev_net(dev), _net)) {
+   return 0;
+   }
+
dev_hold(dev);
 
if (is_vmalloc_addr(skb->head))
-- 
2.7.4



[PATCH] netlink: Add netns check on taps

2017-12-05 Thread Kevin Cernekee
Currently, a nlmon link inside a child namespace can observe systemwide
netlink activity.  Filter the traffic so that in a non-init netns,
nlmon can only sniff netlink messages from its own netns.

Test case:

vpnns -- bash -c "ip link add nlmon0 type nlmon; \
  ip link set nlmon0 up; \
  tcpdump -i nlmon0 -q -w /tmp/nlmon.pcap -U" &
sudo ip xfrm state add src 10.1.1.1 dst 10.1.1.2 proto esp \
spi 0x1 mode transport \
auth sha1 0x616263313233 \
enc aes 0x
grep abc123 /tmp/nlmon.pcap

Signed-off-by: Kevin Cernekee 
---
 net/netlink/af_netlink.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index b9e0ee4..88381a2 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -253,6 +253,11 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb,
struct sock *sk = skb->sk;
int ret = -ENOMEM;
 
+   if (!net_eq(dev_net(dev), sock_net(sk)) &&
+   !net_eq(dev_net(dev), _net)) {
+   return 0;
+   }
+
dev_hold(dev);
 
if (is_vmalloc_addr(skb->head))
-- 
2.7.4



[PATCH] netfilter: nfnetlink_cthelper: Add missing permission checks

2017-12-03 Thread Kevin Cernekee
The capability check in nfnetlink_rcv() verifies that the caller
has CAP_NET_ADMIN in the namespace that "owns" the netlink socket.
However, nfnl_cthelper_list is shared by all net namespaces on the
system.  An unprivileged user can create user and net namespaces
in which he holds CAP_NET_ADMIN to bypass the netlink_net_capable()
check:

$ nfct helper list
nfct v1.4.4: netlink error: Operation not permitted
$ vpnns -- nfct helper list
{
.name = ftp,
.queuenum = 0,
.l3protonum = 2,
.l4protonum = 6,
.priv_data_len = 24,
.status = enabled,
};

Add capable() checks in nfnetlink_cthelper, as this is cleaner than
trying to generalize the solution.

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 net/netfilter/nfnetlink_cthelper.c | 10 ++
 1 file changed, 10 insertions(+)


I think xt_osf has the same issue with respect to xt_osf_fingers.
Also, it looks like nlmon devices created in an unprivileged netns can
see netlink activity from the init namespace.


diff --git a/net/netfilter/nfnetlink_cthelper.c 
b/net/netfilter/nfnetlink_cthelper.c
index 41628b393673..d33ce6d5ebce 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -407,6 +408,9 @@ static int nfnl_cthelper_new(struct net *net, struct sock 
*nfnl,
struct nfnl_cthelper *nlcth;
int ret = 0;
 
+   if (!capable(CAP_NET_ADMIN))
+   return -EPERM;
+
if (!tb[NFCTH_NAME] || !tb[NFCTH_TUPLE])
return -EINVAL;
 
@@ -611,6 +615,9 @@ static int nfnl_cthelper_get(struct net *net, struct sock 
*nfnl,
struct nfnl_cthelper *nlcth;
bool tuple_set = false;
 
+   if (!capable(CAP_NET_ADMIN))
+   return -EPERM;
+
if (nlh->nlmsg_flags & NLM_F_DUMP) {
struct netlink_dump_control c = {
.dump = nfnl_cthelper_dump_table,
@@ -678,6 +685,9 @@ static int nfnl_cthelper_del(struct net *net, struct sock 
*nfnl,
struct nfnl_cthelper *nlcth, *n;
int j = 0, ret;
 
+   if (!capable(CAP_NET_ADMIN))
+   return -EPERM;
+
if (tb[NFCTH_NAME])
helper_name = nla_data(tb[NFCTH_NAME]);
 
-- 
2.7.4



[PATCH] netfilter: nfnetlink_cthelper: Add missing permission checks

2017-12-03 Thread Kevin Cernekee
The capability check in nfnetlink_rcv() verifies that the caller
has CAP_NET_ADMIN in the namespace that "owns" the netlink socket.
However, nfnl_cthelper_list is shared by all net namespaces on the
system.  An unprivileged user can create user and net namespaces
in which he holds CAP_NET_ADMIN to bypass the netlink_net_capable()
check:

$ nfct helper list
nfct v1.4.4: netlink error: Operation not permitted
$ vpnns -- nfct helper list
{
.name = ftp,
.queuenum = 0,
.l3protonum = 2,
.l4protonum = 6,
.priv_data_len = 24,
.status = enabled,
};

Add capable() checks in nfnetlink_cthelper, as this is cleaner than
trying to generalize the solution.

Signed-off-by: Kevin Cernekee 
---
 net/netfilter/nfnetlink_cthelper.c | 10 ++
 1 file changed, 10 insertions(+)


I think xt_osf has the same issue with respect to xt_osf_fingers.
Also, it looks like nlmon devices created in an unprivileged netns can
see netlink activity from the init namespace.


diff --git a/net/netfilter/nfnetlink_cthelper.c 
b/net/netfilter/nfnetlink_cthelper.c
index 41628b393673..d33ce6d5ebce 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -407,6 +408,9 @@ static int nfnl_cthelper_new(struct net *net, struct sock 
*nfnl,
struct nfnl_cthelper *nlcth;
int ret = 0;
 
+   if (!capable(CAP_NET_ADMIN))
+   return -EPERM;
+
if (!tb[NFCTH_NAME] || !tb[NFCTH_TUPLE])
return -EINVAL;
 
@@ -611,6 +615,9 @@ static int nfnl_cthelper_get(struct net *net, struct sock 
*nfnl,
struct nfnl_cthelper *nlcth;
bool tuple_set = false;
 
+   if (!capable(CAP_NET_ADMIN))
+   return -EPERM;
+
if (nlh->nlmsg_flags & NLM_F_DUMP) {
struct netlink_dump_control c = {
.dump = nfnl_cthelper_dump_table,
@@ -678,6 +685,9 @@ static int nfnl_cthelper_del(struct net *net, struct sock 
*nfnl,
struct nfnl_cthelper *nlcth, *n;
int j = 0, ret;
 
+   if (!capable(CAP_NET_ADMIN))
+   return -EPERM;
+
if (tb[NFCTH_NAME])
helper_name = nla_data(tb[NFCTH_NAME]);
 
-- 
2.7.4



[PATCH V2 2/2] netfilter: ctnetlink: Fix regression in CTA_HELP processing

2017-01-26 Thread Kevin Cernekee
Prior to Linux 4.4, it was usually harmless to send a CTA_HELP attribute
containing the name of the current helper.  That is no longer the case:
as of Linux 4.4, if ctnetlink_change_helper() returns an error from
the ct->master check, processing of the request will fail, skipping the
NFQA_EXP attribute (if present).

This patch changes the behavior to improve compatibility with user
programs that expect the kernel interface to work the way it did prior
to Linux 4.4.  If a user program specifies CTA_HELP but the argument
matches the current conntrack helper name, ignore it instead of generating
an error.

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---


V1->V2:

 - Add comment and update changelog, per code review feedback
 - Rebase + retest on net-next


 net/netfilter/nf_conntrack_netlink.c | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index e8f704a6..891f02a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1503,14 +1503,23 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
struct nlattr *helpinfo = NULL;
int err;
 
-   /* don't change helper of sibling connections */
-   if (ct->master)
-   return -EBUSY;
-
err = ctnetlink_parse_help(cda[CTA_HELP], , );
if (err < 0)
return err;
 
+   /* don't change helper of sibling connections */
+   if (ct->master) {
+   /* If we try to change the helper to the same thing twice,
+* treat the second attempt as a no-op instead of returning
+* an error.
+*/
+   if (help && help->helper &&
+   !strcmp(help->helper->name, helpname))
+   return 0;
+   else
+   return -EBUSY;
+   }
+
if (!strcmp(helpname, "")) {
if (help && help->helper) {
/* we had a helper before ... */
-- 
2.7.4



[PATCH V2 2/2] netfilter: ctnetlink: Fix regression in CTA_HELP processing

2017-01-26 Thread Kevin Cernekee
Prior to Linux 4.4, it was usually harmless to send a CTA_HELP attribute
containing the name of the current helper.  That is no longer the case:
as of Linux 4.4, if ctnetlink_change_helper() returns an error from
the ct->master check, processing of the request will fail, skipping the
NFQA_EXP attribute (if present).

This patch changes the behavior to improve compatibility with user
programs that expect the kernel interface to work the way it did prior
to Linux 4.4.  If a user program specifies CTA_HELP but the argument
matches the current conntrack helper name, ignore it instead of generating
an error.

Signed-off-by: Kevin Cernekee 
---


V1->V2:

 - Add comment and update changelog, per code review feedback
 - Rebase + retest on net-next


 net/netfilter/nf_conntrack_netlink.c | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index e8f704a6..891f02a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1503,14 +1503,23 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
struct nlattr *helpinfo = NULL;
int err;
 
-   /* don't change helper of sibling connections */
-   if (ct->master)
-   return -EBUSY;
-
err = ctnetlink_parse_help(cda[CTA_HELP], , );
if (err < 0)
return err;
 
+   /* don't change helper of sibling connections */
+   if (ct->master) {
+   /* If we try to change the helper to the same thing twice,
+* treat the second attempt as a no-op instead of returning
+* an error.
+*/
+   if (help && help->helper &&
+   !strcmp(help->helper->name, helpname))
+   return 0;
+   else
+   return -EBUSY;
+   }
+
if (!strcmp(helpname, "")) {
if (help && help->helper) {
/* we had a helper before ... */
-- 
2.7.4



[PATCH V2 1/2] netfilter: ctnetlink: Fix regression in CTA_STATUS processing

2017-01-26 Thread Kevin Cernekee
The libnetfilter_conntrack userland library always sets IPS_CONFIRMED
when building a CTA_STATUS attribute.  If this toggles the bit from
0->1, the parser will return an error.  On Linux 4.4+ this will cause any
NFQA_EXP attribute in the packet to be ignored.  This breaks conntrackd's
userland helpers because they operate on unconfirmed connections.

Instead of returning -EBUSY if the user program asks to modify an
unchangeable bit, simply ignore the change.

Also, fix the logic so that user programs are allowed to clear
the bits that they are allowed to change.

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---


V1->V2:

 - Create a new ctnetlink_update_status() function, per code review feedback
 - Add comment and update changelog, per code review feedback
 - Rebase + retest on net-next

(Note that the original patch 1/3, which fixed a related problem on
CTA_TIMEOUT, is only needed on old kernels like 4.4.)


 include/uapi/linux/netfilter/nf_conntrack_common.h |  4 
 net/netfilter/nf_conntrack_netlink.c   | 27 +-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h 
b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 6d074d1..6a8e33d 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -82,6 +82,10 @@ enum ip_conntrack_status {
IPS_DYING_BIT = 9,
IPS_DYING = (1 << IPS_DYING_BIT),
 
+   /* Bits that cannot be altered from userland. */
+   IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
+IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING),
+
/* Connection has fixed timeout. */
IPS_FIXED_TIMEOUT_BIT = 10,
IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index 2754045..e8f704a6 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1446,6 +1446,31 @@ ctnetlink_change_status(struct nf_conn *ct, const struct 
nlattr * const cda[])
 }
 
 static int
+ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[])
+{
+   unsigned long d;
+   unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
+   d = ct->status ^ status;
+
+   if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
+   /* SEEN_REPLY bit can only be set */
+   return -EBUSY;
+
+   if (d & IPS_ASSURED && !(status & IPS_ASSURED))
+   /* ASSURED bit can only be set */
+   return -EBUSY;
+
+   /* This check is less strict than ctnetlink_change_status()
+* because callers often flip IPS_EXPECTED bits when sending
+* an NFQA_CT attribute to the kernel.  So ignore the
+* unchangeable bits but do not error out.
+*/
+   ct->status = (status & ~IPS_UNCHANGEABLE_MASK) |
+(ct->status & IPS_UNCHANGEABLE_MASK);
+   return 0;
+}
+
+static int
 ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[])
 {
 #ifdef CONFIG_NF_NAT_NEEDED
@@ -2280,7 +2305,7 @@ ctnetlink_glue_parse_ct(const struct nlattr *cda[], 
struct nf_conn *ct)
return err;
}
if (cda[CTA_STATUS]) {
-   err = ctnetlink_change_status(ct, cda);
+   err = ctnetlink_update_status(ct, cda);
if (err < 0)
return err;
}
-- 
2.7.4



[PATCH V2 1/2] netfilter: ctnetlink: Fix regression in CTA_STATUS processing

2017-01-26 Thread Kevin Cernekee
The libnetfilter_conntrack userland library always sets IPS_CONFIRMED
when building a CTA_STATUS attribute.  If this toggles the bit from
0->1, the parser will return an error.  On Linux 4.4+ this will cause any
NFQA_EXP attribute in the packet to be ignored.  This breaks conntrackd's
userland helpers because they operate on unconfirmed connections.

Instead of returning -EBUSY if the user program asks to modify an
unchangeable bit, simply ignore the change.

Also, fix the logic so that user programs are allowed to clear
the bits that they are allowed to change.

Signed-off-by: Kevin Cernekee 
---


V1->V2:

 - Create a new ctnetlink_update_status() function, per code review feedback
 - Add comment and update changelog, per code review feedback
 - Rebase + retest on net-next

(Note that the original patch 1/3, which fixed a related problem on
CTA_TIMEOUT, is only needed on old kernels like 4.4.)


 include/uapi/linux/netfilter/nf_conntrack_common.h |  4 
 net/netfilter/nf_conntrack_netlink.c   | 27 +-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h 
b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 6d074d1..6a8e33d 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -82,6 +82,10 @@ enum ip_conntrack_status {
IPS_DYING_BIT = 9,
IPS_DYING = (1 << IPS_DYING_BIT),
 
+   /* Bits that cannot be altered from userland. */
+   IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
+IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING),
+
/* Connection has fixed timeout. */
IPS_FIXED_TIMEOUT_BIT = 10,
IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index 2754045..e8f704a6 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1446,6 +1446,31 @@ ctnetlink_change_status(struct nf_conn *ct, const struct 
nlattr * const cda[])
 }
 
 static int
+ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[])
+{
+   unsigned long d;
+   unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
+   d = ct->status ^ status;
+
+   if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
+   /* SEEN_REPLY bit can only be set */
+   return -EBUSY;
+
+   if (d & IPS_ASSURED && !(status & IPS_ASSURED))
+   /* ASSURED bit can only be set */
+   return -EBUSY;
+
+   /* This check is less strict than ctnetlink_change_status()
+* because callers often flip IPS_EXPECTED bits when sending
+* an NFQA_CT attribute to the kernel.  So ignore the
+* unchangeable bits but do not error out.
+*/
+   ct->status = (status & ~IPS_UNCHANGEABLE_MASK) |
+(ct->status & IPS_UNCHANGEABLE_MASK);
+   return 0;
+}
+
+static int
 ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[])
 {
 #ifdef CONFIG_NF_NAT_NEEDED
@@ -2280,7 +2305,7 @@ ctnetlink_glue_parse_ct(const struct nlattr *cda[], 
struct nf_conn *ct)
return err;
}
if (cda[CTA_STATUS]) {
-   err = ctnetlink_change_status(ct, cda);
+   err = ctnetlink_update_status(ct, cda);
if (err < 0)
return err;
}
-- 
2.7.4



[PATCH 1/4] xfrm: Constify xfrm_user arguments and xfrm_mgr callback APIs

2017-01-20 Thread Kevin Cernekee
This provides a better sense of the data flow and inputs/outputs.  No
change to code size or functionality.

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 include/net/xfrm.h |  36 --
 net/key/af_key.c   |  34 +++--
 net/xfrm/xfrm_policy.c |   8 +-
 net/xfrm/xfrm_state.c  |   2 +-
 net/xfrm/xfrm_user.c   | 342 +
 5 files changed, 253 insertions(+), 169 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 31947b9c21d6..34298d78ba45 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -228,7 +228,7 @@ struct xfrm_state {
void*data;
 };
 
-static inline struct net *xs_net(struct xfrm_state *x)
+static inline struct net *xs_net(const struct xfrm_state *x)
 {
return read_pnet(>xs_net);
 }
@@ -587,12 +587,23 @@ struct xfrm_migrate {
 struct xfrm_mgr {
struct list_headlist;
char*id;
-   int (*notify)(struct xfrm_state *x, const struct 
km_event *c);
-   int (*acquire)(struct xfrm_state *x, struct 
xfrm_tmpl *, struct xfrm_policy *xp);
-   struct xfrm_policy  *(*compile_policy)(struct sock *sk, int opt, u8 
*data, int len, int *dir);
-   int (*new_mapping)(struct xfrm_state *x, 
xfrm_address_t *ipaddr, __be16 sport);
-   int (*notify_policy)(struct xfrm_policy *x, int 
dir, const struct km_event *c);
-   int (*report)(struct net *net, u8 proto, struct 
xfrm_selector *sel, xfrm_address_t *addr);
+   int (*notify)(const struct xfrm_state *x,
+ const struct km_event *c);
+   int (*acquire)(struct xfrm_state *x,
+  const struct xfrm_tmpl *,
+  const struct xfrm_policy *xp);
+   struct xfrm_policy  *(*compile_policy)(struct sock *sk,
+  int opt, u8 *data,
+  int len, int *dir);
+   int (*new_mapping)(struct xfrm_state *x,
+  const xfrm_address_t *ipaddr,
+  __be16 sport);
+   int (*notify_policy)(const struct xfrm_policy *x,
+int dir,
+const struct km_event *c);
+   int (*report)(struct net *net, u8 proto,
+ const struct xfrm_selector *sel,
+ const xfrm_address_t *addr);
int (*migrate)(const struct xfrm_selector *sel,
   u8 dir, u8 type,
   const struct xfrm_migrate *m,
@@ -1432,7 +1443,7 @@ static inline void xfrm_sysctl_fini(struct net *net)
 void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto,
  struct xfrm_address_filter *filter);
 int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
-   int (*func)(struct xfrm_state *, int, void*), void *);
+   int (*func)(const struct xfrm_state *, int, void*), void *);
 void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net);
 struct xfrm_state *xfrm_state_alloc(struct net *net);
 struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr,
@@ -1584,13 +1595,13 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, 
gfp_t gfp);
 
 void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type);
 int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
-int (*func)(struct xfrm_policy *, int, int, void*),
+int (*func)(const struct xfrm_policy *, int, int, void*),
 void *);
 void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net);
 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
 struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
  u8 type, int dir,
- struct xfrm_selector *sel,
+ const struct xfrm_selector *sel,
  struct xfrm_sec_ctx *ctx, int delete,
  int *err);
 struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir,
@@ -1695,7 +1706,7 @@ static inline int xfrm_acquire_is_on(struct net *net)
 }
 #endif
 
-static inline int aead_len(struct xfrm_algo_aead *alg)
+static inline int aead_len(const struct xfrm_algo_aead *alg)
 {
return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
 }
@@ -1710,7 +1721,8 @@ s

[PATCH 0/4] Make xfrm usable by 32-bit programs

2017-01-20 Thread Kevin Cernekee
Several of the xfrm netlink and setsockopt() interfaces are not usable
from a 32-bit binary running on a 64-bit kernel due to struct padding
differences.  This has been the case for many, many years[0].  This
patch series deprecates the broken netlink messages and replaces them
with packed structs that are compatible between 64-bit and 32-bit
programs.  It retains support for legacy user programs (i.e. anything
that is currently working today), and allows legacy support to be
compiled out via CONFIG_XFRM_USER_LEGACY if it becomes unnecessary in
the future.

Earlier attempts at fixing the problem had implemented a compat layer.
A compat layer is helpful because it avoids the need to recompile old
user binaries, but there are many challenges involved in implementing
it.  I believe a compat layer is of limited value in this instance
because anybody who really needed to solve the problem without
recompiling their binaries has almost certainly found another solution
in the ~7 years since the compat patches were first proposed.

A benefit of this approach is that long-term, the broken netlink messages
will no longer be used.  A drawback is that in the short term, user
programs that want to adopt the new message formats will require a
modern kernel.  Projects like strongSwan and iproute2 bundle the xfrm.h
header inside their own source trees, so they will need to make a
judgment call on when to remove support for kernels that do not support
the new messages.  And programs built against the new kernel headers
will not work on old kernels.  (Perhaps this is an argument for naming
the new messages _NEW, rather than renaming the old messages to
_LEGACY.)

The following netlink messages are affected:

XFRM_MSG_NEWSA
XFRM_MSG_UPDSA
XFRM_MSG_DELSA
XFRM_MSG_GETSA
XFRM_MSG_NEWPOLICY
XFRM_MSG_UPDPOLICY
XFRM_MSG_DELPOLICY
XFRM_MSG_GETPOLICY
XFRM_MSG_ALLOCSPI
XFRM_MSG_ACQUIRE
XFRM_MSG_EXPIRE
XFRM_MSG_POLEXPIRE

The following setsockopt() settings are affected:

IP_XFRM_POLICY
IPV6_XFRM_POLICY

The root cause of the problem involves padding and alignment
incompatibilities in the following structs:

xfrm_usersa_info 220 bytes on i386 -> 224 bytes on amd64
xfrm_userpolicy_info 164 -> 168
xfrm_userspi_info 228 -> 232, offset mismatch on min
xfrm_user_acquire 276 -> 280, offset mismatch on aalgos
xfrm_user_expire 224 -> 232, offset mismatch on hard
xfrm_user_polexpire 168 -> 176, offset mismatch on hard

Most xfrm netlink messages consist of an xfrm_* struct followed by
additional attributes (struct nlattr TLV), so even cases where the
struct layout (sans padding) is identical will result in incompatible
messages.

Some possible tweaks to this approach:

a) Name the new messages _NEW instead of renaming the old messages
_LEGACY.  This fixes the "new binary on old kernel" problem, but it
means that callers need to change every call site in their programs
to explicitly request the new interface.

b) Tweak xfrm.h so that user programs build against the legacy
interfaces by default, but can alter that behavior using a #define
flag.  Maybe in a few years, assume that everyone is running a modern
kernel and make the new interface the default.


[0] https://www.spinics.net/lists/netdev/msg126176.html


Kevin Cernekee (4):
  xfrm: Constify xfrm_user arguments and xfrm_mgr callback APIs
  xfrm_user: Allow common functions to be called from another file
  xfrm_user: Initial commit of xfrm_user_legacy.c
  xfrm_user: Add new 32/64-agnostic netlink messages

 include/net/xfrm.h  |   36 +-
 include/uapi/linux/xfrm.h   |  152 --
 net/key/af_key.c|   34 +-
 net/xfrm/Kconfig|   14 +
 net/xfrm/Makefile   |8 +-
 net/xfrm/xfrm_policy.c  |8 +-
 net/xfrm/xfrm_state.c   |2 +-
 net/xfrm/xfrm_user.c|  587 +-
 net/xfrm/xfrm_user.h|  165 +++
 net/xfrm/xfrm_user_legacy.c | 1140 +++
 security/selinux/nlmsgtab.c |   61 ++-
 11 files changed, 1890 insertions(+), 317 deletions(-)
 create mode 100644 net/xfrm/xfrm_user.h
 create mode 100644 net/xfrm/xfrm_user_legacy.c

-- 
2.11.0.483.g087da7b7c-goog



[PATCH 0/4] Make xfrm usable by 32-bit programs

2017-01-20 Thread Kevin Cernekee
Several of the xfrm netlink and setsockopt() interfaces are not usable
from a 32-bit binary running on a 64-bit kernel due to struct padding
differences.  This has been the case for many, many years[0].  This
patch series deprecates the broken netlink messages and replaces them
with packed structs that are compatible between 64-bit and 32-bit
programs.  It retains support for legacy user programs (i.e. anything
that is currently working today), and allows legacy support to be
compiled out via CONFIG_XFRM_USER_LEGACY if it becomes unnecessary in
the future.

Earlier attempts at fixing the problem had implemented a compat layer.
A compat layer is helpful because it avoids the need to recompile old
user binaries, but there are many challenges involved in implementing
it.  I believe a compat layer is of limited value in this instance
because anybody who really needed to solve the problem without
recompiling their binaries has almost certainly found another solution
in the ~7 years since the compat patches were first proposed.

A benefit of this approach is that long-term, the broken netlink messages
will no longer be used.  A drawback is that in the short term, user
programs that want to adopt the new message formats will require a
modern kernel.  Projects like strongSwan and iproute2 bundle the xfrm.h
header inside their own source trees, so they will need to make a
judgment call on when to remove support for kernels that do not support
the new messages.  And programs built against the new kernel headers
will not work on old kernels.  (Perhaps this is an argument for naming
the new messages _NEW, rather than renaming the old messages to
_LEGACY.)

The following netlink messages are affected:

XFRM_MSG_NEWSA
XFRM_MSG_UPDSA
XFRM_MSG_DELSA
XFRM_MSG_GETSA
XFRM_MSG_NEWPOLICY
XFRM_MSG_UPDPOLICY
XFRM_MSG_DELPOLICY
XFRM_MSG_GETPOLICY
XFRM_MSG_ALLOCSPI
XFRM_MSG_ACQUIRE
XFRM_MSG_EXPIRE
XFRM_MSG_POLEXPIRE

The following setsockopt() settings are affected:

IP_XFRM_POLICY
IPV6_XFRM_POLICY

The root cause of the problem involves padding and alignment
incompatibilities in the following structs:

xfrm_usersa_info 220 bytes on i386 -> 224 bytes on amd64
xfrm_userpolicy_info 164 -> 168
xfrm_userspi_info 228 -> 232, offset mismatch on min
xfrm_user_acquire 276 -> 280, offset mismatch on aalgos
xfrm_user_expire 224 -> 232, offset mismatch on hard
xfrm_user_polexpire 168 -> 176, offset mismatch on hard

Most xfrm netlink messages consist of an xfrm_* struct followed by
additional attributes (struct nlattr TLV), so even cases where the
struct layout (sans padding) is identical will result in incompatible
messages.

Some possible tweaks to this approach:

a) Name the new messages _NEW instead of renaming the old messages
_LEGACY.  This fixes the "new binary on old kernel" problem, but it
means that callers need to change every call site in their programs
to explicitly request the new interface.

b) Tweak xfrm.h so that user programs build against the legacy
interfaces by default, but can alter that behavior using a #define
flag.  Maybe in a few years, assume that everyone is running a modern
kernel and make the new interface the default.


[0] https://www.spinics.net/lists/netdev/msg126176.html


Kevin Cernekee (4):
  xfrm: Constify xfrm_user arguments and xfrm_mgr callback APIs
  xfrm_user: Allow common functions to be called from another file
  xfrm_user: Initial commit of xfrm_user_legacy.c
  xfrm_user: Add new 32/64-agnostic netlink messages

 include/net/xfrm.h  |   36 +-
 include/uapi/linux/xfrm.h   |  152 --
 net/key/af_key.c|   34 +-
 net/xfrm/Kconfig|   14 +
 net/xfrm/Makefile   |8 +-
 net/xfrm/xfrm_policy.c  |8 +-
 net/xfrm/xfrm_state.c   |2 +-
 net/xfrm/xfrm_user.c|  587 +-
 net/xfrm/xfrm_user.h|  165 +++
 net/xfrm/xfrm_user_legacy.c | 1140 +++
 security/selinux/nlmsgtab.c |   61 ++-
 11 files changed, 1890 insertions(+), 317 deletions(-)
 create mode 100644 net/xfrm/xfrm_user.h
 create mode 100644 net/xfrm/xfrm_user_legacy.c

-- 
2.11.0.483.g087da7b7c-goog



[PATCH 1/4] xfrm: Constify xfrm_user arguments and xfrm_mgr callback APIs

2017-01-20 Thread Kevin Cernekee
This provides a better sense of the data flow and inputs/outputs.  No
change to code size or functionality.

Signed-off-by: Kevin Cernekee 
---
 include/net/xfrm.h |  36 --
 net/key/af_key.c   |  34 +++--
 net/xfrm/xfrm_policy.c |   8 +-
 net/xfrm/xfrm_state.c  |   2 +-
 net/xfrm/xfrm_user.c   | 342 +
 5 files changed, 253 insertions(+), 169 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 31947b9c21d6..34298d78ba45 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -228,7 +228,7 @@ struct xfrm_state {
void*data;
 };
 
-static inline struct net *xs_net(struct xfrm_state *x)
+static inline struct net *xs_net(const struct xfrm_state *x)
 {
return read_pnet(>xs_net);
 }
@@ -587,12 +587,23 @@ struct xfrm_migrate {
 struct xfrm_mgr {
struct list_headlist;
char*id;
-   int (*notify)(struct xfrm_state *x, const struct 
km_event *c);
-   int (*acquire)(struct xfrm_state *x, struct 
xfrm_tmpl *, struct xfrm_policy *xp);
-   struct xfrm_policy  *(*compile_policy)(struct sock *sk, int opt, u8 
*data, int len, int *dir);
-   int (*new_mapping)(struct xfrm_state *x, 
xfrm_address_t *ipaddr, __be16 sport);
-   int (*notify_policy)(struct xfrm_policy *x, int 
dir, const struct km_event *c);
-   int (*report)(struct net *net, u8 proto, struct 
xfrm_selector *sel, xfrm_address_t *addr);
+   int (*notify)(const struct xfrm_state *x,
+ const struct km_event *c);
+   int (*acquire)(struct xfrm_state *x,
+  const struct xfrm_tmpl *,
+  const struct xfrm_policy *xp);
+   struct xfrm_policy  *(*compile_policy)(struct sock *sk,
+  int opt, u8 *data,
+  int len, int *dir);
+   int (*new_mapping)(struct xfrm_state *x,
+  const xfrm_address_t *ipaddr,
+  __be16 sport);
+   int (*notify_policy)(const struct xfrm_policy *x,
+int dir,
+const struct km_event *c);
+   int (*report)(struct net *net, u8 proto,
+ const struct xfrm_selector *sel,
+ const xfrm_address_t *addr);
int (*migrate)(const struct xfrm_selector *sel,
   u8 dir, u8 type,
   const struct xfrm_migrate *m,
@@ -1432,7 +1443,7 @@ static inline void xfrm_sysctl_fini(struct net *net)
 void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto,
  struct xfrm_address_filter *filter);
 int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
-   int (*func)(struct xfrm_state *, int, void*), void *);
+   int (*func)(const struct xfrm_state *, int, void*), void *);
 void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net);
 struct xfrm_state *xfrm_state_alloc(struct net *net);
 struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr,
@@ -1584,13 +1595,13 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, 
gfp_t gfp);
 
 void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type);
 int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
-int (*func)(struct xfrm_policy *, int, int, void*),
+int (*func)(const struct xfrm_policy *, int, int, void*),
 void *);
 void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net);
 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
 struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
  u8 type, int dir,
- struct xfrm_selector *sel,
+ const struct xfrm_selector *sel,
  struct xfrm_sec_ctx *ctx, int delete,
  int *err);
 struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir,
@@ -1695,7 +1706,7 @@ static inline int xfrm_acquire_is_on(struct net *net)
 }
 #endif
 
-static inline int aead_len(struct xfrm_algo_aead *alg)
+static inline int aead_len(const struct xfrm_algo_aead *alg)
 {
return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
 }
@@ -1710,7 +1721,8 @@ static inline int xfrm_alg_au

[PATCH 2/4] xfrm_user: Allow common functions to be called from another file

2017-01-20 Thread Kevin Cernekee
xfrm_user_legacy.c will need to call a few common functions.  Make
sure them have an "xfrm_" prefix, and declare them in a new xfrm_user.h
header.

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 net/xfrm/xfrm_user.c | 147 +--
 net/xfrm/xfrm_user.h |  90 +++
 2 files changed, 138 insertions(+), 99 deletions(-)
 create mode 100644 net/xfrm/xfrm_user.h

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index ed389aad4994..4d733f02c3a1 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -32,6 +32,7 @@
 #include 
 #endif
 #include 
+#include "xfrm_user.h"
 
 static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
 {
@@ -100,7 +101,7 @@ static void verify_one_addr(struct nlattr **attrs, enum 
xfrm_attr_type_t type,
*addrp = nla_data(rt);
 }
 
-static inline int verify_sec_ctx_len(struct nlattr **attrs)
+int xfrm_verify_sec_ctx_len(struct nlattr **attrs)
 {
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
struct xfrm_user_sec_ctx *uctx;
@@ -148,8 +149,8 @@ static inline int verify_replay(const struct 
xfrm_usersa_info *p,
return 0;
 }
 
-static int verify_newsa_info(const struct xfrm_usersa_info *p,
-struct nlattr **attrs)
+int xfrm_verify_newsa_info(const struct xfrm_usersa_info *p,
+  struct nlattr **attrs)
 {
int err;
 
@@ -241,7 +242,7 @@ static int verify_newsa_info(const struct xfrm_usersa_info 
*p,
goto out;
if ((err = verify_one_alg(attrs, XFRMA_ALG_COMP)))
goto out;
-   if ((err = verify_sec_ctx_len(attrs)))
+   if ((err = xfrm_verify_sec_ctx_len(attrs)))
goto out;
if ((err = verify_replay(p, attrs)))
goto out;
@@ -460,17 +461,6 @@ static int xfrm_alloc_replay_state_esn(
return 0;
 }
 
-static inline int xfrm_user_sec_ctx_size(const struct xfrm_sec_ctx *xfrm_ctx)
-{
-   int len = 0;
-
-   if (xfrm_ctx) {
-   len += sizeof(struct xfrm_user_sec_ctx);
-   len += xfrm_ctx->ctx_len;
-   }
-   return len;
-}
-
 static void copy_from_user_state(struct xfrm_state *x,
 const struct xfrm_usersa_info *p)
 {
@@ -537,10 +527,10 @@ static void xfrm_update_ae_params(struct xfrm_state *x,
x->replay_maxdiff = nla_get_u32(rt);
 }
 
-static struct xfrm_state *xfrm_state_construct(struct net *net,
-  const struct xfrm_usersa_info *p,
-  struct nlattr **attrs,
-  int *errp)
+struct xfrm_state *xfrm_state_construct(struct net *net,
+   const struct xfrm_usersa_info *p,
+   struct nlattr **attrs,
+   int *errp)
 {
struct xfrm_state *x = xfrm_state_alloc(net);
int err = -ENOMEM;
@@ -634,7 +624,7 @@ static int xfrm_add_sa(struct sk_buff *skb, const struct 
nlmsghdr *nlh,
int err;
struct km_event c;
 
-   err = verify_newsa_info(p, attrs);
+   err = xfrm_verify_newsa_info(p, attrs);
if (err)
return err;
 
@@ -666,10 +656,10 @@ static int xfrm_add_sa(struct sk_buff *skb, const struct 
nlmsghdr *nlh,
return err;
 }
 
-static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
-const struct xfrm_usersa_id *p,
-struct nlattr **attrs,
-int *errp)
+struct xfrm_state *xfrm_user_state_lookup(struct net *net,
+ const struct xfrm_usersa_id *p,
+ struct nlattr **attrs,
+ int *errp)
 {
struct xfrm_state *x = NULL;
struct xfrm_mark m;
@@ -757,14 +747,7 @@ static void copy_to_user_state(const struct xfrm_state *x,
p->seq = x->km.seq;
 }
 
-struct xfrm_dump_info {
-   struct sk_buff *in_skb;
-   struct sk_buff *out_skb;
-   u32 nlmsg_seq;
-   u16 nlmsg_flags;
-};
-
-static int copy_sec_ctx(const struct xfrm_sec_ctx *s, struct sk_buff *skb)
+int xfrm_copy_sec_ctx(const struct xfrm_sec_ctx *s, struct sk_buff *skb)
 {
struct xfrm_user_sec_ctx *uctx;
struct nlattr *attr;
@@ -785,8 +768,8 @@ static int copy_sec_ctx(const struct xfrm_sec_ctx *s, 
struct sk_buff *skb)
return 0;
 }
 
-static int copy_to_user_auth(const struct xfrm_algo_auth *auth,
-struct sk_buff *skb)
+int xfrm_copy_to_user_auth(const struct xfrm_algo_auth *auth,
+  struct sk_buff *skb)
 {
struct xfrm_algo *algo;
struct nlatt

[PATCH 2/4] xfrm_user: Allow common functions to be called from another file

2017-01-20 Thread Kevin Cernekee
xfrm_user_legacy.c will need to call a few common functions.  Make
sure them have an "xfrm_" prefix, and declare them in a new xfrm_user.h
header.

Signed-off-by: Kevin Cernekee 
---
 net/xfrm/xfrm_user.c | 147 +--
 net/xfrm/xfrm_user.h |  90 +++
 2 files changed, 138 insertions(+), 99 deletions(-)
 create mode 100644 net/xfrm/xfrm_user.h

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index ed389aad4994..4d733f02c3a1 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -32,6 +32,7 @@
 #include 
 #endif
 #include 
+#include "xfrm_user.h"
 
 static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
 {
@@ -100,7 +101,7 @@ static void verify_one_addr(struct nlattr **attrs, enum 
xfrm_attr_type_t type,
*addrp = nla_data(rt);
 }
 
-static inline int verify_sec_ctx_len(struct nlattr **attrs)
+int xfrm_verify_sec_ctx_len(struct nlattr **attrs)
 {
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
struct xfrm_user_sec_ctx *uctx;
@@ -148,8 +149,8 @@ static inline int verify_replay(const struct 
xfrm_usersa_info *p,
return 0;
 }
 
-static int verify_newsa_info(const struct xfrm_usersa_info *p,
-struct nlattr **attrs)
+int xfrm_verify_newsa_info(const struct xfrm_usersa_info *p,
+  struct nlattr **attrs)
 {
int err;
 
@@ -241,7 +242,7 @@ static int verify_newsa_info(const struct xfrm_usersa_info 
*p,
goto out;
if ((err = verify_one_alg(attrs, XFRMA_ALG_COMP)))
goto out;
-   if ((err = verify_sec_ctx_len(attrs)))
+   if ((err = xfrm_verify_sec_ctx_len(attrs)))
goto out;
if ((err = verify_replay(p, attrs)))
goto out;
@@ -460,17 +461,6 @@ static int xfrm_alloc_replay_state_esn(
return 0;
 }
 
-static inline int xfrm_user_sec_ctx_size(const struct xfrm_sec_ctx *xfrm_ctx)
-{
-   int len = 0;
-
-   if (xfrm_ctx) {
-   len += sizeof(struct xfrm_user_sec_ctx);
-   len += xfrm_ctx->ctx_len;
-   }
-   return len;
-}
-
 static void copy_from_user_state(struct xfrm_state *x,
 const struct xfrm_usersa_info *p)
 {
@@ -537,10 +527,10 @@ static void xfrm_update_ae_params(struct xfrm_state *x,
x->replay_maxdiff = nla_get_u32(rt);
 }
 
-static struct xfrm_state *xfrm_state_construct(struct net *net,
-  const struct xfrm_usersa_info *p,
-  struct nlattr **attrs,
-  int *errp)
+struct xfrm_state *xfrm_state_construct(struct net *net,
+   const struct xfrm_usersa_info *p,
+   struct nlattr **attrs,
+   int *errp)
 {
struct xfrm_state *x = xfrm_state_alloc(net);
int err = -ENOMEM;
@@ -634,7 +624,7 @@ static int xfrm_add_sa(struct sk_buff *skb, const struct 
nlmsghdr *nlh,
int err;
struct km_event c;
 
-   err = verify_newsa_info(p, attrs);
+   err = xfrm_verify_newsa_info(p, attrs);
if (err)
return err;
 
@@ -666,10 +656,10 @@ static int xfrm_add_sa(struct sk_buff *skb, const struct 
nlmsghdr *nlh,
return err;
 }
 
-static struct xfrm_state *xfrm_user_state_lookup(struct net *net,
-const struct xfrm_usersa_id *p,
-struct nlattr **attrs,
-int *errp)
+struct xfrm_state *xfrm_user_state_lookup(struct net *net,
+ const struct xfrm_usersa_id *p,
+ struct nlattr **attrs,
+ int *errp)
 {
struct xfrm_state *x = NULL;
struct xfrm_mark m;
@@ -757,14 +747,7 @@ static void copy_to_user_state(const struct xfrm_state *x,
p->seq = x->km.seq;
 }
 
-struct xfrm_dump_info {
-   struct sk_buff *in_skb;
-   struct sk_buff *out_skb;
-   u32 nlmsg_seq;
-   u16 nlmsg_flags;
-};
-
-static int copy_sec_ctx(const struct xfrm_sec_ctx *s, struct sk_buff *skb)
+int xfrm_copy_sec_ctx(const struct xfrm_sec_ctx *s, struct sk_buff *skb)
 {
struct xfrm_user_sec_ctx *uctx;
struct nlattr *attr;
@@ -785,8 +768,8 @@ static int copy_sec_ctx(const struct xfrm_sec_ctx *s, 
struct sk_buff *skb)
return 0;
 }
 
-static int copy_to_user_auth(const struct xfrm_algo_auth *auth,
-struct sk_buff *skb)
+int xfrm_copy_to_user_auth(const struct xfrm_algo_auth *auth,
+  struct sk_buff *skb)
 {
struct xfrm_algo *algo;
struct nlattr *nla;
@@ -837,7 +820,7 @@ static int copy_

[PATCH 4/4] xfrm_user: Add new 32/64-agnostic netlink messages

2017-01-20 Thread Kevin Cernekee
Add several new message types to address longstanding 32-bit/64-bit
compatibility issues.  Use xfrm_user_legacy to handle the existing
message types, which will retain the old IDs for compatibility with
existing binaries.

For user->kernel messages, the nlmsg_type will determine whether to use
the old format or the new format (for both requests and replies).  For
kernel->user multicasts, both types will be sent.

setsockopt() will deduce the format from the length.

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 include/uapi/linux/xfrm.h   | 152 ++-
 net/xfrm/xfrm_user.c| 136 ---
 net/xfrm/xfrm_user.h|  75 
 net/xfrm/xfrm_user_legacy.c | 169 
 security/selinux/nlmsgtab.c |  61 +---
 5 files changed, 466 insertions(+), 127 deletions(-)

diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h
index 1fc62b239f1b..ae5f97681989 100644
--- a/include/uapi/linux/xfrm.h
+++ b/include/uapi/linux/xfrm.h
@@ -1,6 +1,7 @@
 #ifndef _LINUX_XFRM_H
 #define _LINUX_XFRM_H
 
+#include 
 #include 
 #include 
 
@@ -157,34 +158,34 @@ enum {
 enum {
XFRM_MSG_BASE = 0x10,
 
-   XFRM_MSG_NEWSA = 0x10,
-#define XFRM_MSG_NEWSA XFRM_MSG_NEWSA
-   XFRM_MSG_DELSA,
-#define XFRM_MSG_DELSA XFRM_MSG_DELSA
-   XFRM_MSG_GETSA,
-#define XFRM_MSG_GETSA XFRM_MSG_GETSA
-
-   XFRM_MSG_NEWPOLICY,
-#define XFRM_MSG_NEWPOLICY XFRM_MSG_NEWPOLICY
-   XFRM_MSG_DELPOLICY,
-#define XFRM_MSG_DELPOLICY XFRM_MSG_DELPOLICY
-   XFRM_MSG_GETPOLICY,
-#define XFRM_MSG_GETPOLICY XFRM_MSG_GETPOLICY
-
-   XFRM_MSG_ALLOCSPI,
-#define XFRM_MSG_ALLOCSPI XFRM_MSG_ALLOCSPI
-   XFRM_MSG_ACQUIRE,
-#define XFRM_MSG_ACQUIRE XFRM_MSG_ACQUIRE
-   XFRM_MSG_EXPIRE,
-#define XFRM_MSG_EXPIRE XFRM_MSG_EXPIRE
-
-   XFRM_MSG_UPDPOLICY,
-#define XFRM_MSG_UPDPOLICY XFRM_MSG_UPDPOLICY
-   XFRM_MSG_UPDSA,
-#define XFRM_MSG_UPDSA XFRM_MSG_UPDSA
-
-   XFRM_MSG_POLEXPIRE,
-#define XFRM_MSG_POLEXPIRE XFRM_MSG_POLEXPIRE
+   XFRM_MSG_NEWSA_LEGACY = 0x10,
+#define XFRM_MSG_NEWSA_LEGACY XFRM_MSG_NEWSA_LEGACY
+   XFRM_MSG_DELSA_LEGACY,
+#define XFRM_MSG_DELSA_LEGACY XFRM_MSG_DELSA_LEGACY
+   XFRM_MSG_GETSA_LEGACY,
+#define XFRM_MSG_GETSA_LEGACY XFRM_MSG_GETSA_LEGACY
+
+   XFRM_MSG_NEWPOLICY_LEGACY,
+#define XFRM_MSG_NEWPOLICY_LEGACY XFRM_MSG_NEWPOLICY_LEGACY
+   XFRM_MSG_DELPOLICY_LEGACY,
+#define XFRM_MSG_DELPOLICY_LEGACY XFRM_MSG_DELPOLICY_LEGACY
+   XFRM_MSG_GETPOLICY_LEGACY,
+#define XFRM_MSG_GETPOLICY_LEGACY XFRM_MSG_GETPOLICY_LEGACY
+
+   XFRM_MSG_ALLOCSPI_LEGACY,
+#define XFRM_MSG_ALLOCSPI_LEGACY XFRM_MSG_ALLOCSPI_LEGACY
+   XFRM_MSG_ACQUIRE_LEGACY,
+#define XFRM_MSG_ACQUIRE_LEGACY XFRM_MSG_ACQUIRE_LEGACY
+   XFRM_MSG_EXPIRE_LEGACY,
+#define XFRM_MSG_EXPIRE_LEGACY XFRM_MSG_EXPIRE_LEGACY
+
+   XFRM_MSG_UPDPOLICY_LEGACY,
+#define XFRM_MSG_UPDPOLICY_LEGACY XFRM_MSG_UPDPOLICY_LEGACY
+   XFRM_MSG_UPDSA_LEGACY,
+#define XFRM_MSG_UPDSA_LEGACY XFRM_MSG_UPDSA_LEGACY
+
+   XFRM_MSG_POLEXPIRE_LEGACY,
+#define XFRM_MSG_POLEXPIRE_LEGACY XFRM_MSG_POLEXPIRE_LEGACY
 
XFRM_MSG_FLUSHSA,
 #define XFRM_MSG_FLUSHSA XFRM_MSG_FLUSHSA
@@ -214,6 +215,34 @@ enum {
 
XFRM_MSG_MAPPING,
 #define XFRM_MSG_MAPPING XFRM_MSG_MAPPING
+
+   XFRM_MSG_ALLOCSPI,
+#define XFRM_MSG_ALLOCSPI XFRM_MSG_ALLOCSPI
+   XFRM_MSG_ACQUIRE,
+#define XFRM_MSG_ACQUIRE XFRM_MSG_ACQUIRE
+   XFRM_MSG_EXPIRE,
+#define XFRM_MSG_EXPIRE XFRM_MSG_EXPIRE
+   XFRM_MSG_POLEXPIRE,
+#define XFRM_MSG_POLEXPIRE XFRM_MSG_POLEXPIRE
+
+   XFRM_MSG_NEWSA,
+#define XFRM_MSG_NEWSA XFRM_MSG_NEWSA
+   XFRM_MSG_UPDSA,
+#define XFRM_MSG_UPDSA XFRM_MSG_UPDSA
+   XFRM_MSG_DELSA,
+#define XFRM_MSG_DELSA XFRM_MSG_DELSA
+   XFRM_MSG_GETSA,
+#define XFRM_MSG_GETSA XFRM_MSG_GETSA
+
+   XFRM_MSG_NEWPOLICY,
+#define XFRM_MSG_NEWPOLICY XFRM_MSG_NEWPOLICY
+   XFRM_MSG_UPDPOLICY,
+#define XFRM_MSG_UPDPOLICY XFRM_MSG_UPDPOLICY
+   XFRM_MSG_DELPOLICY,
+#define XFRM_MSG_DELPOLICY XFRM_MSG_DELPOLICY
+   XFRM_MSG_GETPOLICY,
+#define XFRM_MSG_GETPOLICY XFRM_MSG_GETPOLICY
+
__XFRM_MSG_MAX
 };
 #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
@@ -221,7 +250,7 @@ enum {
 #define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)
 
 /*
- * Generic LSM security context for comunicating to user space
+ * Generic LSM security context for communicating to user space
  * NOTE: Same format as sadb_x_sec_ctx
  */
 struct xfrm_user_sec_ctx {
@@ -357,6 +386,22 @@ struct xfrmu_spdhthresh {
__u8 rbits;
 };
 
+/* Legacy structs are incompatible between 32-bit and 64-bit. */
+struct xfrm_usersa_info_legacy {
+   struct xfrm_selectorsel;
+   struct xfrm_id  id;
+   xfrm_address_t  saddr;
+   struct xfrm_lifetime_cfglft;
+   struct xfrm_lifetime_cur  

[PATCH 4/4] xfrm_user: Add new 32/64-agnostic netlink messages

2017-01-20 Thread Kevin Cernekee
Add several new message types to address longstanding 32-bit/64-bit
compatibility issues.  Use xfrm_user_legacy to handle the existing
message types, which will retain the old IDs for compatibility with
existing binaries.

For user->kernel messages, the nlmsg_type will determine whether to use
the old format or the new format (for both requests and replies).  For
kernel->user multicasts, both types will be sent.

setsockopt() will deduce the format from the length.

Signed-off-by: Kevin Cernekee 
---
 include/uapi/linux/xfrm.h   | 152 ++-
 net/xfrm/xfrm_user.c| 136 ---
 net/xfrm/xfrm_user.h|  75 
 net/xfrm/xfrm_user_legacy.c | 169 
 security/selinux/nlmsgtab.c |  61 +---
 5 files changed, 466 insertions(+), 127 deletions(-)

diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h
index 1fc62b239f1b..ae5f97681989 100644
--- a/include/uapi/linux/xfrm.h
+++ b/include/uapi/linux/xfrm.h
@@ -1,6 +1,7 @@
 #ifndef _LINUX_XFRM_H
 #define _LINUX_XFRM_H
 
+#include 
 #include 
 #include 
 
@@ -157,34 +158,34 @@ enum {
 enum {
XFRM_MSG_BASE = 0x10,
 
-   XFRM_MSG_NEWSA = 0x10,
-#define XFRM_MSG_NEWSA XFRM_MSG_NEWSA
-   XFRM_MSG_DELSA,
-#define XFRM_MSG_DELSA XFRM_MSG_DELSA
-   XFRM_MSG_GETSA,
-#define XFRM_MSG_GETSA XFRM_MSG_GETSA
-
-   XFRM_MSG_NEWPOLICY,
-#define XFRM_MSG_NEWPOLICY XFRM_MSG_NEWPOLICY
-   XFRM_MSG_DELPOLICY,
-#define XFRM_MSG_DELPOLICY XFRM_MSG_DELPOLICY
-   XFRM_MSG_GETPOLICY,
-#define XFRM_MSG_GETPOLICY XFRM_MSG_GETPOLICY
-
-   XFRM_MSG_ALLOCSPI,
-#define XFRM_MSG_ALLOCSPI XFRM_MSG_ALLOCSPI
-   XFRM_MSG_ACQUIRE,
-#define XFRM_MSG_ACQUIRE XFRM_MSG_ACQUIRE
-   XFRM_MSG_EXPIRE,
-#define XFRM_MSG_EXPIRE XFRM_MSG_EXPIRE
-
-   XFRM_MSG_UPDPOLICY,
-#define XFRM_MSG_UPDPOLICY XFRM_MSG_UPDPOLICY
-   XFRM_MSG_UPDSA,
-#define XFRM_MSG_UPDSA XFRM_MSG_UPDSA
-
-   XFRM_MSG_POLEXPIRE,
-#define XFRM_MSG_POLEXPIRE XFRM_MSG_POLEXPIRE
+   XFRM_MSG_NEWSA_LEGACY = 0x10,
+#define XFRM_MSG_NEWSA_LEGACY XFRM_MSG_NEWSA_LEGACY
+   XFRM_MSG_DELSA_LEGACY,
+#define XFRM_MSG_DELSA_LEGACY XFRM_MSG_DELSA_LEGACY
+   XFRM_MSG_GETSA_LEGACY,
+#define XFRM_MSG_GETSA_LEGACY XFRM_MSG_GETSA_LEGACY
+
+   XFRM_MSG_NEWPOLICY_LEGACY,
+#define XFRM_MSG_NEWPOLICY_LEGACY XFRM_MSG_NEWPOLICY_LEGACY
+   XFRM_MSG_DELPOLICY_LEGACY,
+#define XFRM_MSG_DELPOLICY_LEGACY XFRM_MSG_DELPOLICY_LEGACY
+   XFRM_MSG_GETPOLICY_LEGACY,
+#define XFRM_MSG_GETPOLICY_LEGACY XFRM_MSG_GETPOLICY_LEGACY
+
+   XFRM_MSG_ALLOCSPI_LEGACY,
+#define XFRM_MSG_ALLOCSPI_LEGACY XFRM_MSG_ALLOCSPI_LEGACY
+   XFRM_MSG_ACQUIRE_LEGACY,
+#define XFRM_MSG_ACQUIRE_LEGACY XFRM_MSG_ACQUIRE_LEGACY
+   XFRM_MSG_EXPIRE_LEGACY,
+#define XFRM_MSG_EXPIRE_LEGACY XFRM_MSG_EXPIRE_LEGACY
+
+   XFRM_MSG_UPDPOLICY_LEGACY,
+#define XFRM_MSG_UPDPOLICY_LEGACY XFRM_MSG_UPDPOLICY_LEGACY
+   XFRM_MSG_UPDSA_LEGACY,
+#define XFRM_MSG_UPDSA_LEGACY XFRM_MSG_UPDSA_LEGACY
+
+   XFRM_MSG_POLEXPIRE_LEGACY,
+#define XFRM_MSG_POLEXPIRE_LEGACY XFRM_MSG_POLEXPIRE_LEGACY
 
XFRM_MSG_FLUSHSA,
 #define XFRM_MSG_FLUSHSA XFRM_MSG_FLUSHSA
@@ -214,6 +215,34 @@ enum {
 
XFRM_MSG_MAPPING,
 #define XFRM_MSG_MAPPING XFRM_MSG_MAPPING
+
+   XFRM_MSG_ALLOCSPI,
+#define XFRM_MSG_ALLOCSPI XFRM_MSG_ALLOCSPI
+   XFRM_MSG_ACQUIRE,
+#define XFRM_MSG_ACQUIRE XFRM_MSG_ACQUIRE
+   XFRM_MSG_EXPIRE,
+#define XFRM_MSG_EXPIRE XFRM_MSG_EXPIRE
+   XFRM_MSG_POLEXPIRE,
+#define XFRM_MSG_POLEXPIRE XFRM_MSG_POLEXPIRE
+
+   XFRM_MSG_NEWSA,
+#define XFRM_MSG_NEWSA XFRM_MSG_NEWSA
+   XFRM_MSG_UPDSA,
+#define XFRM_MSG_UPDSA XFRM_MSG_UPDSA
+   XFRM_MSG_DELSA,
+#define XFRM_MSG_DELSA XFRM_MSG_DELSA
+   XFRM_MSG_GETSA,
+#define XFRM_MSG_GETSA XFRM_MSG_GETSA
+
+   XFRM_MSG_NEWPOLICY,
+#define XFRM_MSG_NEWPOLICY XFRM_MSG_NEWPOLICY
+   XFRM_MSG_UPDPOLICY,
+#define XFRM_MSG_UPDPOLICY XFRM_MSG_UPDPOLICY
+   XFRM_MSG_DELPOLICY,
+#define XFRM_MSG_DELPOLICY XFRM_MSG_DELPOLICY
+   XFRM_MSG_GETPOLICY,
+#define XFRM_MSG_GETPOLICY XFRM_MSG_GETPOLICY
+
__XFRM_MSG_MAX
 };
 #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
@@ -221,7 +250,7 @@ enum {
 #define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)
 
 /*
- * Generic LSM security context for comunicating to user space
+ * Generic LSM security context for communicating to user space
  * NOTE: Same format as sadb_x_sec_ctx
  */
 struct xfrm_user_sec_ctx {
@@ -357,6 +386,22 @@ struct xfrmu_spdhthresh {
__u8 rbits;
 };
 
+/* Legacy structs are incompatible between 32-bit and 64-bit. */
+struct xfrm_usersa_info_legacy {
+   struct xfrm_selectorsel;
+   struct xfrm_id  id;
+   xfrm_address_t  saddr;
+   struct xfrm_lifetime_cfglft;
+   struct xfrm_lifetime_curcurlft;
+   struct xfrm

[PATCH 3/4] xfrm_user: Initial commit of xfrm_user_legacy.c

2017-01-20 Thread Kevin Cernekee
Several xfrm_* structs are incompatible between 32bit and 64bit builds:

xfrm_usersa_info 220 bytes on i386 -> 224 bytes on amd64
xfrm_userpolicy_info 164 -> 168
xfrm_userspi_info 228 -> 232, offset mismatch on min
xfrm_user_acquire 276 -> 280, offset mismatch on aalgos
xfrm_user_expire 224 -> 232, offset mismatch on hard
xfrm_user_polexpire 168 -> 176, offset mismatch on hard

Fork all of the functions that handle these structs into a new file so
that it is possible to support both legacy + new layouts.

This commit contains an exact copy of the necessary functions from
xfrm_user.c, for ease of reviewing.  The next commit will contain all
of the changes needed to make these functions handle legacy messages
correctly.

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 net/xfrm/Kconfig|   14 +
 net/xfrm/Makefile   |8 +-
 net/xfrm/xfrm_user_legacy.c | 1091 +++
 3 files changed, 1112 insertions(+), 1 deletion(-)
 create mode 100644 net/xfrm/xfrm_user_legacy.c

diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig
index bda1a13628a8..317dcc411345 100644
--- a/net/xfrm/Kconfig
+++ b/net/xfrm/Kconfig
@@ -20,6 +20,20 @@ config XFRM_USER
 
  If unsure, say Y.
 
+config XFRM_USER_LEGACY
+   tristate "Legacy transformation user configuration interface"
+   depends on XFRM_USER
+   default y
+   ---help---
+ The original Transformation(XFRM) netlink messages were not
+ compatible between 32-bit programs and 64-bit kernels, so they
+ have been deprecated.  Enable this option if you have existing
+ binaries that rely on the old format messages.  Disable this
+ option if you know that all users of the interface have been
+ built against recent kernel headers.
+
+ If unsure, say Y.
+
 config XFRM_SUB_POLICY
bool "Transformation sub policy support"
depends on XFRM
diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile
index c0e961983f17..6cf6f8da3dc8 100644
--- a/net/xfrm/Makefile
+++ b/net/xfrm/Makefile
@@ -7,5 +7,11 @@ obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
  xfrm_sysctl.o xfrm_replay.o
 obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
 obj-$(CONFIG_XFRM_ALGO) += xfrm_algo.o
-obj-$(CONFIG_XFRM_USER) += xfrm_user.o
+
+xfrm-user-objs := xfrm_user.o
+ifneq ($(CONFIG_XFRM_USER_LEGACY),)
+xfrm-user-objs += xfrm_user_legacy.o
+endif
+obj-$(CONFIG_XFRM_USER) += xfrm-user.o
+
 obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o
diff --git a/net/xfrm/xfrm_user_legacy.c b/net/xfrm/xfrm_user_legacy.c
new file mode 100644
index ..058accfefc83
--- /dev/null
+++ b/net/xfrm/xfrm_user_legacy.c
@@ -0,0 +1,1091 @@
+/* xfrm_user.c: User interface to configure xfrm engine.
+ *
+ * Copyright (C) 2002 David S. Miller (da...@redhat.com)
+ *
+ * Changes:
+ * Mitsuru KANDA @USAGI
+ * Kazunori MIYAZAWA @USAGI
+ * Kunihiro Ishiguro <kunih...@ipinfusion.com>
+ * IPv6 support
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "xfrm_user.h"
+
+static int xfrm_add_sa(struct sk_buff *skb, const struct nlmsghdr *nlh,
+  struct nlattr **attrs)
+{
+   struct net *net = sock_net(skb->sk);
+   const struct xfrm_usersa_info *p = nlmsg_data(nlh);
+   struct xfrm_state *x;
+   int err;
+   struct km_event c;
+
+   err = xfrm_verify_newsa_info(p, attrs);
+   if (err)
+   return err;
+
+   x = xfrm_state_construct(net, p, attrs, );
+   if (!x)
+   return err;
+
+   xfrm_state_hold(x);
+   if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
+   err = xfrm_state_add(x);
+   else
+   err = xfrm_state_update(x);
+
+   xfrm_audit_state_add(x, err ? 0 : 1, true);
+
+   if (err < 0) {
+   x->km.state = XFRM_STATE_DEAD;
+   __xfrm_state_put(x);
+   goto out;
+   }
+
+   c.seq = nlh->nlmsg_seq;
+   c.portid = nlh->nlmsg_pid;
+   c.event = nlh->nlmsg_type;
+
+   km_state_notify(x, );
+out:
+   xfrm_state_put(x);
+   return err;
+}
+
+static int xfrm_del_sa(struct sk_buff *skb, const struct nlmsghdr *nlh,
+  struct nlattr **attrs)
+{
+   struct net *net = sock_net(skb->sk);
+   struct xfrm_state *x;
+   int err = -ESRCH;
+   struct km_event c;
+   const struct xfrm_usersa_id *p = nlmsg_data(nlh);
+
+   x = xfrm_user_state_lookup(net, p, attrs, );
+   if (x == NULL)
+   return err;
+
+   if ((err = security_xfrm_state_delete(x)) != 0)
+   goto out;
+
+   if (xfrm_state_kern(x)) {
+   err = -EPERM;
+  

[PATCH 3/4] xfrm_user: Initial commit of xfrm_user_legacy.c

2017-01-20 Thread Kevin Cernekee
Several xfrm_* structs are incompatible between 32bit and 64bit builds:

xfrm_usersa_info 220 bytes on i386 -> 224 bytes on amd64
xfrm_userpolicy_info 164 -> 168
xfrm_userspi_info 228 -> 232, offset mismatch on min
xfrm_user_acquire 276 -> 280, offset mismatch on aalgos
xfrm_user_expire 224 -> 232, offset mismatch on hard
xfrm_user_polexpire 168 -> 176, offset mismatch on hard

Fork all of the functions that handle these structs into a new file so
that it is possible to support both legacy + new layouts.

This commit contains an exact copy of the necessary functions from
xfrm_user.c, for ease of reviewing.  The next commit will contain all
of the changes needed to make these functions handle legacy messages
correctly.

Signed-off-by: Kevin Cernekee 
---
 net/xfrm/Kconfig|   14 +
 net/xfrm/Makefile   |8 +-
 net/xfrm/xfrm_user_legacy.c | 1091 +++
 3 files changed, 1112 insertions(+), 1 deletion(-)
 create mode 100644 net/xfrm/xfrm_user_legacy.c

diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig
index bda1a13628a8..317dcc411345 100644
--- a/net/xfrm/Kconfig
+++ b/net/xfrm/Kconfig
@@ -20,6 +20,20 @@ config XFRM_USER
 
  If unsure, say Y.
 
+config XFRM_USER_LEGACY
+   tristate "Legacy transformation user configuration interface"
+   depends on XFRM_USER
+   default y
+   ---help---
+ The original Transformation(XFRM) netlink messages were not
+ compatible between 32-bit programs and 64-bit kernels, so they
+ have been deprecated.  Enable this option if you have existing
+ binaries that rely on the old format messages.  Disable this
+ option if you know that all users of the interface have been
+ built against recent kernel headers.
+
+ If unsure, say Y.
+
 config XFRM_SUB_POLICY
bool "Transformation sub policy support"
depends on XFRM
diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile
index c0e961983f17..6cf6f8da3dc8 100644
--- a/net/xfrm/Makefile
+++ b/net/xfrm/Makefile
@@ -7,5 +7,11 @@ obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
  xfrm_sysctl.o xfrm_replay.o
 obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
 obj-$(CONFIG_XFRM_ALGO) += xfrm_algo.o
-obj-$(CONFIG_XFRM_USER) += xfrm_user.o
+
+xfrm-user-objs := xfrm_user.o
+ifneq ($(CONFIG_XFRM_USER_LEGACY),)
+xfrm-user-objs += xfrm_user_legacy.o
+endif
+obj-$(CONFIG_XFRM_USER) += xfrm-user.o
+
 obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o
diff --git a/net/xfrm/xfrm_user_legacy.c b/net/xfrm/xfrm_user_legacy.c
new file mode 100644
index ..058accfefc83
--- /dev/null
+++ b/net/xfrm/xfrm_user_legacy.c
@@ -0,0 +1,1091 @@
+/* xfrm_user.c: User interface to configure xfrm engine.
+ *
+ * Copyright (C) 2002 David S. Miller (da...@redhat.com)
+ *
+ * Changes:
+ * Mitsuru KANDA @USAGI
+ * Kazunori MIYAZAWA @USAGI
+ * Kunihiro Ishiguro 
+ * IPv6 support
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "xfrm_user.h"
+
+static int xfrm_add_sa(struct sk_buff *skb, const struct nlmsghdr *nlh,
+  struct nlattr **attrs)
+{
+   struct net *net = sock_net(skb->sk);
+   const struct xfrm_usersa_info *p = nlmsg_data(nlh);
+   struct xfrm_state *x;
+   int err;
+   struct km_event c;
+
+   err = xfrm_verify_newsa_info(p, attrs);
+   if (err)
+   return err;
+
+   x = xfrm_state_construct(net, p, attrs, );
+   if (!x)
+   return err;
+
+   xfrm_state_hold(x);
+   if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
+   err = xfrm_state_add(x);
+   else
+   err = xfrm_state_update(x);
+
+   xfrm_audit_state_add(x, err ? 0 : 1, true);
+
+   if (err < 0) {
+   x->km.state = XFRM_STATE_DEAD;
+   __xfrm_state_put(x);
+   goto out;
+   }
+
+   c.seq = nlh->nlmsg_seq;
+   c.portid = nlh->nlmsg_pid;
+   c.event = nlh->nlmsg_type;
+
+   km_state_notify(x, );
+out:
+   xfrm_state_put(x);
+   return err;
+}
+
+static int xfrm_del_sa(struct sk_buff *skb, const struct nlmsghdr *nlh,
+  struct nlattr **attrs)
+{
+   struct net *net = sock_net(skb->sk);
+   struct xfrm_state *x;
+   int err = -ESRCH;
+   struct km_event c;
+   const struct xfrm_usersa_id *p = nlmsg_data(nlh);
+
+   x = xfrm_user_state_lookup(net, p, attrs, );
+   if (x == NULL)
+   return err;
+
+   if ((err = security_xfrm_state_delete(x)) != 0)
+   goto out;
+
+   if (xfrm_state_kern(x)) {
+   err = -EPERM;
+   goto out;
+   }
+
+   err = xfrm_state_delete(x);
+
+  

[RFC/PATCH 1/3] netfilter: ctnetlink: Fix regression in CTA_TIMEOUT processing

2017-01-16 Thread Kevin Cernekee
Commit b7bd1809e078 ("netfilter: nfnetlink_queue: get rid of
nfnetlink_queue_ct.c") introduced a new check on the return value
from the NFQA_CT parser (currently ctnetlink_glue_parse_ct()).
Prior to Linux 4.4, nfqnl_ct_parse() would process the NFQA_EXP
attribute even if there were errors in the NFQA_CT attribute.
After Linux 4.4, this is no longer true, so any error in the NFQA_CT
attribute will cause the kernel to silently fail to create an
expectation.

The new check is causing user conntrack helpers to fail.  If a user
program sends an NFQA_CT attribute containing a CTA_TIMEOUT attribute
before the connection is confirmed (i.e. before the initial
ACCEPT/DROP decision has been made), del_timer() in
ctnetlink_change_timeout() will fail, and all further processing will be
aborted.  The (simplified) calling sequence looks like:

nfnetlink_rcv_msg
  nfqnl_recv_verdict
nfqnl_ct_parse
  ctnetlink_glue_parse_ct
ctnetlink_change_timeout
  del_timer [ERROR]
nf_reinject
  __nf_conntrack_confirm

Fix this by adding a case to ctnetlink_change_timeout() to handle
unconfirmed connections.

Also, if a timeout of 0 is set for an unconfirmed connection, restore the
old behavior of ignoring it (rather than setting up a connection that
expires immediately).

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 net/netfilter/nf_conntrack_netlink.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index 9f5272968abb..43beb950df16 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1531,11 +1531,15 @@ ctnetlink_change_timeout(struct nf_conn *ct, const 
struct nlattr * const cda[])
 {
u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
 
-   if (!del_timer(>timeout))
-   return -ETIME;
+   if (nf_ct_is_confirmed(ct)) {
+   if (!del_timer(>timeout))
+   return -ETIME;
 
-   ct->timeout.expires = jiffies + timeout * HZ;
-   add_timer(>timeout);
+   ct->timeout.expires = jiffies + timeout * HZ;
+   add_timer(>timeout);
+   } else if (timeout != 0) {
+   ct->timeout.expires = timeout * HZ;
+   }
 
return 0;
 }
-- 
2.7.4



[RFC/PATCH 1/3] netfilter: ctnetlink: Fix regression in CTA_TIMEOUT processing

2017-01-16 Thread Kevin Cernekee
Commit b7bd1809e078 ("netfilter: nfnetlink_queue: get rid of
nfnetlink_queue_ct.c") introduced a new check on the return value
from the NFQA_CT parser (currently ctnetlink_glue_parse_ct()).
Prior to Linux 4.4, nfqnl_ct_parse() would process the NFQA_EXP
attribute even if there were errors in the NFQA_CT attribute.
After Linux 4.4, this is no longer true, so any error in the NFQA_CT
attribute will cause the kernel to silently fail to create an
expectation.

The new check is causing user conntrack helpers to fail.  If a user
program sends an NFQA_CT attribute containing a CTA_TIMEOUT attribute
before the connection is confirmed (i.e. before the initial
ACCEPT/DROP decision has been made), del_timer() in
ctnetlink_change_timeout() will fail, and all further processing will be
aborted.  The (simplified) calling sequence looks like:

nfnetlink_rcv_msg
  nfqnl_recv_verdict
nfqnl_ct_parse
  ctnetlink_glue_parse_ct
ctnetlink_change_timeout
  del_timer [ERROR]
nf_reinject
  __nf_conntrack_confirm

Fix this by adding a case to ctnetlink_change_timeout() to handle
unconfirmed connections.

Also, if a timeout of 0 is set for an unconfirmed connection, restore the
old behavior of ignoring it (rather than setting up a connection that
expires immediately).

Signed-off-by: Kevin Cernekee 
---
 net/netfilter/nf_conntrack_netlink.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index 9f5272968abb..43beb950df16 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1531,11 +1531,15 @@ ctnetlink_change_timeout(struct nf_conn *ct, const 
struct nlattr * const cda[])
 {
u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT]));
 
-   if (!del_timer(>timeout))
-   return -ETIME;
+   if (nf_ct_is_confirmed(ct)) {
+   if (!del_timer(>timeout))
+   return -ETIME;
 
-   ct->timeout.expires = jiffies + timeout * HZ;
-   add_timer(>timeout);
+   ct->timeout.expires = jiffies + timeout * HZ;
+   add_timer(>timeout);
+   } else if (timeout != 0) {
+   ct->timeout.expires = timeout * HZ;
+   }
 
return 0;
 }
-- 
2.7.4



[RFC/PATCH 2/3] netfilter: ctnetlink: Fix regression in CTA_STATUS processing

2017-01-16 Thread Kevin Cernekee
The libnetfilter_conntrack userland library always sets IPS_CONFIRMED
when building a CTA_STATUS attribute.  If this toggles the bit from
0->1, Linux 4.4+ will reject it and this will cause any NFQA_EXP
attribute in the packet to be ignored.  This breaks conntrackd's
userland helpers because they operate on unconfirmed connections.

Instead of returning -EBUSY if the user program asks to modify an
unchangeable bit, simply ignore the change.

Also, fix the logic so that user programs are allowed to clear
the bits that they are allowed to change.

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 include/uapi/linux/netfilter/nf_conntrack_common.h |  4 
 net/netfilter/nf_conntrack_netlink.c   | 10 --
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h 
b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 319f47128db8..846722d8e2a4 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -76,6 +76,10 @@ enum ip_conntrack_status {
IPS_DYING_BIT = 9,
IPS_DYING = (1 << IPS_DYING_BIT),
 
+   /* Bits that cannot be altered from userland. */
+   IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
+IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING),
+
/* Connection has fixed timeout. */
IPS_FIXED_TIMEOUT_BIT = 10,
IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index 43beb950df16..cc59f388928e 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1422,10 +1422,6 @@ ctnetlink_change_status(struct nf_conn *ct, const struct 
nlattr * const cda[])
unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
d = ct->status ^ status;
 
-   if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
-   /* unchangeable */
-   return -EBUSY;
-
if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
/* SEEN_REPLY bit can only be set */
return -EBUSY;
@@ -1436,8 +1432,10 @@ ctnetlink_change_status(struct nf_conn *ct, const struct 
nlattr * const cda[])
 
/* Be careful here, modifying NAT bits can screw up things,
 * so don't let users modify them directly if they don't pass
-* nf_nat_range. */
-   ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
+* nf_nat_range.  Also, disallow changing bits that indicate
+* which hash table owns the connection. */
+   ct->status = (status & ~IPS_UNCHANGEABLE_MASK) |
+(ct->status & IPS_UNCHANGEABLE_MASK);
return 0;
 }
 
-- 
2.7.4



[RFC/PATCH 3/3] netfilter: ctnetlink: Fix regression in CTA_HELP processing

2017-01-16 Thread Kevin Cernekee
If a user program specifies CTA_HELP but the argument matches the
current conntrack helper name, ignore it instead of generating an error.

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 net/netfilter/nf_conntrack_netlink.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index cc59f388928e..2912f582da65 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1472,14 +1472,19 @@ ctnetlink_change_helper(struct nf_conn *ct, const 
struct nlattr * const cda[])
struct nlattr *helpinfo = NULL;
int err;
 
-   /* don't change helper of sibling connections */
-   if (ct->master)
-   return -EBUSY;
-
err = ctnetlink_parse_help(cda[CTA_HELP], , );
if (err < 0)
return err;
 
+   /* don't change helper of sibling connections */
+   if (ct->master) {
+   if (help && help->helper &&
+   !strcmp(help->helper->name, helpname))
+   return 0;
+   else
+   return -EBUSY;
+   }
+
if (!strcmp(helpname, "")) {
if (help && help->helper) {
/* we had a helper before ... */
-- 
2.7.4



[RFC/PATCH 2/3] netfilter: ctnetlink: Fix regression in CTA_STATUS processing

2017-01-16 Thread Kevin Cernekee
The libnetfilter_conntrack userland library always sets IPS_CONFIRMED
when building a CTA_STATUS attribute.  If this toggles the bit from
0->1, Linux 4.4+ will reject it and this will cause any NFQA_EXP
attribute in the packet to be ignored.  This breaks conntrackd's
userland helpers because they operate on unconfirmed connections.

Instead of returning -EBUSY if the user program asks to modify an
unchangeable bit, simply ignore the change.

Also, fix the logic so that user programs are allowed to clear
the bits that they are allowed to change.

Signed-off-by: Kevin Cernekee 
---
 include/uapi/linux/netfilter/nf_conntrack_common.h |  4 
 net/netfilter/nf_conntrack_netlink.c   | 10 --
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h 
b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 319f47128db8..846722d8e2a4 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -76,6 +76,10 @@ enum ip_conntrack_status {
IPS_DYING_BIT = 9,
IPS_DYING = (1 << IPS_DYING_BIT),
 
+   /* Bits that cannot be altered from userland. */
+   IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
+IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING),
+
/* Connection has fixed timeout. */
IPS_FIXED_TIMEOUT_BIT = 10,
IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index 43beb950df16..cc59f388928e 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1422,10 +1422,6 @@ ctnetlink_change_status(struct nf_conn *ct, const struct 
nlattr * const cda[])
unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
d = ct->status ^ status;
 
-   if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING))
-   /* unchangeable */
-   return -EBUSY;
-
if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
/* SEEN_REPLY bit can only be set */
return -EBUSY;
@@ -1436,8 +1432,10 @@ ctnetlink_change_status(struct nf_conn *ct, const struct 
nlattr * const cda[])
 
/* Be careful here, modifying NAT bits can screw up things,
 * so don't let users modify them directly if they don't pass
-* nf_nat_range. */
-   ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
+* nf_nat_range.  Also, disallow changing bits that indicate
+* which hash table owns the connection. */
+   ct->status = (status & ~IPS_UNCHANGEABLE_MASK) |
+(ct->status & IPS_UNCHANGEABLE_MASK);
return 0;
 }
 
-- 
2.7.4



[RFC/PATCH 3/3] netfilter: ctnetlink: Fix regression in CTA_HELP processing

2017-01-16 Thread Kevin Cernekee
If a user program specifies CTA_HELP but the argument matches the
current conntrack helper name, ignore it instead of generating an error.

Signed-off-by: Kevin Cernekee 
---
 net/netfilter/nf_conntrack_netlink.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index cc59f388928e..2912f582da65 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1472,14 +1472,19 @@ ctnetlink_change_helper(struct nf_conn *ct, const 
struct nlattr * const cda[])
struct nlattr *helpinfo = NULL;
int err;
 
-   /* don't change helper of sibling connections */
-   if (ct->master)
-   return -EBUSY;
-
err = ctnetlink_parse_help(cda[CTA_HELP], , );
if (err < 0)
return err;
 
+   /* don't change helper of sibling connections */
+   if (ct->master) {
+   if (help && help->helper &&
+   !strcmp(help->helper->name, helpname))
+   return 0;
+   else
+   return -EBUSY;
+   }
+
if (!strcmp(helpname, "")) {
if (help && help->helper) {
/* we had a helper before ... */
-- 
2.7.4



[RFC/PATCH 0/3] Fix ctnetlink regressions

2017-01-16 Thread Kevin Cernekee
These patches address a problem I am seeing on Linux 4.4.  They do not
apply as-is to the master branch.  But I wanted to run them past the list
first to gather feedback on whether this is a reasonable approach.

I am using the user conntrack helpers from conntrackd on systems running
Linux 3.14, 3.18, and 4.4.  It was observed that conntrackd worked fine
on the 3.14/3.18 systems, but had no apparent effect on the 4.4 systems.
I tracked this down to a new check that was added in 4.4:

+   if (nfq_ct->parse(nfqa[NFQA_CT], ct) < 0)
+   return NULL;
+
+   if (nfqa[NFQA_EXP])
+   nfq_ct->attach_expect(nfqa[NFQA_EXP], ct,
+ NETLINK_CB(entry->skb).portid,
+ nlmsg_report(nlh));

Prior to 4.4, even if a netlink message failed the parse() checks, the
kernel would still run attach_expect() on it.  This masked a number of
failures.  With 4.4+, a sanity check failure on any attribute checked by
parse() will prevent the expectation from being created, which usually
breaks the conntrack helper.

In my testing I found that the sanity checks for CTA_TIMEOUT, CTA_STATUS,
and CTA_HELP were overly strict.  CTA_TIMEOUT may have been inadvertently
fixed in master (commit f330a7fdbe161), but I don't think the other two
are.  My proposal is to relax the checks so that existing user programs
do not break.

Another option is to simply ignore the parse() result, so that the
interface remains bug-compatible with old user code.


Kevin Cernekee (3):
  netfilter: ctnetlink: Fix regression in CTA_TIMEOUT processing
  netfilter: ctnetlink: Fix regression in CTA_STATUS processing
  netfilter: ctnetlink: Fix regression in CTA_HELP processing

 include/uapi/linux/netfilter/nf_conntrack_common.h |  4 +++
 net/netfilter/nf_conntrack_netlink.c   | 35 +-
 2 files changed, 25 insertions(+), 14 deletions(-)

-- 
2.7.4



[RFC/PATCH 0/3] Fix ctnetlink regressions

2017-01-16 Thread Kevin Cernekee
These patches address a problem I am seeing on Linux 4.4.  They do not
apply as-is to the master branch.  But I wanted to run them past the list
first to gather feedback on whether this is a reasonable approach.

I am using the user conntrack helpers from conntrackd on systems running
Linux 3.14, 3.18, and 4.4.  It was observed that conntrackd worked fine
on the 3.14/3.18 systems, but had no apparent effect on the 4.4 systems.
I tracked this down to a new check that was added in 4.4:

+   if (nfq_ct->parse(nfqa[NFQA_CT], ct) < 0)
+   return NULL;
+
+   if (nfqa[NFQA_EXP])
+   nfq_ct->attach_expect(nfqa[NFQA_EXP], ct,
+ NETLINK_CB(entry->skb).portid,
+ nlmsg_report(nlh));

Prior to 4.4, even if a netlink message failed the parse() checks, the
kernel would still run attach_expect() on it.  This masked a number of
failures.  With 4.4+, a sanity check failure on any attribute checked by
parse() will prevent the expectation from being created, which usually
breaks the conntrack helper.

In my testing I found that the sanity checks for CTA_TIMEOUT, CTA_STATUS,
and CTA_HELP were overly strict.  CTA_TIMEOUT may have been inadvertently
fixed in master (commit f330a7fdbe161), but I don't think the other two
are.  My proposal is to relax the checks so that existing user programs
do not break.

Another option is to simply ignore the parse() result, so that the
interface remains bug-compatible with old user code.


Kevin Cernekee (3):
  netfilter: ctnetlink: Fix regression in CTA_TIMEOUT processing
  netfilter: ctnetlink: Fix regression in CTA_STATUS processing
  netfilter: ctnetlink: Fix regression in CTA_HELP processing

 include/uapi/linux/netfilter/nf_conntrack_common.h |  4 +++
 net/netfilter/nf_conntrack_netlink.c   | 35 +-
 2 files changed, 25 insertions(+), 14 deletions(-)

-- 
2.7.4



[PATCH] printk: Make %pS print offsets into modules

2016-10-23 Thread Kevin Cernekee
If kallsyms cannot find a symbol for an address, entries like this will
appear in backtraces:

Call trace:
[] 0xffbffc1ecd7c
[] 0xffbffc1ef7f0
[] 0xffbffc1f0094

This isn't particularly useful for debugging because modules are not
loaded at fixed addresses.  Instead, print the offset from the module's
base, so that the offending location can be easily located in a
disassembly of the .ko file:

Call trace:
[] [mwifiex_pcie+0x37f4/0x9000]
[] [mwifiex_pcie+0x40ac/0x9000]
[] mwifiex_main_process+0xdc/0x6fc [mwifiex]

Signed-off-by: Kevin Cernekee <cerne...@chromium.org>
---
 include/linux/module.h | 16 
 kernel/kallsyms.c  | 19 ++-
 kernel/module.c| 23 +++
 3 files changed, 57 insertions(+), 1 deletion(-)


Tested on 4.4 only (so the core_layout / init_layout stuff is untested).


diff --git a/include/linux/module.h b/include/linux/module.h
index 0c3207d26ac0..611d1e71b7c8 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -616,6 +616,14 @@ const char *module_address_lookup(unsigned long addr,
unsigned long *offset,
char **modname,
char *namebuf);
+
+/* For kallsyms to ask which module, if any, contains addr.  On success,
+ * returns true and populates module_size, module_offset, and modname. */
+bool module_base_lookup(unsigned long addr,
+   unsigned long *module_size,
+   unsigned long *module_offset,
+   char **modname);
+
 int lookup_module_symbol_name(unsigned long addr, char *symname);
 int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, 
unsigned long *offset, char *modname, char *name);
 
@@ -698,6 +706,14 @@ static inline const char *module_address_lookup(unsigned 
long addr,
return NULL;
 }
 
+static inline bool module_base_lookup(unsigned long addr,
+ unsigned long *module_size,
+ unsigned long *module_offset,
+ char **modname)
+{
+   return false;
+}
+
 static inline int lookup_module_symbol_name(unsigned long addr, char *symname)
 {
return -ERANGE;
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index fafd1a3ef0da..43b114e6861f 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -387,8 +387,25 @@ static int __sprint_symbol(char *buffer, unsigned long 
address,
 
address += symbol_offset;
name = kallsyms_lookup(address, , , , buffer);
-   if (!name)
+   if (!name) {
+   /*
+* Fall back to [module_base+offset/size] if the actual
+* symbol name is unavailable.
+*/
+   if (module_base_lookup(address, , , )) {
+   if (add_offset) {
+   return snprintf(buffer, KSYM_SYMBOL_LEN,
+   "[%s+%#lx/%#lx]", modname,
+   address - offset -
+   symbol_offset,
+   size);
+   } else {
+   return snprintf(buffer, KSYM_SYMBOL_LEN,
+   "[%s]", modname);
+   }
+   }
return sprintf(buffer, "0x%lx", address - symbol_offset);
+   }
 
if (name != buffer)
strcpy(buffer, name);
diff --git a/kernel/module.c b/kernel/module.c
index f57dd63186e6..5e09f568c601 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3899,6 +3899,29 @@ const char *module_address_lookup(unsigned long addr,
return ret;
 }
 
+bool module_base_lookup(unsigned long addr,
+   unsigned long *module_size,
+   unsigned long *module_offset,
+   char **modname)
+{
+   struct module *mod;
+
+   preempt_disable();
+
+   mod = __module_address(addr);
+   if (!mod) {
+   preempt_enable();
+   return false;
+   }
+
+   *modname = mod->name;
+   *module_offset = (unsigned long)mod->core_layout.base;
+   *module_size = mod->init_layout.size + mod->core_layout.size;
+
+   preempt_enable();
+   return true;
+}
+
 int lookup_module_symbol_name(unsigned long addr, char *symname)
 {
struct module *mod;
-- 
2.8.0.rc3.226.g39d4020



[PATCH] printk: Make %pS print offsets into modules

2016-10-23 Thread Kevin Cernekee
If kallsyms cannot find a symbol for an address, entries like this will
appear in backtraces:

Call trace:
[] 0xffbffc1ecd7c
[] 0xffbffc1ef7f0
[] 0xffbffc1f0094

This isn't particularly useful for debugging because modules are not
loaded at fixed addresses.  Instead, print the offset from the module's
base, so that the offending location can be easily located in a
disassembly of the .ko file:

Call trace:
[] [mwifiex_pcie+0x37f4/0x9000]
[] [mwifiex_pcie+0x40ac/0x9000]
[] mwifiex_main_process+0xdc/0x6fc [mwifiex]

Signed-off-by: Kevin Cernekee 
---
 include/linux/module.h | 16 
 kernel/kallsyms.c  | 19 ++-
 kernel/module.c| 23 +++
 3 files changed, 57 insertions(+), 1 deletion(-)


Tested on 4.4 only (so the core_layout / init_layout stuff is untested).


diff --git a/include/linux/module.h b/include/linux/module.h
index 0c3207d26ac0..611d1e71b7c8 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -616,6 +616,14 @@ const char *module_address_lookup(unsigned long addr,
unsigned long *offset,
char **modname,
char *namebuf);
+
+/* For kallsyms to ask which module, if any, contains addr.  On success,
+ * returns true and populates module_size, module_offset, and modname. */
+bool module_base_lookup(unsigned long addr,
+   unsigned long *module_size,
+   unsigned long *module_offset,
+   char **modname);
+
 int lookup_module_symbol_name(unsigned long addr, char *symname);
 int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, 
unsigned long *offset, char *modname, char *name);
 
@@ -698,6 +706,14 @@ static inline const char *module_address_lookup(unsigned 
long addr,
return NULL;
 }
 
+static inline bool module_base_lookup(unsigned long addr,
+ unsigned long *module_size,
+ unsigned long *module_offset,
+ char **modname)
+{
+   return false;
+}
+
 static inline int lookup_module_symbol_name(unsigned long addr, char *symname)
 {
return -ERANGE;
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index fafd1a3ef0da..43b114e6861f 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -387,8 +387,25 @@ static int __sprint_symbol(char *buffer, unsigned long 
address,
 
address += symbol_offset;
name = kallsyms_lookup(address, , , , buffer);
-   if (!name)
+   if (!name) {
+   /*
+* Fall back to [module_base+offset/size] if the actual
+* symbol name is unavailable.
+*/
+   if (module_base_lookup(address, , , )) {
+   if (add_offset) {
+   return snprintf(buffer, KSYM_SYMBOL_LEN,
+   "[%s+%#lx/%#lx]", modname,
+   address - offset -
+   symbol_offset,
+   size);
+   } else {
+   return snprintf(buffer, KSYM_SYMBOL_LEN,
+   "[%s]", modname);
+   }
+   }
return sprintf(buffer, "0x%lx", address - symbol_offset);
+   }
 
if (name != buffer)
strcpy(buffer, name);
diff --git a/kernel/module.c b/kernel/module.c
index f57dd63186e6..5e09f568c601 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3899,6 +3899,29 @@ const char *module_address_lookup(unsigned long addr,
return ret;
 }
 
+bool module_base_lookup(unsigned long addr,
+   unsigned long *module_size,
+   unsigned long *module_offset,
+   char **modname)
+{
+   struct module *mod;
+
+   preempt_disable();
+
+   mod = __module_address(addr);
+   if (!mod) {
+   preempt_enable();
+   return false;
+   }
+
+   *modname = mod->name;
+   *module_offset = (unsigned long)mod->core_layout.base;
+   *module_size = mod->init_layout.size + mod->core_layout.size;
+
+   preempt_enable();
+   return true;
+}
+
 int lookup_module_symbol_name(unsigned long addr, char *symname)
 {
struct module *mod;
-- 
2.8.0.rc3.226.g39d4020



Re: [PATCH] MIPS: Flush cache after DMA_FROM_DEVICE for agressively speculative CPUs

2015-05-13 Thread Kevin Cernekee
On Wed, May 13, 2015 at 6:49 PM, Leonid Yegoshin
 wrote:
> Some MIPS CPUs have an aggressive speculative load and may erroneuosly load
> some cache line in the middle of DMA transaction. CPU discards result but 
> cache
> doesn't. If DMA happens from device then additional cache invalidation is 
> needed
> on that CPU's after DMA.
>
> Found in test.
>
> Signed-off-by: Leonid Yegoshin 
> ---
>  arch/mips/mm/dma-default.c |   10 ++
>  1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
> index 609d1241b0c4..ccf49ecfbf8c 100644
> --- a/arch/mips/mm/dma-default.c
> +++ b/arch/mips/mm/dma-default.c
> @@ -67,11 +67,13 @@ static inline struct page *dma_addr_to_page(struct device 
> *dev,
>   * systems and only the R1 and R12000 are used in such systems, the
>   * SGI IP28 Indigo² rsp. SGI IP32 aka O2.
>   */
> -static inline int cpu_needs_post_dma_flush(struct device *dev)
> +static inline int cpu_needs_post_dma_flush(struct device *dev,
> +  enum dma_data_direction direction)
>  {
> return !plat_device_is_coherent(dev) &&
>(boot_cpu_type() == CPU_R1 ||
> boot_cpu_type() == CPU_R12000 ||
> +   (cpu_has_maar && (direction != DMA_TO_DEVICE)) ||
> boot_cpu_type() == CPU_BMIPS5000);

Can all of these CPUs safely skip the post_dma_flush on DMA_TO_DEVICE
(not just maar)?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] MIPS: Flush cache after DMA_FROM_DEVICE for agressively speculative CPUs

2015-05-13 Thread Kevin Cernekee
On Wed, May 13, 2015 at 6:49 PM, Leonid Yegoshin
leonid.yegos...@imgtec.com wrote:
 Some MIPS CPUs have an aggressive speculative load and may erroneuosly load
 some cache line in the middle of DMA transaction. CPU discards result but 
 cache
 doesn't. If DMA happens from device then additional cache invalidation is 
 needed
 on that CPU's after DMA.

 Found in test.

 Signed-off-by: Leonid Yegoshin leonid.yegos...@imgtec.com
 ---
  arch/mips/mm/dma-default.c |   10 ++
  1 file changed, 6 insertions(+), 4 deletions(-)

 diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
 index 609d1241b0c4..ccf49ecfbf8c 100644
 --- a/arch/mips/mm/dma-default.c
 +++ b/arch/mips/mm/dma-default.c
 @@ -67,11 +67,13 @@ static inline struct page *dma_addr_to_page(struct device 
 *dev,
   * systems and only the R1 and R12000 are used in such systems, the
   * SGI IP28 Indigo² rsp. SGI IP32 aka O2.
   */
 -static inline int cpu_needs_post_dma_flush(struct device *dev)
 +static inline int cpu_needs_post_dma_flush(struct device *dev,
 +  enum dma_data_direction direction)
  {
 return !plat_device_is_coherent(dev) 
(boot_cpu_type() == CPU_R1 ||
 boot_cpu_type() == CPU_R12000 ||
 +   (cpu_has_maar  (direction != DMA_TO_DEVICE)) ||
 boot_cpu_type() == CPU_BMIPS5000);

Can all of these CPUs safely skip the post_dma_flush on DMA_TO_DEVICE
(not just maar)?
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V4 3/5] ASoC: tas571x: Add DT binding document

2015-05-05 Thread Kevin Cernekee
On Tue, May 5, 2015 at 3:32 PM, Mark Brown  wrote:
> On Tue, May 05, 2015 at 03:14:15PM -0700, Kevin Cernekee wrote:
>> Document the bindings for the soon-to-be-added tas571x driver.
>
> If this is different to the already applied patches send incremental
> updates.  If this is the same as the version of the driver that is
> already applied please don't resend already applied patches.

OK - I sent an incremental update for the one thing that changed in
the tas571x driver from V3 to V4.

Note that the regcache changes were intentionally ordered before the
tas571x commits, because the regcache changes are needed for the new
driver to work correctly.  In the for-next branch I see the tas571x
commits, but not the regcache changes.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] ASoC: tas571x: Eliminate redundant dev->of_node NULL check

2015-05-05 Thread Kevin Cernekee
of_match_device() checks if dev->of_node is NULL, so we don't need to do
it again in the probe function.

Signed-off-by: Kevin Cernekee 
---


This applies to the broonie/sound.git for-next branch.


 sound/soc/codecs/tas571x.c | 13 -
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
index b187ea53a7f9..85bcc374c8e8 100644
--- a/sound/soc/codecs/tas571x.c
+++ b/sound/soc/codecs/tas571x.c
@@ -377,6 +377,7 @@ static int tas571x_i2c_probe(struct i2c_client *client,
 {
struct tas571x_private *priv;
struct device *dev = >dev;
+   const struct of_device_id *of_id;
int i, ret;
 
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -384,18 +385,12 @@ static int tas571x_i2c_probe(struct i2c_client *client,
return -ENOMEM;
i2c_set_clientdata(client, priv);
 
-   if (dev->of_node) {
-   const struct of_device_id *of_id;
-
-   of_id = of_match_device(tas571x_of_match, dev);
-   if (of_id)
-   priv->chip = of_id->data;
-   }
-
-   if (!priv->chip) {
+   of_id = of_match_device(tas571x_of_match, dev);
+   if (!of_id) {
dev_err(dev, "Unknown device type\n");
return -EINVAL;
}
+   priv->chip = of_id->data;
 
priv->mclk = devm_clk_get(dev, "mclk");
if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) {
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V4 3/5] ASoC: tas571x: Add DT binding document

2015-05-05 Thread Kevin Cernekee
Document the bindings for the soon-to-be-added tas571x driver.

Signed-off-by: Kevin Cernekee 
---
 .../devicetree/bindings/sound/tas571x.txt  | 41 ++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt

diff --git a/Documentation/devicetree/bindings/sound/tas571x.txt 
b/Documentation/devicetree/bindings/sound/tas571x.txt
new file mode 100644
index ..0ac31d8d5ac4
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tas571x.txt
@@ -0,0 +1,41 @@
+Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers
+
+The codec is controlled through an I2C interface.  It also has two other
+signals that can be wired up to GPIOs: reset (strongly recommended), and
+powerdown (optional).
+
+Required properties:
+
+- compatible: "ti,tas5711", "ti,tas5717", or "ti,tas5719"
+- reg: The I2C address of the device
+- #sound-dai-cells: must be equal to 0
+
+Optional properties:
+
+- reset-gpios: GPIO specifier for the TAS571x's active low reset line
+- pdn-gpios: GPIO specifier for the TAS571x's active low powerdown line
+- clocks: clock phandle for the MCLK input
+- clock-names: should be "mclk"
+- AVDD-supply: regulator phandle for the AVDD supply (all chips)
+- DVDD-supply: regulator phandle for the DVDD supply (all chips)
+- HPVDD-supply: regulator phandle for the HPVDD supply (5717/5719)
+- PVDD_AB-supply: regulator phandle for the PVDD_AB supply (5717/5719)
+- PVDD_CD-supply: regulator phandle for the PVDD_CD supply (5717/5719)
+- PVDD_A-supply: regulator phandle for the PVDD_A supply (5711)
+- PVDD_B-supply: regulator phandle for the PVDD_B supply (5711)
+- PVDD_C-supply: regulator phandle for the PVDD_C supply (5711)
+- PVDD_D-supply: regulator phandle for the PVDD_D supply (5711)
+
+Example:
+
+   tas5717: audio-codec@2a {
+   compatible = "ti,tas5717";
+   reg = <0x2a>;
+   #sound-dai-cells = <0>;
+
+   reset-gpios = < 1 GPIO_ACTIVE_LOW>;
+   pdn-gpios = < 2 GPIO_ACTIVE_LOW>;
+
+   clocks = <_core CLK_I2S>;
+   clock-names = "mclk";
+   };
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V4 2/5] regmap: Use regcache_mark_dirty() to indicate power loss or reset

2015-05-05 Thread Kevin Cernekee
Existing regmap users call regcache_mark_dirty() as part of the
suspend/resume sequence, to tell regcache that non-default values need to
be resynced post-resume.  Add an internal "no_sync_defaults" regmap flag
to remember this state, so that regcache_sync() can differentiate between
these two cases:

1) HW was reset, so any cache values that match map->reg_defaults can be
safely skipped.  On some chips there are a lot of registers in the
reg_defaults list, so this optimization speeds things up quite a bit.

2) HW was not reset (maybe it was just clock-gated), so if we cached
any writes, they should be sent to the hardware regardless of whether
they match the HW default.  Currently this will write out all values in
the regcache, since we don't maintain per-register dirty bits.

Suggested-by: Mark Brown 
Signed-off-by: Kevin Cernekee 
---
 drivers/base/regmap/internal.h |  3 +++
 drivers/base/regmap/regcache.c | 19 +++
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index a13587b5c2be..b2b2849fc6d3 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -131,7 +131,10 @@ struct regmap {
struct reg_default *reg_defaults;
const void *reg_defaults_raw;
void *cache;
+   /* if set, the cache contains newer data than the HW */
u32 cache_dirty;
+   /* if set, the HW registers are known to match map->reg_defaults */
+   bool no_sync_defaults;
 
struct reg_default *patch;
int patch_regs;
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index c58493eaf050..b9862d741a56 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -254,6 +254,10 @@ static bool regcache_reg_needs_sync(struct regmap *map, 
unsigned int reg,
 {
int ret;
 
+   /* If we don't know the chip just got reset, then sync everything. */
+   if (!map->no_sync_defaults)
+   return true;
+
/* Is this the hardware default?  If so skip. */
ret = regcache_lookup_reg(map, reg);
if (ret >= 0 && val == map->reg_defaults[ret].def)
@@ -352,6 +356,7 @@ out:
/* Restore the bypass state */
map->async = false;
map->cache_bypass = bypass;
+   map->no_sync_defaults = false;
map->unlock(map->lock_arg);
 
regmap_async_complete(map);
@@ -407,6 +412,7 @@ out:
/* Restore the bypass state */
map->cache_bypass = bypass;
map->async = false;
+   map->no_sync_defaults = false;
map->unlock(map->lock_arg);
 
regmap_async_complete(map);
@@ -471,18 +477,23 @@ void regcache_cache_only(struct regmap *map, bool enable)
 EXPORT_SYMBOL_GPL(regcache_cache_only);
 
 /**
- * regcache_mark_dirty: Mark the register cache as dirty
+ * regcache_mark_dirty: Indicate that HW registers were reset to default values
  *
  * @map: map to mark
  *
- * Mark the register cache as dirty, for example due to the device
- * having been powered down for suspend.  If the cache is not marked
- * as dirty then the cache sync will be suppressed.
+ * Inform regcache that the device has been powered down or reset, so that
+ * on resume, regcache_sync() knows to write out all non-default values
+ * stored in the cache.
+ *
+ * If this function is not called, regcache_sync() will assume that
+ * the hardware state still matches the cache state, modulo any writes that
+ * happened when cache_only was true.
  */
 void regcache_mark_dirty(struct regmap *map)
 {
map->lock(map->lock_arg);
map->cache_dirty = true;
+   map->no_sync_defaults = true;
map->unlock(map->lock_arg);
 }
 EXPORT_SYMBOL_GPL(regcache_mark_dirty);
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V4 1/5] regmap: Add a helper function for regcache sync test

2015-05-05 Thread Kevin Cernekee
We're going to add another "does this register need syncing?" check, so
rather than repeating it in three places, we'll separate all of the
relevant logic into a helper function.

Signed-off-by: Kevin Cernekee 
---
 drivers/base/regmap/regcache.c | 26 +++---
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 7eb7b3b98794..c58493eaf050 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -249,6 +249,18 @@ int regcache_write(struct regmap *map,
return 0;
 }
 
+static bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg,
+   unsigned int val)
+{
+   int ret;
+
+   /* Is this the hardware default?  If so skip. */
+   ret = regcache_lookup_reg(map, reg);
+   if (ret >= 0 && val == map->reg_defaults[ret].def)
+   return false;
+   return true;
+}
+
 static int regcache_default_sync(struct regmap *map, unsigned int min,
 unsigned int max)
 {
@@ -266,9 +278,7 @@ static int regcache_default_sync(struct regmap *map, 
unsigned int min,
if (ret)
return ret;
 
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, reg);
-   if (ret >= 0 && val == map->reg_defaults[ret].def)
+   if (!regcache_reg_needs_sync(map, reg, val))
continue;
 
map->cache_bypass = 1;
@@ -613,10 +623,7 @@ static int regcache_sync_block_single(struct regmap *map, 
void *block,
continue;
 
val = regcache_get_val(map, block, i);
-
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, regtmp);
-   if (ret >= 0 && val == map->reg_defaults[ret].def)
+   if (!regcache_reg_needs_sync(map, regtmp, val))
continue;
 
map->cache_bypass = 1;
@@ -688,10 +695,7 @@ static int regcache_sync_block_raw(struct regmap *map, 
void *block,
}
 
val = regcache_get_val(map, block, i);
-
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, regtmp);
-   if (ret >= 0 && val == map->reg_defaults[ret].def) {
+   if (!regcache_reg_needs_sync(map, regtmp, val)) {
ret = regcache_sync_block_raw_flush(map, ,
base, regtmp);
if (ret != 0)
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V4 4/5] ASoC: tas571x: New driver for TI TAS571x power amplifiers

2015-05-05 Thread Kevin Cernekee
Introduce a new codec driver for the Texas Instruments
TAS5711/TAS5717/TAS5719 power amplifier chips.  These chips are typically
used to take an I2S digital audio input and drive 10-20W into a pair of
speakers.

Signed-off-by: Kevin Cernekee 
---
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 515 +
 sound/soc/codecs/tas571x.h |  33 +++
 4 files changed, 555 insertions(+)
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 061c46587628..befff910d71a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TAS2552 if I2C
select SND_SOC_TAS5086 if I2C
+   select SND_SOC_TAS571X if I2C
select SND_SOC_TFA9879 if I2C
select SND_SOC_TLV320AIC23_I2C if I2C
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
@@ -611,6 +612,10 @@ config SND_SOC_TAS5086
tristate "Texas Instruments TAS5086 speaker amplifier"
depends on I2C
 
+config SND_SOC_TAS571X
+   tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers"
+   depends on I2C
+
 config SND_SOC_TFA9879
tristate "NXP Semiconductors TFA9879 amplifier"
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index abe2d7edf65c..3dcf5ac85e89 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -106,6 +106,7 @@ snd-soc-sta350-objs := sta350.o
 snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tas5086-objs := tas5086.o
+snd-soc-tas571x-objs := tas571x.o
 snd-soc-tfa9879-objs := tfa9879.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
@@ -288,6 +289,7 @@ obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TAS2552)  += snd-soc-tas2552.o
 obj-$(CONFIG_SND_SOC_TAS5086)  += snd-soc-tas5086.o
+obj-$(CONFIG_SND_SOC_TAS571X)  += snd-soc-tas571x.o
 obj-$(CONFIG_SND_SOC_TFA9879)  += snd-soc-tfa9879.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)  += snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C)  += snd-soc-tlv320aic23-i2c.o
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
new file mode 100644
index ..e724cc463e78
--- /dev/null
+++ b/sound/soc/codecs/tas571x.c
@@ -0,0 +1,515 @@
+/*
+ * TAS571x amplifier audio driver
+ *
+ * Copyright (C) 2015 Google, Inc.
+ * Copyright (c) 2013 Daniel Mack 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "tas571x.h"
+
+#define TAS571X_MAX_SUPPLIES   6
+
+struct tas571x_chip {
+   const char  *const *supply_names;
+   int num_supply_names;
+   const struct snd_kcontrol_new   *controls;
+   int num_controls;
+   const struct regmap_config  *regmap_config;
+   int vol_reg_size;
+};
+
+struct tas571x_private {
+   const struct tas571x_chip   *chip;
+   struct regmap   *regmap;
+   struct regulator_bulk_data  supplies[TAS571X_MAX_SUPPLIES];
+   struct clk  *mclk;
+   unsigned intformat;
+   struct gpio_desc*reset_gpio;
+   struct gpio_desc*pdn_gpio;
+   struct snd_soc_codec_driver codec_driver;
+};
+
+static int tas571x_register_size(struct tas571x_private *priv, unsigned int 
reg)
+{
+   switch (reg) {
+   case TAS571X_MVOL_REG:
+   case TAS571X_CH1_VOL_REG:
+   case TAS571X_CH2_VOL_REG:
+   return priv->chip->vol_reg_size;
+   default:
+   return 1;
+   }
+}
+
+static int tas571x_reg_write(void *context, unsigned int reg,
+unsigned int value)
+{
+   struct i2c_client *client = context;
+   struct tas571x_private *priv = i2c_get_clientdata(client);
+   unsigned int i, size;
+   uint8_t buf[5];
+   int ret;
+
+   size = tas571x_register_size(priv, reg);
+   buf[0] = reg;
+
+   for (i = size; i >= 1; --i) {
+   buf[i] = value;
+   value >>= 8;
+   }
+
+   ret = i2c_master_send(client, buf, size + 1);
+   if (ret == size + 1)
+   return 

[PATCH V4 5/5] MAINTAINERS: Add entry for tas571x ASoC codec driver

2015-05-05 Thread Kevin Cernekee
Add self as maintainer for the new driver.

Signed-off-by: Kevin Cernekee 
---
 MAINTAINERS | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ea0001760035..15153fc37cc4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9878,6 +9878,12 @@ L:   net...@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/ti/netcp*
 
+TI TAS571X FAMILY ASoC CODEC DRIVER
+M: Kevin Cernekee 
+L: alsa-de...@alsa-project.org (moderated for non-subscribers)
+S: Odd Fixes
+F: sound/soc/codecs/tas571x*
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M: Peter Ujfalusi 
 L: alsa-de...@alsa-project.org (moderated for non-subscribers)
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V4 0/5] tas571x amplifier driver

2015-05-05 Thread Kevin Cernekee
V3->V4:

Eliminate unnecessary dev->of_node NULL check.

Move the "should I sync this register?" test into a common helper function.

Clear map->no_sync_defaults at the end of the regcache_sync functions.


Kevin Cernekee (5):
  regmap: Add a helper function for regcache sync test
  regmap: Use regcache_mark_dirty() to indicate power loss or reset
  ASoC: tas571x: Add DT binding document
  ASoC: tas571x: New driver for TI TAS571x power amplifiers
  MAINTAINERS: Add entry for tas571x ASoC codec driver

 .../devicetree/bindings/sound/tas571x.txt  |  41 ++
 MAINTAINERS|   6 +
 drivers/base/regmap/internal.h |   3 +
 drivers/base/regmap/regcache.c |  45 +-
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 515 +
 sound/soc/codecs/tas571x.h |  33 ++
 8 files changed, 635 insertions(+), 15 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/6] MAINTAINERS: Remove section BROADCOM BCM33XX MIPS ARCHITECTURE

2015-05-05 Thread Kevin Cernekee
On Tue, May 5, 2015 at 9:32 AM, Joe Perches  wrote:
> commit 5f2d44591fb3 ("MIPS: bcm3384: Rename "bcm3384" target to "bmips"")
> renamed the files and integrated them into an existing section.
>
> Remove the section.
>
> Signed-off-by: Joe Perches 
> cc: Kevin Cernekee 
> ---
>  MAINTAINERS | 8 
>  1 file changed, 8 deletions(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index bbfb324..f2fd5c7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2141,14 +2141,6 @@ T:   git 
> git://git.kernel.org/pub/scm/linux/kernel/git/rpi/linux-rpi.git
>  S: Maintained
>  N: bcm2835
>
> -BROADCOM BCM33XX MIPS ARCHITECTURE
> -M: Kevin Cernekee 
> -L: linux-m...@linux-mips.org
> -S: Maintained
> -F: arch/mips/bcm3384/*
> -F: arch/mips/include/asm/mach-bcm3384/*
> -F: arch/mips/kernel/*bmips*
> -
>  BROADCOM BCM5301X ARM ARCHITECTURE
>  M: Hauke Mehrtens 
>  L: linux-arm-ker...@lists.infradead.org
> --
> 2.1.4
>

Acked-by: Kevin Cernekee 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V4 3/5] ASoC: tas571x: Add DT binding document

2015-05-05 Thread Kevin Cernekee
On Tue, May 5, 2015 at 3:32 PM, Mark Brown broo...@kernel.org wrote:
 On Tue, May 05, 2015 at 03:14:15PM -0700, Kevin Cernekee wrote:
 Document the bindings for the soon-to-be-added tas571x driver.

 If this is different to the already applied patches send incremental
 updates.  If this is the same as the version of the driver that is
 already applied please don't resend already applied patches.

OK - I sent an incremental update for the one thing that changed in
the tas571x driver from V3 to V4.

Note that the regcache changes were intentionally ordered before the
tas571x commits, because the regcache changes are needed for the new
driver to work correctly.  In the for-next branch I see the tas571x
commits, but not the regcache changes.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] ASoC: tas571x: Eliminate redundant dev-of_node NULL check

2015-05-05 Thread Kevin Cernekee
of_match_device() checks if dev-of_node is NULL, so we don't need to do
it again in the probe function.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---


This applies to the broonie/sound.git for-next branch.


 sound/soc/codecs/tas571x.c | 13 -
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
index b187ea53a7f9..85bcc374c8e8 100644
--- a/sound/soc/codecs/tas571x.c
+++ b/sound/soc/codecs/tas571x.c
@@ -377,6 +377,7 @@ static int tas571x_i2c_probe(struct i2c_client *client,
 {
struct tas571x_private *priv;
struct device *dev = client-dev;
+   const struct of_device_id *of_id;
int i, ret;
 
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -384,18 +385,12 @@ static int tas571x_i2c_probe(struct i2c_client *client,
return -ENOMEM;
i2c_set_clientdata(client, priv);
 
-   if (dev-of_node) {
-   const struct of_device_id *of_id;
-
-   of_id = of_match_device(tas571x_of_match, dev);
-   if (of_id)
-   priv-chip = of_id-data;
-   }
-
-   if (!priv-chip) {
+   of_id = of_match_device(tas571x_of_match, dev);
+   if (!of_id) {
dev_err(dev, Unknown device type\n);
return -EINVAL;
}
+   priv-chip = of_id-data;
 
priv-mclk = devm_clk_get(dev, mclk);
if (IS_ERR(priv-mclk)  PTR_ERR(priv-mclk) != -ENOENT) {
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V4 4/5] ASoC: tas571x: New driver for TI TAS571x power amplifiers

2015-05-05 Thread Kevin Cernekee
Introduce a new codec driver for the Texas Instruments
TAS5711/TAS5717/TAS5719 power amplifier chips.  These chips are typically
used to take an I2S digital audio input and drive 10-20W into a pair of
speakers.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 515 +
 sound/soc/codecs/tas571x.h |  33 +++
 4 files changed, 555 insertions(+)
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 061c46587628..befff910d71a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TAS2552 if I2C
select SND_SOC_TAS5086 if I2C
+   select SND_SOC_TAS571X if I2C
select SND_SOC_TFA9879 if I2C
select SND_SOC_TLV320AIC23_I2C if I2C
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
@@ -611,6 +612,10 @@ config SND_SOC_TAS5086
tristate Texas Instruments TAS5086 speaker amplifier
depends on I2C
 
+config SND_SOC_TAS571X
+   tristate Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers
+   depends on I2C
+
 config SND_SOC_TFA9879
tristate NXP Semiconductors TFA9879 amplifier
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index abe2d7edf65c..3dcf5ac85e89 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -106,6 +106,7 @@ snd-soc-sta350-objs := sta350.o
 snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tas5086-objs := tas5086.o
+snd-soc-tas571x-objs := tas571x.o
 snd-soc-tfa9879-objs := tfa9879.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
@@ -288,6 +289,7 @@ obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TAS2552)  += snd-soc-tas2552.o
 obj-$(CONFIG_SND_SOC_TAS5086)  += snd-soc-tas5086.o
+obj-$(CONFIG_SND_SOC_TAS571X)  += snd-soc-tas571x.o
 obj-$(CONFIG_SND_SOC_TFA9879)  += snd-soc-tfa9879.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)  += snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C)  += snd-soc-tlv320aic23-i2c.o
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
new file mode 100644
index ..e724cc463e78
--- /dev/null
+++ b/sound/soc/codecs/tas571x.c
@@ -0,0 +1,515 @@
+/*
+ * TAS571x amplifier audio driver
+ *
+ * Copyright (C) 2015 Google, Inc.
+ * Copyright (c) 2013 Daniel Mack zon...@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include linux/clk.h
+#include linux/delay.h
+#include linux/device.h
+#include linux/gpio/consumer.h
+#include linux/i2c.h
+#include linux/init.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/of_device.h
+#include linux/regmap.h
+#include linux/regulator/consumer.h
+#include linux/stddef.h
+#include sound/pcm_params.h
+#include sound/soc.h
+#include sound/tlv.h
+
+#include tas571x.h
+
+#define TAS571X_MAX_SUPPLIES   6
+
+struct tas571x_chip {
+   const char  *const *supply_names;
+   int num_supply_names;
+   const struct snd_kcontrol_new   *controls;
+   int num_controls;
+   const struct regmap_config  *regmap_config;
+   int vol_reg_size;
+};
+
+struct tas571x_private {
+   const struct tas571x_chip   *chip;
+   struct regmap   *regmap;
+   struct regulator_bulk_data  supplies[TAS571X_MAX_SUPPLIES];
+   struct clk  *mclk;
+   unsigned intformat;
+   struct gpio_desc*reset_gpio;
+   struct gpio_desc*pdn_gpio;
+   struct snd_soc_codec_driver codec_driver;
+};
+
+static int tas571x_register_size(struct tas571x_private *priv, unsigned int 
reg)
+{
+   switch (reg) {
+   case TAS571X_MVOL_REG:
+   case TAS571X_CH1_VOL_REG:
+   case TAS571X_CH2_VOL_REG:
+   return priv-chip-vol_reg_size;
+   default:
+   return 1;
+   }
+}
+
+static int tas571x_reg_write(void *context, unsigned int reg,
+unsigned int value)
+{
+   struct i2c_client *client = context;
+   struct tas571x_private *priv = i2c_get_clientdata(client);
+   unsigned int i, size;
+   uint8_t buf[5];
+   int ret;
+
+   size = tas571x_register_size(priv, reg);
+   buf[0] = reg;
+
+   for (i = size; i = 1

[PATCH V4 0/5] tas571x amplifier driver

2015-05-05 Thread Kevin Cernekee
V3-V4:

Eliminate unnecessary dev-of_node NULL check.

Move the should I sync this register? test into a common helper function.

Clear map-no_sync_defaults at the end of the regcache_sync functions.


Kevin Cernekee (5):
  regmap: Add a helper function for regcache sync test
  regmap: Use regcache_mark_dirty() to indicate power loss or reset
  ASoC: tas571x: Add DT binding document
  ASoC: tas571x: New driver for TI TAS571x power amplifiers
  MAINTAINERS: Add entry for tas571x ASoC codec driver

 .../devicetree/bindings/sound/tas571x.txt  |  41 ++
 MAINTAINERS|   6 +
 drivers/base/regmap/internal.h |   3 +
 drivers/base/regmap/regcache.c |  45 +-
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 515 +
 sound/soc/codecs/tas571x.h |  33 ++
 8 files changed, 635 insertions(+), 15 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V4 5/5] MAINTAINERS: Add entry for tas571x ASoC codec driver

2015-05-05 Thread Kevin Cernekee
Add self as maintainer for the new driver.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 MAINTAINERS | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ea0001760035..15153fc37cc4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9878,6 +9878,12 @@ L:   net...@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/ti/netcp*
 
+TI TAS571X FAMILY ASoC CODEC DRIVER
+M: Kevin Cernekee cerne...@chromium.org
+L: alsa-de...@alsa-project.org (moderated for non-subscribers)
+S: Odd Fixes
+F: sound/soc/codecs/tas571x*
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M: Peter Ujfalusi peter.ujfal...@ti.com
 L: alsa-de...@alsa-project.org (moderated for non-subscribers)
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V4 1/5] regmap: Add a helper function for regcache sync test

2015-05-05 Thread Kevin Cernekee
We're going to add another does this register need syncing? check, so
rather than repeating it in three places, we'll separate all of the
relevant logic into a helper function.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 drivers/base/regmap/regcache.c | 26 +++---
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 7eb7b3b98794..c58493eaf050 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -249,6 +249,18 @@ int regcache_write(struct regmap *map,
return 0;
 }
 
+static bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg,
+   unsigned int val)
+{
+   int ret;
+
+   /* Is this the hardware default?  If so skip. */
+   ret = regcache_lookup_reg(map, reg);
+   if (ret = 0  val == map-reg_defaults[ret].def)
+   return false;
+   return true;
+}
+
 static int regcache_default_sync(struct regmap *map, unsigned int min,
 unsigned int max)
 {
@@ -266,9 +278,7 @@ static int regcache_default_sync(struct regmap *map, 
unsigned int min,
if (ret)
return ret;
 
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, reg);
-   if (ret = 0  val == map-reg_defaults[ret].def)
+   if (!regcache_reg_needs_sync(map, reg, val))
continue;
 
map-cache_bypass = 1;
@@ -613,10 +623,7 @@ static int regcache_sync_block_single(struct regmap *map, 
void *block,
continue;
 
val = regcache_get_val(map, block, i);
-
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, regtmp);
-   if (ret = 0  val == map-reg_defaults[ret].def)
+   if (!regcache_reg_needs_sync(map, regtmp, val))
continue;
 
map-cache_bypass = 1;
@@ -688,10 +695,7 @@ static int regcache_sync_block_raw(struct regmap *map, 
void *block,
}
 
val = regcache_get_val(map, block, i);
-
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, regtmp);
-   if (ret = 0  val == map-reg_defaults[ret].def) {
+   if (!regcache_reg_needs_sync(map, regtmp, val)) {
ret = regcache_sync_block_raw_flush(map, data,
base, regtmp);
if (ret != 0)
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V4 3/5] ASoC: tas571x: Add DT binding document

2015-05-05 Thread Kevin Cernekee
Document the bindings for the soon-to-be-added tas571x driver.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 .../devicetree/bindings/sound/tas571x.txt  | 41 ++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt

diff --git a/Documentation/devicetree/bindings/sound/tas571x.txt 
b/Documentation/devicetree/bindings/sound/tas571x.txt
new file mode 100644
index ..0ac31d8d5ac4
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tas571x.txt
@@ -0,0 +1,41 @@
+Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers
+
+The codec is controlled through an I2C interface.  It also has two other
+signals that can be wired up to GPIOs: reset (strongly recommended), and
+powerdown (optional).
+
+Required properties:
+
+- compatible: ti,tas5711, ti,tas5717, or ti,tas5719
+- reg: The I2C address of the device
+- #sound-dai-cells: must be equal to 0
+
+Optional properties:
+
+- reset-gpios: GPIO specifier for the TAS571x's active low reset line
+- pdn-gpios: GPIO specifier for the TAS571x's active low powerdown line
+- clocks: clock phandle for the MCLK input
+- clock-names: should be mclk
+- AVDD-supply: regulator phandle for the AVDD supply (all chips)
+- DVDD-supply: regulator phandle for the DVDD supply (all chips)
+- HPVDD-supply: regulator phandle for the HPVDD supply (5717/5719)
+- PVDD_AB-supply: regulator phandle for the PVDD_AB supply (5717/5719)
+- PVDD_CD-supply: regulator phandle for the PVDD_CD supply (5717/5719)
+- PVDD_A-supply: regulator phandle for the PVDD_A supply (5711)
+- PVDD_B-supply: regulator phandle for the PVDD_B supply (5711)
+- PVDD_C-supply: regulator phandle for the PVDD_C supply (5711)
+- PVDD_D-supply: regulator phandle for the PVDD_D supply (5711)
+
+Example:
+
+   tas5717: audio-codec@2a {
+   compatible = ti,tas5717;
+   reg = 0x2a;
+   #sound-dai-cells = 0;
+
+   reset-gpios = gpio5 1 GPIO_ACTIVE_LOW;
+   pdn-gpios = gpio5 2 GPIO_ACTIVE_LOW;
+
+   clocks = clk_core CLK_I2S;
+   clock-names = mclk;
+   };
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V4 2/5] regmap: Use regcache_mark_dirty() to indicate power loss or reset

2015-05-05 Thread Kevin Cernekee
Existing regmap users call regcache_mark_dirty() as part of the
suspend/resume sequence, to tell regcache that non-default values need to
be resynced post-resume.  Add an internal no_sync_defaults regmap flag
to remember this state, so that regcache_sync() can differentiate between
these two cases:

1) HW was reset, so any cache values that match map-reg_defaults can be
safely skipped.  On some chips there are a lot of registers in the
reg_defaults list, so this optimization speeds things up quite a bit.

2) HW was not reset (maybe it was just clock-gated), so if we cached
any writes, they should be sent to the hardware regardless of whether
they match the HW default.  Currently this will write out all values in
the regcache, since we don't maintain per-register dirty bits.

Suggested-by: Mark Brown broo...@kernel.org
Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 drivers/base/regmap/internal.h |  3 +++
 drivers/base/regmap/regcache.c | 19 +++
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index a13587b5c2be..b2b2849fc6d3 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -131,7 +131,10 @@ struct regmap {
struct reg_default *reg_defaults;
const void *reg_defaults_raw;
void *cache;
+   /* if set, the cache contains newer data than the HW */
u32 cache_dirty;
+   /* if set, the HW registers are known to match map-reg_defaults */
+   bool no_sync_defaults;
 
struct reg_default *patch;
int patch_regs;
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index c58493eaf050..b9862d741a56 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -254,6 +254,10 @@ static bool regcache_reg_needs_sync(struct regmap *map, 
unsigned int reg,
 {
int ret;
 
+   /* If we don't know the chip just got reset, then sync everything. */
+   if (!map-no_sync_defaults)
+   return true;
+
/* Is this the hardware default?  If so skip. */
ret = regcache_lookup_reg(map, reg);
if (ret = 0  val == map-reg_defaults[ret].def)
@@ -352,6 +356,7 @@ out:
/* Restore the bypass state */
map-async = false;
map-cache_bypass = bypass;
+   map-no_sync_defaults = false;
map-unlock(map-lock_arg);
 
regmap_async_complete(map);
@@ -407,6 +412,7 @@ out:
/* Restore the bypass state */
map-cache_bypass = bypass;
map-async = false;
+   map-no_sync_defaults = false;
map-unlock(map-lock_arg);
 
regmap_async_complete(map);
@@ -471,18 +477,23 @@ void regcache_cache_only(struct regmap *map, bool enable)
 EXPORT_SYMBOL_GPL(regcache_cache_only);
 
 /**
- * regcache_mark_dirty: Mark the register cache as dirty
+ * regcache_mark_dirty: Indicate that HW registers were reset to default values
  *
  * @map: map to mark
  *
- * Mark the register cache as dirty, for example due to the device
- * having been powered down for suspend.  If the cache is not marked
- * as dirty then the cache sync will be suppressed.
+ * Inform regcache that the device has been powered down or reset, so that
+ * on resume, regcache_sync() knows to write out all non-default values
+ * stored in the cache.
+ *
+ * If this function is not called, regcache_sync() will assume that
+ * the hardware state still matches the cache state, modulo any writes that
+ * happened when cache_only was true.
  */
 void regcache_mark_dirty(struct regmap *map)
 {
map-lock(map-lock_arg);
map-cache_dirty = true;
+   map-no_sync_defaults = true;
map-unlock(map-lock_arg);
 }
 EXPORT_SYMBOL_GPL(regcache_mark_dirty);
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/6] MAINTAINERS: Remove section BROADCOM BCM33XX MIPS ARCHITECTURE

2015-05-05 Thread Kevin Cernekee
On Tue, May 5, 2015 at 9:32 AM, Joe Perches j...@perches.com wrote:
 commit 5f2d44591fb3 (MIPS: bcm3384: Rename bcm3384 target to bmips)
 renamed the files and integrated them into an existing section.

 Remove the section.

 Signed-off-by: Joe Perches j...@perches.com
 cc: Kevin Cernekee cerne...@gmail.com
 ---
  MAINTAINERS | 8 
  1 file changed, 8 deletions(-)

 diff --git a/MAINTAINERS b/MAINTAINERS
 index bbfb324..f2fd5c7 100644
 --- a/MAINTAINERS
 +++ b/MAINTAINERS
 @@ -2141,14 +2141,6 @@ T:   git 
 git://git.kernel.org/pub/scm/linux/kernel/git/rpi/linux-rpi.git
  S: Maintained
  N: bcm2835

 -BROADCOM BCM33XX MIPS ARCHITECTURE
 -M: Kevin Cernekee cerne...@gmail.com
 -L: linux-m...@linux-mips.org
 -S: Maintained
 -F: arch/mips/bcm3384/*
 -F: arch/mips/include/asm/mach-bcm3384/*
 -F: arch/mips/kernel/*bmips*
 -
  BROADCOM BCM5301X ARM ARCHITECTURE
  M: Hauke Mehrtens ha...@hauke-m.de
  L: linux-arm-ker...@lists.infradead.org
 --
 2.1.4


Acked-by: Kevin Cernekee cerne...@gmail.com
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V3 1/4] regmap: Use regcache_mark_dirty() to indicate power loss or reset

2015-05-04 Thread Kevin Cernekee
On Sun, May 3, 2015 at 11:38 PM, Lars-Peter Clausen  wrote:
>> diff --git a/drivers/base/regmap/regcache.c
>> b/drivers/base/regmap/regcache.c
>> index 7eb7b3b98794..63af3103d0c6 100644
>> --- a/drivers/base/regmap/regcache.c
>> +++ b/drivers/base/regmap/regcache.c
>> @@ -253,6 +253,9 @@ static int regcache_default_sync(struct regmap *map,
>> unsigned int min,
>>  unsigned int max)
>>   {
>> unsigned int reg;
>> +   bool no_sync_defaults = map->no_sync_defaults;
>> +
>> +   map->no_sync_defaults = false;
>
>
> This needs to be done at the end in regcache_sync(), the same place where
> dirty is set to false.

But map->cache_dirty means "any register is dirty," not "all registers
are dirty."  So it can only be cleared after a successful flush.

If one of the writes fails and regcache_sync() has to return
prematurely, we probably don't want no_sync_defaults to stay true
because some of the HW registers might not match map->reg_defaults
anymore.

Leaving it set to true wouldn't break the current regcache_sync()
implementation, but no_sync_defaults is documented as: "if set, the HW
registers are known to match map->reg_defaults".  Writing any register
to a non-default value makes it false.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V3 3/4] ASoC: tas571x: New driver for TI TAS571x power amplifiers

2015-05-04 Thread Kevin Cernekee
On Mon, May 4, 2015 at 4:45 AM, Mark Brown  wrote:
> On Sun, May 03, 2015 at 05:00:18PM -0700, Kevin Cernekee wrote:
>> + if (dev->of_node) {
>> + const struct of_device_id *of_id;
>> +
>> + of_id = of_match_device(tas571x_of_match, dev);
>> + if (of_id)
>> + priv->chip = of_id->data;
>> + }
>
> Doesn't of_match_device() do the right thing with devices not registered
> from DT?

Not sure.  What kinds of situations are you concerned about?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V3 3/4] ASoC: tas571x: New driver for TI TAS571x power amplifiers

2015-05-04 Thread Kevin Cernekee
On Mon, May 4, 2015 at 4:45 AM, Mark Brown broo...@kernel.org wrote:
 On Sun, May 03, 2015 at 05:00:18PM -0700, Kevin Cernekee wrote:
 + if (dev-of_node) {
 + const struct of_device_id *of_id;
 +
 + of_id = of_match_device(tas571x_of_match, dev);
 + if (of_id)
 + priv-chip = of_id-data;
 + }

 Doesn't of_match_device() do the right thing with devices not registered
 from DT?

Not sure.  What kinds of situations are you concerned about?
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V3 1/4] regmap: Use regcache_mark_dirty() to indicate power loss or reset

2015-05-04 Thread Kevin Cernekee
On Sun, May 3, 2015 at 11:38 PM, Lars-Peter Clausen l...@metafoo.de wrote:
 diff --git a/drivers/base/regmap/regcache.c
 b/drivers/base/regmap/regcache.c
 index 7eb7b3b98794..63af3103d0c6 100644
 --- a/drivers/base/regmap/regcache.c
 +++ b/drivers/base/regmap/regcache.c
 @@ -253,6 +253,9 @@ static int regcache_default_sync(struct regmap *map,
 unsigned int min,
  unsigned int max)
   {
 unsigned int reg;
 +   bool no_sync_defaults = map-no_sync_defaults;
 +
 +   map-no_sync_defaults = false;


 This needs to be done at the end in regcache_sync(), the same place where
 dirty is set to false.

But map-cache_dirty means any register is dirty, not all registers
are dirty.  So it can only be cleared after a successful flush.

If one of the writes fails and regcache_sync() has to return
prematurely, we probably don't want no_sync_defaults to stay true
because some of the HW registers might not match map-reg_defaults
anymore.

Leaving it set to true wouldn't break the current regcache_sync()
implementation, but no_sync_defaults is documented as: if set, the HW
registers are known to match map-reg_defaults.  Writing any register
to a non-default value makes it false.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 4/4] MAINTAINERS: Add entry for tas571x ASoC codec driver

2015-05-03 Thread Kevin Cernekee
Add self as maintainer for the new driver.

Signed-off-by: Kevin Cernekee 
---
 MAINTAINERS | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ea0001760035..15153fc37cc4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9878,6 +9878,12 @@ L:   net...@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/ti/netcp*
 
+TI TAS571X FAMILY ASoC CODEC DRIVER
+M: Kevin Cernekee 
+L: alsa-de...@alsa-project.org (moderated for non-subscribers)
+S: Odd Fixes
+F: sound/soc/codecs/tas571x*
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M: Peter Ujfalusi 
 L: alsa-de...@alsa-project.org (moderated for non-subscribers)
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 2/4] ASoC: tas571x: Add DT binding document

2015-05-03 Thread Kevin Cernekee
Document the bindings for the soon-to-be-added tas571x driver.

Signed-off-by: Kevin Cernekee 
---
 .../devicetree/bindings/sound/tas571x.txt  | 41 ++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt

diff --git a/Documentation/devicetree/bindings/sound/tas571x.txt 
b/Documentation/devicetree/bindings/sound/tas571x.txt
new file mode 100644
index ..0ac31d8d5ac4
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tas571x.txt
@@ -0,0 +1,41 @@
+Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers
+
+The codec is controlled through an I2C interface.  It also has two other
+signals that can be wired up to GPIOs: reset (strongly recommended), and
+powerdown (optional).
+
+Required properties:
+
+- compatible: "ti,tas5711", "ti,tas5717", or "ti,tas5719"
+- reg: The I2C address of the device
+- #sound-dai-cells: must be equal to 0
+
+Optional properties:
+
+- reset-gpios: GPIO specifier for the TAS571x's active low reset line
+- pdn-gpios: GPIO specifier for the TAS571x's active low powerdown line
+- clocks: clock phandle for the MCLK input
+- clock-names: should be "mclk"
+- AVDD-supply: regulator phandle for the AVDD supply (all chips)
+- DVDD-supply: regulator phandle for the DVDD supply (all chips)
+- HPVDD-supply: regulator phandle for the HPVDD supply (5717/5719)
+- PVDD_AB-supply: regulator phandle for the PVDD_AB supply (5717/5719)
+- PVDD_CD-supply: regulator phandle for the PVDD_CD supply (5717/5719)
+- PVDD_A-supply: regulator phandle for the PVDD_A supply (5711)
+- PVDD_B-supply: regulator phandle for the PVDD_B supply (5711)
+- PVDD_C-supply: regulator phandle for the PVDD_C supply (5711)
+- PVDD_D-supply: regulator phandle for the PVDD_D supply (5711)
+
+Example:
+
+   tas5717: audio-codec@2a {
+   compatible = "ti,tas5717";
+   reg = <0x2a>;
+   #sound-dai-cells = <0>;
+
+   reset-gpios = < 1 GPIO_ACTIVE_LOW>;
+   pdn-gpios = < 2 GPIO_ACTIVE_LOW>;
+
+   clocks = <_core CLK_I2S>;
+   clock-names = "mclk";
+   };
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 3/4] ASoC: tas571x: New driver for TI TAS571x power amplifiers

2015-05-03 Thread Kevin Cernekee
Introduce a new codec driver for the Texas Instruments
TAS5711/TAS5717/TAS5719 power amplifier chips.  These chips are typically
used to take an I2S digital audio input and drive 10-20W into a pair of
speakers.

Signed-off-by: Kevin Cernekee 
---
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 520 +
 sound/soc/codecs/tas571x.h |  33 +++
 4 files changed, 560 insertions(+)
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 061c46587628..befff910d71a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TAS2552 if I2C
select SND_SOC_TAS5086 if I2C
+   select SND_SOC_TAS571X if I2C
select SND_SOC_TFA9879 if I2C
select SND_SOC_TLV320AIC23_I2C if I2C
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
@@ -611,6 +612,10 @@ config SND_SOC_TAS5086
tristate "Texas Instruments TAS5086 speaker amplifier"
depends on I2C
 
+config SND_SOC_TAS571X
+   tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers"
+   depends on I2C
+
 config SND_SOC_TFA9879
tristate "NXP Semiconductors TFA9879 amplifier"
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index abe2d7edf65c..3dcf5ac85e89 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -106,6 +106,7 @@ snd-soc-sta350-objs := sta350.o
 snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tas5086-objs := tas5086.o
+snd-soc-tas571x-objs := tas571x.o
 snd-soc-tfa9879-objs := tfa9879.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
@@ -288,6 +289,7 @@ obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TAS2552)  += snd-soc-tas2552.o
 obj-$(CONFIG_SND_SOC_TAS5086)  += snd-soc-tas5086.o
+obj-$(CONFIG_SND_SOC_TAS571X)  += snd-soc-tas571x.o
 obj-$(CONFIG_SND_SOC_TFA9879)  += snd-soc-tfa9879.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)  += snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C)  += snd-soc-tlv320aic23-i2c.o
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
new file mode 100644
index ..ffdf48397491
--- /dev/null
+++ b/sound/soc/codecs/tas571x.c
@@ -0,0 +1,520 @@
+/*
+ * TAS571x amplifier audio driver
+ *
+ * Copyright (C) 2015 Google, Inc.
+ * Copyright (c) 2013 Daniel Mack 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "tas571x.h"
+
+#define TAS571X_MAX_SUPPLIES   6
+
+struct tas571x_chip {
+   const char  *const *supply_names;
+   int num_supply_names;
+   const struct snd_kcontrol_new   *controls;
+   int num_controls;
+   const struct regmap_config  *regmap_config;
+   int vol_reg_size;
+};
+
+struct tas571x_private {
+   const struct tas571x_chip   *chip;
+   struct regmap   *regmap;
+   struct regulator_bulk_data  supplies[TAS571X_MAX_SUPPLIES];
+   struct clk  *mclk;
+   unsigned intformat;
+   struct gpio_desc*reset_gpio;
+   struct gpio_desc*pdn_gpio;
+   struct snd_soc_codec_driver codec_driver;
+};
+
+static int tas571x_register_size(struct tas571x_private *priv, unsigned int 
reg)
+{
+   switch (reg) {
+   case TAS571X_MVOL_REG:
+   case TAS571X_CH1_VOL_REG:
+   case TAS571X_CH2_VOL_REG:
+   return priv->chip->vol_reg_size;
+   default:
+   return 1;
+   }
+}
+
+static int tas571x_reg_write(void *context, unsigned int reg,
+unsigned int value)
+{
+   struct i2c_client *client = context;
+   struct tas571x_private *priv = i2c_get_clientdata(client);
+   unsigned int i, size;
+   uint8_t buf[5];
+   int ret;
+
+   size = tas571x_register_size(priv, reg);
+   buf[0] = reg;
+
+   for (i = size; i >= 1; --i) {
+   buf[i] = value;
+   value >>= 8;
+   }
+
+   ret = i2c_master_send(client, buf, size + 1);
+   if (ret == size + 1)
+   return 

[PATCH V3 1/4] regmap: Use regcache_mark_dirty() to indicate power loss or reset

2015-05-03 Thread Kevin Cernekee
Existing regmap users call regcache_mark_dirty() as part of the
suspend/resume sequence, to tell regcache that non-default values need to
be resynced post-resume.  Add an internal "no_sync_defaults" regmap flag
to remember this state, so that regcache_sync() can differentiate between
these two cases:

1) HW was reset, so any cache values that match map->reg_defaults can be
safely skipped.  On some chips there are a lot of registers in the
reg_defaults list, so this optimization speeds things up quite a bit.

2) HW was not reset (maybe it was just clock-gated), so if we cached
any writes, they should be sent to the hardware regardless of whether
they match the HW default.  Currently this will write out all values in
the regcache, since we don't maintain per-register dirty bits.

Suggested-by: Mark Brown 
Signed-off-by: Kevin Cernekee 
---
 drivers/base/regmap/internal.h |  3 +++
 drivers/base/regmap/regcache.c | 61 --
 2 files changed, 44 insertions(+), 20 deletions(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index a13587b5c2be..b2b2849fc6d3 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -131,7 +131,10 @@ struct regmap {
struct reg_default *reg_defaults;
const void *reg_defaults_raw;
void *cache;
+   /* if set, the cache contains newer data than the HW */
u32 cache_dirty;
+   /* if set, the HW registers are known to match map->reg_defaults */
+   bool no_sync_defaults;
 
struct reg_default *patch;
int patch_regs;
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 7eb7b3b98794..63af3103d0c6 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -253,6 +253,9 @@ static int regcache_default_sync(struct regmap *map, 
unsigned int min,
 unsigned int max)
 {
unsigned int reg;
+   bool no_sync_defaults = map->no_sync_defaults;
+
+   map->no_sync_defaults = false;
 
for (reg = min; reg <= max; reg += map->reg_stride) {
unsigned int val;
@@ -266,10 +269,12 @@ static int regcache_default_sync(struct regmap *map, 
unsigned int min,
if (ret)
return ret;
 
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, reg);
-   if (ret >= 0 && val == map->reg_defaults[ret].def)
-   continue;
+   if (no_sync_defaults) {
+   /* Is this the hardware default?  If so skip. */
+   ret = regcache_lookup_reg(map, reg);
+   if (ret >= 0 && val == map->reg_defaults[ret].def)
+   continue;
+   }
 
map->cache_bypass = 1;
ret = _regmap_write(map, reg, val);
@@ -461,18 +466,23 @@ void regcache_cache_only(struct regmap *map, bool enable)
 EXPORT_SYMBOL_GPL(regcache_cache_only);
 
 /**
- * regcache_mark_dirty: Mark the register cache as dirty
+ * regcache_mark_dirty: Indicate that HW registers were reset to default values
  *
  * @map: map to mark
  *
- * Mark the register cache as dirty, for example due to the device
- * having been powered down for suspend.  If the cache is not marked
- * as dirty then the cache sync will be suppressed.
+ * Inform regcache that the device has been powered down or reset, so that
+ * on resume, regcache_sync() knows to write out all non-default values
+ * stored in the cache.
+ *
+ * If this function is not called, regcache_sync() will assume that
+ * the hardware state still matches the cache state, modulo any writes that
+ * happened when cache_only was true.
  */
 void regcache_mark_dirty(struct regmap *map)
 {
map->lock(map->lock_arg);
map->cache_dirty = true;
+   map->no_sync_defaults = true;
map->unlock(map->lock_arg);
 }
 EXPORT_SYMBOL_GPL(regcache_mark_dirty);
@@ -604,6 +614,9 @@ static int regcache_sync_block_single(struct regmap *map, 
void *block,
 {
unsigned int i, regtmp, val;
int ret;
+   bool no_sync_defaults = map->no_sync_defaults;
+
+   map->no_sync_defaults = false;
 
for (i = start; i < end; i++) {
regtmp = block_base + (i * map->reg_stride);
@@ -614,10 +627,12 @@ static int regcache_sync_block_single(struct regmap *map, 
void *block,
 
val = regcache_get_val(map, block, i);
 
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, regtmp);
-   if (ret >= 0 && val == map->reg_defaults[ret].def)
-   continue;
+   if (no_sync_defaults) {
+   /* Is this the hardware default?  If so skip. */
+  

[PATCH V3 0/4] tas571x amplifier driver

2015-05-03 Thread Kevin Cernekee
V2->V3:

Revert earlier changes to the regcache APIs.

Change regcache_sync() so that regcache_mark_dirty() is used to indicate
that the HW was reset.  This allows tas571x (which does NOT call
regcache_mark_dirty()) to use regcache_sync() to write back any register
changes that occurred while in cache_only (tas571x pdn) mode.

One assumption here is that regcache_sync() will be called once on
resume, before any other writes.  If it fails, the no_sync_defaults flag
will be cleared and the next sync attempt, if any, will try to write
out all contents of the cache.


Kevin Cernekee (4):
  regmap: Use regcache_mark_dirty() to indicate power loss or reset
  ASoC: tas571x: Add DT binding document
  ASoC: tas571x: New driver for TI TAS571x power amplifiers
  MAINTAINERS: Add entry for tas571x ASoC codec driver

 .../devicetree/bindings/sound/tas571x.txt  |  41 ++
 MAINTAINERS|   6 +
 drivers/base/regmap/internal.h |   3 +
 drivers/base/regmap/regcache.c |  61 ++-
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 520 +
 sound/soc/codecs/tas571x.h |  33 ++
 8 files changed, 651 insertions(+), 20 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 3/4] ASoC: tas571x: New driver for TI TAS571x power amplifiers

2015-05-03 Thread Kevin Cernekee
Introduce a new codec driver for the Texas Instruments
TAS5711/TAS5717/TAS5719 power amplifier chips.  These chips are typically
used to take an I2S digital audio input and drive 10-20W into a pair of
speakers.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 520 +
 sound/soc/codecs/tas571x.h |  33 +++
 4 files changed, 560 insertions(+)
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 061c46587628..befff910d71a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TAS2552 if I2C
select SND_SOC_TAS5086 if I2C
+   select SND_SOC_TAS571X if I2C
select SND_SOC_TFA9879 if I2C
select SND_SOC_TLV320AIC23_I2C if I2C
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
@@ -611,6 +612,10 @@ config SND_SOC_TAS5086
tristate Texas Instruments TAS5086 speaker amplifier
depends on I2C
 
+config SND_SOC_TAS571X
+   tristate Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers
+   depends on I2C
+
 config SND_SOC_TFA9879
tristate NXP Semiconductors TFA9879 amplifier
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index abe2d7edf65c..3dcf5ac85e89 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -106,6 +106,7 @@ snd-soc-sta350-objs := sta350.o
 snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tas5086-objs := tas5086.o
+snd-soc-tas571x-objs := tas571x.o
 snd-soc-tfa9879-objs := tfa9879.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
@@ -288,6 +289,7 @@ obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TAS2552)  += snd-soc-tas2552.o
 obj-$(CONFIG_SND_SOC_TAS5086)  += snd-soc-tas5086.o
+obj-$(CONFIG_SND_SOC_TAS571X)  += snd-soc-tas571x.o
 obj-$(CONFIG_SND_SOC_TFA9879)  += snd-soc-tfa9879.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)  += snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C)  += snd-soc-tlv320aic23-i2c.o
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
new file mode 100644
index ..ffdf48397491
--- /dev/null
+++ b/sound/soc/codecs/tas571x.c
@@ -0,0 +1,520 @@
+/*
+ * TAS571x amplifier audio driver
+ *
+ * Copyright (C) 2015 Google, Inc.
+ * Copyright (c) 2013 Daniel Mack zon...@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include linux/clk.h
+#include linux/delay.h
+#include linux/device.h
+#include linux/gpio/consumer.h
+#include linux/i2c.h
+#include linux/init.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/of_device.h
+#include linux/regmap.h
+#include linux/regulator/consumer.h
+#include linux/stddef.h
+#include sound/pcm_params.h
+#include sound/soc.h
+#include sound/tlv.h
+
+#include tas571x.h
+
+#define TAS571X_MAX_SUPPLIES   6
+
+struct tas571x_chip {
+   const char  *const *supply_names;
+   int num_supply_names;
+   const struct snd_kcontrol_new   *controls;
+   int num_controls;
+   const struct regmap_config  *regmap_config;
+   int vol_reg_size;
+};
+
+struct tas571x_private {
+   const struct tas571x_chip   *chip;
+   struct regmap   *regmap;
+   struct regulator_bulk_data  supplies[TAS571X_MAX_SUPPLIES];
+   struct clk  *mclk;
+   unsigned intformat;
+   struct gpio_desc*reset_gpio;
+   struct gpio_desc*pdn_gpio;
+   struct snd_soc_codec_driver codec_driver;
+};
+
+static int tas571x_register_size(struct tas571x_private *priv, unsigned int 
reg)
+{
+   switch (reg) {
+   case TAS571X_MVOL_REG:
+   case TAS571X_CH1_VOL_REG:
+   case TAS571X_CH2_VOL_REG:
+   return priv-chip-vol_reg_size;
+   default:
+   return 1;
+   }
+}
+
+static int tas571x_reg_write(void *context, unsigned int reg,
+unsigned int value)
+{
+   struct i2c_client *client = context;
+   struct tas571x_private *priv = i2c_get_clientdata(client);
+   unsigned int i, size;
+   uint8_t buf[5];
+   int ret;
+
+   size = tas571x_register_size(priv, reg);
+   buf[0] = reg;
+
+   for (i = size; i = 1

[PATCH V3 1/4] regmap: Use regcache_mark_dirty() to indicate power loss or reset

2015-05-03 Thread Kevin Cernekee
Existing regmap users call regcache_mark_dirty() as part of the
suspend/resume sequence, to tell regcache that non-default values need to
be resynced post-resume.  Add an internal no_sync_defaults regmap flag
to remember this state, so that regcache_sync() can differentiate between
these two cases:

1) HW was reset, so any cache values that match map-reg_defaults can be
safely skipped.  On some chips there are a lot of registers in the
reg_defaults list, so this optimization speeds things up quite a bit.

2) HW was not reset (maybe it was just clock-gated), so if we cached
any writes, they should be sent to the hardware regardless of whether
they match the HW default.  Currently this will write out all values in
the regcache, since we don't maintain per-register dirty bits.

Suggested-by: Mark Brown broo...@kernel.org
Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 drivers/base/regmap/internal.h |  3 +++
 drivers/base/regmap/regcache.c | 61 --
 2 files changed, 44 insertions(+), 20 deletions(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index a13587b5c2be..b2b2849fc6d3 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -131,7 +131,10 @@ struct regmap {
struct reg_default *reg_defaults;
const void *reg_defaults_raw;
void *cache;
+   /* if set, the cache contains newer data than the HW */
u32 cache_dirty;
+   /* if set, the HW registers are known to match map-reg_defaults */
+   bool no_sync_defaults;
 
struct reg_default *patch;
int patch_regs;
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 7eb7b3b98794..63af3103d0c6 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -253,6 +253,9 @@ static int regcache_default_sync(struct regmap *map, 
unsigned int min,
 unsigned int max)
 {
unsigned int reg;
+   bool no_sync_defaults = map-no_sync_defaults;
+
+   map-no_sync_defaults = false;
 
for (reg = min; reg = max; reg += map-reg_stride) {
unsigned int val;
@@ -266,10 +269,12 @@ static int regcache_default_sync(struct regmap *map, 
unsigned int min,
if (ret)
return ret;
 
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, reg);
-   if (ret = 0  val == map-reg_defaults[ret].def)
-   continue;
+   if (no_sync_defaults) {
+   /* Is this the hardware default?  If so skip. */
+   ret = regcache_lookup_reg(map, reg);
+   if (ret = 0  val == map-reg_defaults[ret].def)
+   continue;
+   }
 
map-cache_bypass = 1;
ret = _regmap_write(map, reg, val);
@@ -461,18 +466,23 @@ void regcache_cache_only(struct regmap *map, bool enable)
 EXPORT_SYMBOL_GPL(regcache_cache_only);
 
 /**
- * regcache_mark_dirty: Mark the register cache as dirty
+ * regcache_mark_dirty: Indicate that HW registers were reset to default values
  *
  * @map: map to mark
  *
- * Mark the register cache as dirty, for example due to the device
- * having been powered down for suspend.  If the cache is not marked
- * as dirty then the cache sync will be suppressed.
+ * Inform regcache that the device has been powered down or reset, so that
+ * on resume, regcache_sync() knows to write out all non-default values
+ * stored in the cache.
+ *
+ * If this function is not called, regcache_sync() will assume that
+ * the hardware state still matches the cache state, modulo any writes that
+ * happened when cache_only was true.
  */
 void regcache_mark_dirty(struct regmap *map)
 {
map-lock(map-lock_arg);
map-cache_dirty = true;
+   map-no_sync_defaults = true;
map-unlock(map-lock_arg);
 }
 EXPORT_SYMBOL_GPL(regcache_mark_dirty);
@@ -604,6 +614,9 @@ static int regcache_sync_block_single(struct regmap *map, 
void *block,
 {
unsigned int i, regtmp, val;
int ret;
+   bool no_sync_defaults = map-no_sync_defaults;
+
+   map-no_sync_defaults = false;
 
for (i = start; i  end; i++) {
regtmp = block_base + (i * map-reg_stride);
@@ -614,10 +627,12 @@ static int regcache_sync_block_single(struct regmap *map, 
void *block,
 
val = regcache_get_val(map, block, i);
 
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, regtmp);
-   if (ret = 0  val == map-reg_defaults[ret].def)
-   continue;
+   if (no_sync_defaults) {
+   /* Is this the hardware default?  If so skip. */
+   ret = regcache_lookup_reg(map, regtmp);
+   if (ret = 0  val == map

[PATCH V3 2/4] ASoC: tas571x: Add DT binding document

2015-05-03 Thread Kevin Cernekee
Document the bindings for the soon-to-be-added tas571x driver.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 .../devicetree/bindings/sound/tas571x.txt  | 41 ++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt

diff --git a/Documentation/devicetree/bindings/sound/tas571x.txt 
b/Documentation/devicetree/bindings/sound/tas571x.txt
new file mode 100644
index ..0ac31d8d5ac4
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tas571x.txt
@@ -0,0 +1,41 @@
+Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers
+
+The codec is controlled through an I2C interface.  It also has two other
+signals that can be wired up to GPIOs: reset (strongly recommended), and
+powerdown (optional).
+
+Required properties:
+
+- compatible: ti,tas5711, ti,tas5717, or ti,tas5719
+- reg: The I2C address of the device
+- #sound-dai-cells: must be equal to 0
+
+Optional properties:
+
+- reset-gpios: GPIO specifier for the TAS571x's active low reset line
+- pdn-gpios: GPIO specifier for the TAS571x's active low powerdown line
+- clocks: clock phandle for the MCLK input
+- clock-names: should be mclk
+- AVDD-supply: regulator phandle for the AVDD supply (all chips)
+- DVDD-supply: regulator phandle for the DVDD supply (all chips)
+- HPVDD-supply: regulator phandle for the HPVDD supply (5717/5719)
+- PVDD_AB-supply: regulator phandle for the PVDD_AB supply (5717/5719)
+- PVDD_CD-supply: regulator phandle for the PVDD_CD supply (5717/5719)
+- PVDD_A-supply: regulator phandle for the PVDD_A supply (5711)
+- PVDD_B-supply: regulator phandle for the PVDD_B supply (5711)
+- PVDD_C-supply: regulator phandle for the PVDD_C supply (5711)
+- PVDD_D-supply: regulator phandle for the PVDD_D supply (5711)
+
+Example:
+
+   tas5717: audio-codec@2a {
+   compatible = ti,tas5717;
+   reg = 0x2a;
+   #sound-dai-cells = 0;
+
+   reset-gpios = gpio5 1 GPIO_ACTIVE_LOW;
+   pdn-gpios = gpio5 2 GPIO_ACTIVE_LOW;
+
+   clocks = clk_core CLK_I2S;
+   clock-names = mclk;
+   };
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 0/4] tas571x amplifier driver

2015-05-03 Thread Kevin Cernekee
V2-V3:

Revert earlier changes to the regcache APIs.

Change regcache_sync() so that regcache_mark_dirty() is used to indicate
that the HW was reset.  This allows tas571x (which does NOT call
regcache_mark_dirty()) to use regcache_sync() to write back any register
changes that occurred while in cache_only (tas571x pdn) mode.

One assumption here is that regcache_sync() will be called once on
resume, before any other writes.  If it fails, the no_sync_defaults flag
will be cleared and the next sync attempt, if any, will try to write
out all contents of the cache.


Kevin Cernekee (4):
  regmap: Use regcache_mark_dirty() to indicate power loss or reset
  ASoC: tas571x: Add DT binding document
  ASoC: tas571x: New driver for TI TAS571x power amplifiers
  MAINTAINERS: Add entry for tas571x ASoC codec driver

 .../devicetree/bindings/sound/tas571x.txt  |  41 ++
 MAINTAINERS|   6 +
 drivers/base/regmap/internal.h |   3 +
 drivers/base/regmap/regcache.c |  61 ++-
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 520 +
 sound/soc/codecs/tas571x.h |  33 ++
 8 files changed, 651 insertions(+), 20 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3 4/4] MAINTAINERS: Add entry for tas571x ASoC codec driver

2015-05-03 Thread Kevin Cernekee
Add self as maintainer for the new driver.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 MAINTAINERS | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ea0001760035..15153fc37cc4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9878,6 +9878,12 @@ L:   net...@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/ti/netcp*
 
+TI TAS571X FAMILY ASoC CODEC DRIVER
+M: Kevin Cernekee cerne...@chromium.org
+L: alsa-de...@alsa-project.org (moderated for non-subscribers)
+S: Odd Fixes
+F: sound/soc/codecs/tas571x*
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M: Peter Ujfalusi peter.ujfal...@ti.com
 L: alsa-de...@alsa-project.org (moderated for non-subscribers)
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2 1/4] regmap: cache: Add "was_reset" argument to regcache_sync_region()

2015-04-29 Thread Kevin Cernekee
On Wed, Apr 29, 2015 at 9:46 AM, Mark Brown  wrote:
> On Wed, Apr 29, 2015 at 07:13:27AM -0700, Kevin Cernekee wrote:
>> On Wed, Apr 29, 2015 at 3:40 AM, Mark Brown  wrote:
>
>> > Like I said above we can tell if the hardware was reset because
>> > mark_dirty() is called.
>
>> That covers the public API, but I do not understand how you intended
>> for this data to be stored in the rbtree if the use of a dirty bitmask
>> is discouraged.
>
> We just need a single boolean?

Right, so if we add a per-regmap bool that tells us whether the device
has been reset, then in the case of "not reset" we will have to write
every regcache entry out to the device.  Even the ones that weren't
touched while in cache_only mode.  This makes the "not reset" case
much less efficient than the "reset" case.

Maybe that's good enough for most purposes.  It's no worse than what
my original patch submission did, anyway.

BTW, any preferences on naming for the bool or for the renamed
mark_dirty function?

>> i.e. regcache_sync() finds a register value marked "present".  How do
>> we know whether we need to write it back to the hardware?  For the
>> special case of "cached non default register values immediately after
>> a HW reset" you can mostly figure this out, but if there was no HW
>> reset how do we know which entries changed while the HW was
>> inaccessible?
>
> In the first instance do we care?

I'm not sure I understand the question.

>> > I'm not suggesting that we do anything based on the presence of a cache
>> > entry, I'm suggesting that we could avoid having to ever cache values
>> > that never get referenced on a system (which can be a lot of them for
>> > common use cases) saving us memory.
>
>> This seems to be solving a different problem.  It sounds like you are
>> more worried about regcache_sync() writing back lots of default values
>> for registers that were never touched, than performing unnecessary
>> writes to a few (actively used) registers that weren't changed while
>> we were in cache_only mode.  Is that accurate?
>
> No.  This is nothing to do with sync, it's just something that might be
> nice.

Thanks, that clarifies things.  I was not aware that other drivers
even had an issue with excessively large regcache rbtrees, as my
reg_defaults list is short.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2 1/4] regmap: cache: Add "was_reset" argument to regcache_sync_region()

2015-04-29 Thread Kevin Cernekee
On Wed, Apr 29, 2015 at 3:40 AM, Mark Brown  wrote:
> On Tue, Apr 28, 2015 at 09:58:48PM -0700, Kevin Cernekee wrote:
>> On Sat, Apr 25, 2015 at 4:32 AM, Mark Brown  wrote:
>
>> > What we should be doing here is providing a way for users to tell regmap
>> > if they've reset the register map and actually we already have that
>> > interface, it's just not got the best name - regcache_mark_dirty() is
>> > effectively it since there's really not a lot of other reasons why a
>> > driver would need to mark the cache as dirty.  We're just not handling
>
>> 1) How do we tell the difference between "regcache contains a
>> non-default value that correctly reflects the hardware register
>> contents" versus "regcache contains a non-default value that is
>> waiting to be written when we exit cache_only mode"?
>
> Like I said above we can tell if the hardware was reset because
> mark_dirty() is called.

That covers the public API, but I do not understand how you intended
for this data to be stored in the rbtree if the use of a dirty bitmask
is discouraged.

i.e. regcache_sync() finds a register value marked "present".  How do
we know whether we need to write it back to the hardware?  For the
special case of "cached non default register values immediately after
a HW reset" you can mostly figure this out, but if there was no HW
reset how do we know which entries changed while the HW was
inaccessible?

> I'm not suggesting that we do anything based on the presence of a cache
> entry, I'm suggesting that we could avoid having to ever cache values
> that never get referenced on a system (which can be a lot of them for
> common use cases) saving us memory.

This seems to be solving a different problem.  It sounds like you are
more worried about regcache_sync() writing back lots of default values
for registers that were never touched, than performing unnecessary
writes to a few (actively used) registers that weren't changed while
we were in cache_only mode.  Is that accurate?

FWIW, in the current iteration of the tas571x driver, there are few if
any registers that meet this criteria.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2 1/4] regmap: cache: Add was_reset argument to regcache_sync_region()

2015-04-29 Thread Kevin Cernekee
On Wed, Apr 29, 2015 at 9:46 AM, Mark Brown broo...@kernel.org wrote:
 On Wed, Apr 29, 2015 at 07:13:27AM -0700, Kevin Cernekee wrote:
 On Wed, Apr 29, 2015 at 3:40 AM, Mark Brown broo...@kernel.org wrote:

  Like I said above we can tell if the hardware was reset because
  mark_dirty() is called.

 That covers the public API, but I do not understand how you intended
 for this data to be stored in the rbtree if the use of a dirty bitmask
 is discouraged.

 We just need a single boolean?

Right, so if we add a per-regmap bool that tells us whether the device
has been reset, then in the case of not reset we will have to write
every regcache entry out to the device.  Even the ones that weren't
touched while in cache_only mode.  This makes the not reset case
much less efficient than the reset case.

Maybe that's good enough for most purposes.  It's no worse than what
my original patch submission did, anyway.

BTW, any preferences on naming for the bool or for the renamed
mark_dirty function?

 i.e. regcache_sync() finds a register value marked present.  How do
 we know whether we need to write it back to the hardware?  For the
 special case of cached non default register values immediately after
 a HW reset you can mostly figure this out, but if there was no HW
 reset how do we know which entries changed while the HW was
 inaccessible?

 In the first instance do we care?

I'm not sure I understand the question.

  I'm not suggesting that we do anything based on the presence of a cache
  entry, I'm suggesting that we could avoid having to ever cache values
  that never get referenced on a system (which can be a lot of them for
  common use cases) saving us memory.

 This seems to be solving a different problem.  It sounds like you are
 more worried about regcache_sync() writing back lots of default values
 for registers that were never touched, than performing unnecessary
 writes to a few (actively used) registers that weren't changed while
 we were in cache_only mode.  Is that accurate?

 No.  This is nothing to do with sync, it's just something that might be
 nice.

Thanks, that clarifies things.  I was not aware that other drivers
even had an issue with excessively large regcache rbtrees, as my
reg_defaults list is short.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2 1/4] regmap: cache: Add was_reset argument to regcache_sync_region()

2015-04-29 Thread Kevin Cernekee
On Wed, Apr 29, 2015 at 3:40 AM, Mark Brown broo...@kernel.org wrote:
 On Tue, Apr 28, 2015 at 09:58:48PM -0700, Kevin Cernekee wrote:
 On Sat, Apr 25, 2015 at 4:32 AM, Mark Brown broo...@kernel.org wrote:

  What we should be doing here is providing a way for users to tell regmap
  if they've reset the register map and actually we already have that
  interface, it's just not got the best name - regcache_mark_dirty() is
  effectively it since there's really not a lot of other reasons why a
  driver would need to mark the cache as dirty.  We're just not handling

 1) How do we tell the difference between regcache contains a
 non-default value that correctly reflects the hardware register
 contents versus regcache contains a non-default value that is
 waiting to be written when we exit cache_only mode?

 Like I said above we can tell if the hardware was reset because
 mark_dirty() is called.

That covers the public API, but I do not understand how you intended
for this data to be stored in the rbtree if the use of a dirty bitmask
is discouraged.

i.e. regcache_sync() finds a register value marked present.  How do
we know whether we need to write it back to the hardware?  For the
special case of cached non default register values immediately after
a HW reset you can mostly figure this out, but if there was no HW
reset how do we know which entries changed while the HW was
inaccessible?

 I'm not suggesting that we do anything based on the presence of a cache
 entry, I'm suggesting that we could avoid having to ever cache values
 that never get referenced on a system (which can be a lot of them for
 common use cases) saving us memory.

This seems to be solving a different problem.  It sounds like you are
more worried about regcache_sync() writing back lots of default values
for registers that were never touched, than performing unnecessary
writes to a few (actively used) registers that weren't changed while
we were in cache_only mode.  Is that accurate?

FWIW, in the current iteration of the tas571x driver, there are few if
any registers that meet this criteria.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2 1/4] regmap: cache: Add "was_reset" argument to regcache_sync_region()

2015-04-28 Thread Kevin Cernekee
On Sat, Apr 25, 2015 at 4:32 AM, Mark Brown  wrote:
> On Fri, Apr 24, 2015 at 03:36:45PM -0700, Kevin Cernekee wrote:
>
>> index 116655d92269..ece122a6fdeb 100644
>> --- a/include/linux/regmap.h
>> +++ b/include/linux/regmap.h
>> @@ -438,7 +438,7 @@ bool regmap_can_raw_write(struct regmap *map);
>>
>>  int regcache_sync(struct regmap *map);
>>  int regcache_sync_region(struct regmap *map, unsigned int min,
>> -  unsigned int max);
>> +  unsigned int max, bool was_reset);
>
> This seems pretty ugly - both the fact that we're changing the signature
> of the function and the naming of the argument feel inelegant.  The
> point isn't if the device has been reset, the point is if the device
> currently has the default register values or not, and this means that
> the user is responsible for tracking that state until the next time it
> does the sync.  That may be immediately like in your case but there's no
> reason that has to be the case.  The fact that we're passing in
> something called "is_reset" which sounds like a state value for the
> register map is a bit of a warning sign here.
>
> What we should be doing here is providing a way for users to tell regmap
> if they've reset the register map and actually we already have that
> interface, it's just not got the best name - regcache_mark_dirty() is
> effectively it since there's really not a lot of other reasons why a
> driver would need to mark the cache as dirty.  We're just not handling
> it properly.  What we should do instead is to keep the interface as it
> is for now and make it behave in a more expected fashion so that if the
> cache is explicitly marked dirty we assume that the hardware is in the
> default state and otherwise we don't.
>
> Ideally what we'd do is both improve the naming of mark_dirty() (though
> that's API churn which is nasty) and arrange for rbtree to cache the
> default values lazily, that way the only things in the cache will be
> things that have been explicitly changed (we will still want default
> checking but it makes life easier and means we don't end up having to do
> a full writeout for cases where things have been put into cache mode
> without a reset).

Hi Mark,

I started prototyping this, but ran into a couple of issues:

1) How do we tell the difference between "regcache contains a
non-default value that correctly reflects the hardware register
contents" versus "regcache contains a non-default value that is
waiting to be written when we exit cache_only mode"?

2) Does that also mean that we should store default values in the
rbtree if they are part of a deferred cache_only write, but not store
them if the write went through to the hardware?

3) If we're caching the default values lazily, does that mean that
every regcache read would incur both an rbtree lookup and a bsearch of
the reg_defaults array?

4) If "the only things in the cache will be things that have been
explicitly changed," that could impact the semantics of
regcache_drop_region().  Which fortunately has no users.

Seems like it would be more straightforward just to add an
rbnode->dirty bitmask alongside rbnode->cache_present, rather than
trying to infer the hardware state from the presence/absence of the
cache entry.  Knowing whether each individual register is out of sync
with the hardware lets us avoid unnecessary writes in both situations:
full reset, and temporary loss of register access.

What do you think?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] MIPS: BMIPS: Delete unused Kconfig symbol

2015-04-28 Thread Kevin Cernekee
This was left over from an earlier iteration of the BMIPS irqchip changes.
It doesn't actually have an effect, so let's nuke it.

Reported-by: Valentin Rothberg 
Signed-off-by: Kevin Cernekee 
---


Ralf - could you please pull this for 4.1?


 arch/mips/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f5016656494f..19e5d40fdf40 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -147,7 +147,6 @@ config BMIPS_GENERIC
select BCM7120_L2_IRQ
select BRCMSTB_L2_IRQ
select IRQ_CPU
-   select RAW_IRQ_ACCESSORS
select DMA_NONCOHERENT
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2 1/4] regmap: cache: Add was_reset argument to regcache_sync_region()

2015-04-28 Thread Kevin Cernekee
On Sat, Apr 25, 2015 at 4:32 AM, Mark Brown broo...@kernel.org wrote:
 On Fri, Apr 24, 2015 at 03:36:45PM -0700, Kevin Cernekee wrote:

 index 116655d92269..ece122a6fdeb 100644
 --- a/include/linux/regmap.h
 +++ b/include/linux/regmap.h
 @@ -438,7 +438,7 @@ bool regmap_can_raw_write(struct regmap *map);

  int regcache_sync(struct regmap *map);
  int regcache_sync_region(struct regmap *map, unsigned int min,
 -  unsigned int max);
 +  unsigned int max, bool was_reset);

 This seems pretty ugly - both the fact that we're changing the signature
 of the function and the naming of the argument feel inelegant.  The
 point isn't if the device has been reset, the point is if the device
 currently has the default register values or not, and this means that
 the user is responsible for tracking that state until the next time it
 does the sync.  That may be immediately like in your case but there's no
 reason that has to be the case.  The fact that we're passing in
 something called is_reset which sounds like a state value for the
 register map is a bit of a warning sign here.

 What we should be doing here is providing a way for users to tell regmap
 if they've reset the register map and actually we already have that
 interface, it's just not got the best name - regcache_mark_dirty() is
 effectively it since there's really not a lot of other reasons why a
 driver would need to mark the cache as dirty.  We're just not handling
 it properly.  What we should do instead is to keep the interface as it
 is for now and make it behave in a more expected fashion so that if the
 cache is explicitly marked dirty we assume that the hardware is in the
 default state and otherwise we don't.

 Ideally what we'd do is both improve the naming of mark_dirty() (though
 that's API churn which is nasty) and arrange for rbtree to cache the
 default values lazily, that way the only things in the cache will be
 things that have been explicitly changed (we will still want default
 checking but it makes life easier and means we don't end up having to do
 a full writeout for cases where things have been put into cache mode
 without a reset).

Hi Mark,

I started prototyping this, but ran into a couple of issues:

1) How do we tell the difference between regcache contains a
non-default value that correctly reflects the hardware register
contents versus regcache contains a non-default value that is
waiting to be written when we exit cache_only mode?

2) Does that also mean that we should store default values in the
rbtree if they are part of a deferred cache_only write, but not store
them if the write went through to the hardware?

3) If we're caching the default values lazily, does that mean that
every regcache read would incur both an rbtree lookup and a bsearch of
the reg_defaults array?

4) If the only things in the cache will be things that have been
explicitly changed, that could impact the semantics of
regcache_drop_region().  Which fortunately has no users.

Seems like it would be more straightforward just to add an
rbnode-dirty bitmask alongside rbnode-cache_present, rather than
trying to infer the hardware state from the presence/absence of the
cache entry.  Knowing whether each individual register is out of sync
with the hardware lets us avoid unnecessary writes in both situations:
full reset, and temporary loss of register access.

What do you think?
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] MIPS: BMIPS: Delete unused Kconfig symbol

2015-04-28 Thread Kevin Cernekee
This was left over from an earlier iteration of the BMIPS irqchip changes.
It doesn't actually have an effect, so let's nuke it.

Reported-by: Valentin Rothberg valentinrothb...@gmail.com
Signed-off-by: Kevin Cernekee cerne...@chromium.org
---


Ralf - could you please pull this for 4.1?


 arch/mips/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f5016656494f..19e5d40fdf40 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -147,7 +147,6 @@ config BMIPS_GENERIC
select BCM7120_L2_IRQ
select BRCMSTB_L2_IRQ
select IRQ_CPU
-   select RAW_IRQ_ACCESSORS
select DMA_NONCOHERENT
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2 1/4] regmap: cache: Add "was_reset" argument to regcache_sync_region()

2015-04-24 Thread Kevin Cernekee
On Fri, Apr 24, 2015 at 3:36 PM, Kevin Cernekee  wrote:
> regcache_sync() and regcache_sync_region() currently assume that the
> hardware has just emerged from a clean reset, and that all registers are
> in their default states.  But that isn't the only possibility; the device
> may have been in a different state in which the registers were
> inaccessible but have retained their contents, e.g. clock gating.
>
> So we will extend the more versatile of the two functions,
> regcache_sync_region(), to let the caller decide what assumptions should
> be made.
>
> One driver that can benefit from this is adau1977, which has hacks to
> overwrite the registers that regcache_sync() might have missed.  Also,
> the powerdown pin on tas571x does not reset the register contents either,
> so a similar feature will be required by that driver.
>
> This commit just adds the new argument by changing the function
> declarations and call sites, but doesn't wire it up yet.

The last two lines of the changelog were inadvertently carried over
from an older version of the patch, and should be deleted.  Will fix
in V3.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 2/4] ASoC: tas571x: Add DT binding document

2015-04-24 Thread Kevin Cernekee
Document the bindings for the soon-to-be-added tas571x driver.

Signed-off-by: Kevin Cernekee 
---
 .../devicetree/bindings/sound/tas571x.txt  | 41 ++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt

diff --git a/Documentation/devicetree/bindings/sound/tas571x.txt 
b/Documentation/devicetree/bindings/sound/tas571x.txt
new file mode 100644
index ..0ac31d8d5ac4
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tas571x.txt
@@ -0,0 +1,41 @@
+Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers
+
+The codec is controlled through an I2C interface.  It also has two other
+signals that can be wired up to GPIOs: reset (strongly recommended), and
+powerdown (optional).
+
+Required properties:
+
+- compatible: "ti,tas5711", "ti,tas5717", or "ti,tas5719"
+- reg: The I2C address of the device
+- #sound-dai-cells: must be equal to 0
+
+Optional properties:
+
+- reset-gpios: GPIO specifier for the TAS571x's active low reset line
+- pdn-gpios: GPIO specifier for the TAS571x's active low powerdown line
+- clocks: clock phandle for the MCLK input
+- clock-names: should be "mclk"
+- AVDD-supply: regulator phandle for the AVDD supply (all chips)
+- DVDD-supply: regulator phandle for the DVDD supply (all chips)
+- HPVDD-supply: regulator phandle for the HPVDD supply (5717/5719)
+- PVDD_AB-supply: regulator phandle for the PVDD_AB supply (5717/5719)
+- PVDD_CD-supply: regulator phandle for the PVDD_CD supply (5717/5719)
+- PVDD_A-supply: regulator phandle for the PVDD_A supply (5711)
+- PVDD_B-supply: regulator phandle for the PVDD_B supply (5711)
+- PVDD_C-supply: regulator phandle for the PVDD_C supply (5711)
+- PVDD_D-supply: regulator phandle for the PVDD_D supply (5711)
+
+Example:
+
+   tas5717: audio-codec@2a {
+   compatible = "ti,tas5717";
+   reg = <0x2a>;
+   #sound-dai-cells = <0>;
+
+   reset-gpios = < 1 GPIO_ACTIVE_LOW>;
+   pdn-gpios = < 2 GPIO_ACTIVE_LOW>;
+
+   clocks = <_core CLK_I2S>;
+   clock-names = "mclk";
+   };
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 4/4] MAINTAINERS: Add entry for tas571x ASoC codec driver

2015-04-24 Thread Kevin Cernekee
Add self as maintainer for the new driver.

Signed-off-by: Kevin Cernekee 
---
 MAINTAINERS | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ea0001760035..15153fc37cc4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9878,6 +9878,12 @@ L:   net...@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/ti/netcp*
 
+TI TAS571X FAMILY ASoC CODEC DRIVER
+M: Kevin Cernekee 
+L: alsa-de...@alsa-project.org (moderated for non-subscribers)
+S: Odd Fixes
+F: sound/soc/codecs/tas571x*
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M: Peter Ujfalusi 
 L: alsa-de...@alsa-project.org (moderated for non-subscribers)
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 1/4] regmap: cache: Add "was_reset" argument to regcache_sync_region()

2015-04-24 Thread Kevin Cernekee
regcache_sync() and regcache_sync_region() currently assume that the
hardware has just emerged from a clean reset, and that all registers are
in their default states.  But that isn't the only possibility; the device
may have been in a different state in which the registers were
inaccessible but have retained their contents, e.g. clock gating.

So we will extend the more versatile of the two functions,
regcache_sync_region(), to let the caller decide what assumptions should
be made.

One driver that can benefit from this is adau1977, which has hacks to
overwrite the registers that regcache_sync() might have missed.  Also,
the powerdown pin on tas571x does not reset the register contents either,
so a similar feature will be required by that driver.

This commit just adds the new argument by changing the function
declarations and call sites, but doesn't wire it up yet.

Signed-off-by: Kevin Cernekee 
---
 drivers/base/regmap/internal.h|  5 ++-
 drivers/base/regmap/regcache-lzo.c|  2 +-
 drivers/base/regmap/regcache-rbtree.c |  5 ++-
 drivers/base/regmap/regcache.c| 75 ---
 drivers/media/radio/radio-si476x.c| 18 ++---
 drivers/mfd/wm8994-core.c |  5 ++-
 include/linux/regmap.h|  4 +-
 include/sound/hda_regmap.h|  3 +-
 sound/soc/codecs/wm8962.c |  3 +-
 9 files changed, 72 insertions(+), 48 deletions(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index a13587b5c2be..89dfefeb168e 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -155,7 +155,8 @@ struct regcache_ops {
 #endif
int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
-   int (*sync)(struct regmap *map, unsigned int min, unsigned int max);
+   int (*sync)(struct regmap *map, unsigned int min, unsigned int max,
+   bool was_reset);
int (*drop)(struct regmap *map, unsigned int min, unsigned int max);
 };
 
@@ -215,7 +216,7 @@ int regcache_sync(struct regmap *map);
 int regcache_sync_block(struct regmap *map, void *block,
unsigned long *cache_present,
unsigned int block_base, unsigned int start,
-   unsigned int end);
+   unsigned int end, bool was_reset);
 
 static inline const void *regcache_get_val_addr(struct regmap *map,
const void *base,
diff --git a/drivers/base/regmap/regcache-lzo.c 
b/drivers/base/regmap/regcache-lzo.c
index 2d53f6f138e1..52ed0d03ce69 100644
--- a/drivers/base/regmap/regcache-lzo.c
+++ b/drivers/base/regmap/regcache-lzo.c
@@ -332,7 +332,7 @@ out:
 }
 
 static int regcache_lzo_sync(struct regmap *map, unsigned int min,
-unsigned int max)
+unsigned int max, bool was_reset)
 {
struct regcache_lzo_ctx **lzo_blocks;
unsigned int val;
diff --git a/drivers/base/regmap/regcache-rbtree.c 
b/drivers/base/regmap/regcache-rbtree.c
index 81751a49d8bf..8fc1727e635c 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -445,7 +445,7 @@ static int regcache_rbtree_write(struct regmap *map, 
unsigned int reg,
 }
 
 static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
-   unsigned int max)
+   unsigned int max, bool was_reset)
 {
struct regcache_rbtree_ctx *rbtree_ctx;
struct rb_node *node;
@@ -477,7 +477,8 @@ static int regcache_rbtree_sync(struct regmap *map, 
unsigned int min,
 
ret = regcache_sync_block(map, rbnode->block,
  rbnode->cache_present,
- rbnode->base_reg, start, end);
+ rbnode->base_reg, start, end,
+ was_reset);
if (ret != 0)
return ret;
}
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 7eb7b3b98794..d27b45f50497 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -250,7 +250,7 @@ int regcache_write(struct regmap *map,
 }
 
 static int regcache_default_sync(struct regmap *map, unsigned int min,
-unsigned int max)
+unsigned int max, bool was_reset)
 {
unsigned int reg;
 
@@ -266,10 +266,12 @@ static int regcache_default_sync(struct regmap *map, 
unsigned int min,
if (ret)
return ret;
 
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, reg);
-   if (ret >= 0 && val == map

[PATCH V2 3/4] ASoC: tas571x: New driver for TI TAS571x power amplifiers

2015-04-24 Thread Kevin Cernekee
Introduce a new codec driver for the Texas Instruments
TAS5711/TAS5717/TAS5719 power amplifier chips.  These chips are typically
used to take an I2S digital audio input and drive 10-20W into a pair of
speakers.

Signed-off-by: Kevin Cernekee 
---
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 521 +
 sound/soc/codecs/tas571x.h |  33 +++
 4 files changed, 561 insertions(+)
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 061c46587628..befff910d71a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TAS2552 if I2C
select SND_SOC_TAS5086 if I2C
+   select SND_SOC_TAS571X if I2C
select SND_SOC_TFA9879 if I2C
select SND_SOC_TLV320AIC23_I2C if I2C
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
@@ -611,6 +612,10 @@ config SND_SOC_TAS5086
tristate "Texas Instruments TAS5086 speaker amplifier"
depends on I2C
 
+config SND_SOC_TAS571X
+   tristate "Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers"
+   depends on I2C
+
 config SND_SOC_TFA9879
tristate "NXP Semiconductors TFA9879 amplifier"
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index abe2d7edf65c..3dcf5ac85e89 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -106,6 +106,7 @@ snd-soc-sta350-objs := sta350.o
 snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tas5086-objs := tas5086.o
+snd-soc-tas571x-objs := tas571x.o
 snd-soc-tfa9879-objs := tfa9879.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
@@ -288,6 +289,7 @@ obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TAS2552)  += snd-soc-tas2552.o
 obj-$(CONFIG_SND_SOC_TAS5086)  += snd-soc-tas5086.o
+obj-$(CONFIG_SND_SOC_TAS571X)  += snd-soc-tas571x.o
 obj-$(CONFIG_SND_SOC_TFA9879)  += snd-soc-tfa9879.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)  += snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C)  += snd-soc-tlv320aic23-i2c.o
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
new file mode 100644
index ..08e358638f2e
--- /dev/null
+++ b/sound/soc/codecs/tas571x.c
@@ -0,0 +1,521 @@
+/*
+ * TAS571x amplifier audio driver
+ *
+ * Copyright (C) 2015 Google, Inc.
+ * Copyright (c) 2013 Daniel Mack 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "tas571x.h"
+
+#define TAS571X_MAX_SUPPLIES   6
+
+struct tas571x_chip {
+   const char  *const *supply_names;
+   int num_supply_names;
+   const struct snd_kcontrol_new   *controls;
+   int num_controls;
+   const struct regmap_config  *regmap_config;
+   int vol_reg_size;
+};
+
+struct tas571x_private {
+   const struct tas571x_chip   *chip;
+   struct regmap   *regmap;
+   struct regulator_bulk_data  supplies[TAS571X_MAX_SUPPLIES];
+   struct clk  *mclk;
+   unsigned intformat;
+   struct gpio_desc*reset_gpio;
+   struct gpio_desc*pdn_gpio;
+   struct snd_soc_codec_driver codec_driver;
+};
+
+static int tas571x_register_size(struct tas571x_private *priv, unsigned int 
reg)
+{
+   switch (reg) {
+   case TAS571X_MVOL_REG:
+   case TAS571X_CH1_VOL_REG:
+   case TAS571X_CH2_VOL_REG:
+   return priv->chip->vol_reg_size;
+   default:
+   return 1;
+   }
+}
+
+static int tas571x_reg_write(void *context, unsigned int reg,
+unsigned int value)
+{
+   struct i2c_client *client = context;
+   struct tas571x_private *priv = i2c_get_clientdata(client);
+   unsigned int i, size;
+   uint8_t buf[5];
+   int ret;
+
+   size = tas571x_register_size(priv, reg);
+   buf[0] = reg;
+
+   for (i = size; i >= 1; --i) {
+   buf[i] = value;
+   value >>= 8;
+   }
+
+   ret = i2c_master_send(client, buf, size + 1);
+   if (ret == size + 1)
+   return 

[PATCH V2 0/4] tas571x amplifier driver

2015-04-24 Thread Kevin Cernekee
V1->V2:

 - Incorporate changes from review feedback

 - Change GPIOs to active low

 - Create a tas571x_chip struct to capture the growing list of differences
   between 5711 and 5717/5719

 - Add register defaults for each chip

 - Extend regcache_sync_region() to allow it to sync with hardware registers
   that don't contain their power-on-reset values


Kevin Cernekee (4):
  regmap: cache: Add "was_reset" argument to regcache_sync_region()
  ASoC: tas571x: Add DT binding document
  ASoC: tas571x: New driver for TI TAS571x power amplifiers
  MAINTAINERS: Add entry for tas571x ASoC codec driver

 .../devicetree/bindings/sound/tas571x.txt  |  41 ++
 MAINTAINERS|   6 +
 drivers/base/regmap/internal.h |   5 +-
 drivers/base/regmap/regcache-lzo.c |   2 +-
 drivers/base/regmap/regcache-rbtree.c  |   5 +-
 drivers/base/regmap/regcache.c |  75 +--
 drivers/media/radio/radio-si476x.c |  18 +-
 drivers/mfd/wm8994-core.c  |   5 +-
 include/linux/regmap.h |   4 +-
 include/sound/hda_regmap.h |   3 +-
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 521 +
 sound/soc/codecs/tas571x.h |  33 ++
 sound/soc/codecs/wm8962.c  |   3 +-
 15 files changed, 680 insertions(+), 48 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] ASoC: tas571x: New driver for TI TAS571x power amplifiers

2015-04-24 Thread Kevin Cernekee
On Fri, Apr 24, 2015 at 2:28 AM, Mark Brown  wrote:
> On Thu, Apr 23, 2015 at 05:47:49PM -0700, Kevin Cernekee wrote:
>
>> This is mostly working OK, but regcache_sync() assumes that the
>> hardware registers have been reset back to the default values.  The
>> "pdn" GPIO doesn't actually reset the state of the tas571x; it just
>> makes I2C inaccessible and inhibits audio output.  So if the factory
>> default for mute is 0, corner cases like this fail:
>
> ...
>
>> Aside from unnecessarily pulsing the reset GPIO when transitioning
>> back from SND_SOC_BIAS_OFF or overriding regcache_default_sync(), can
>> you think of a way to work around this?
>
> Do you need to work around it?  If the register map is being perserved
> you don't need to sync so just don't do it - it's just that the normal
> expectation would be that power down would cause the register map to be
> reset.

How do I tell regcache to write out any updates that happened while
the hardware was inaccessible?  I see that regmap->cache_dirty is 1,
but nothing flushes it automatically when exiting cache_only mode.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/3] ASoC: tas571x: New driver for TI TAS571x power amplifiers

2015-04-24 Thread Kevin Cernekee
On Fri, Apr 24, 2015 at 2:28 AM, Mark Brown broo...@kernel.org wrote:
 On Thu, Apr 23, 2015 at 05:47:49PM -0700, Kevin Cernekee wrote:

 This is mostly working OK, but regcache_sync() assumes that the
 hardware registers have been reset back to the default values.  The
 pdn GPIO doesn't actually reset the state of the tas571x; it just
 makes I2C inaccessible and inhibits audio output.  So if the factory
 default for mute is 0, corner cases like this fail:

 ...

 Aside from unnecessarily pulsing the reset GPIO when transitioning
 back from SND_SOC_BIAS_OFF or overriding regcache_default_sync(), can
 you think of a way to work around this?

 Do you need to work around it?  If the register map is being perserved
 you don't need to sync so just don't do it - it's just that the normal
 expectation would be that power down would cause the register map to be
 reset.

How do I tell regcache to write out any updates that happened while
the hardware was inaccessible?  I see that regmap-cache_dirty is 1,
but nothing flushes it automatically when exiting cache_only mode.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 0/4] tas571x amplifier driver

2015-04-24 Thread Kevin Cernekee
V1-V2:

 - Incorporate changes from review feedback

 - Change GPIOs to active low

 - Create a tas571x_chip struct to capture the growing list of differences
   between 5711 and 5717/5719

 - Add register defaults for each chip

 - Extend regcache_sync_region() to allow it to sync with hardware registers
   that don't contain their power-on-reset values


Kevin Cernekee (4):
  regmap: cache: Add was_reset argument to regcache_sync_region()
  ASoC: tas571x: Add DT binding document
  ASoC: tas571x: New driver for TI TAS571x power amplifiers
  MAINTAINERS: Add entry for tas571x ASoC codec driver

 .../devicetree/bindings/sound/tas571x.txt  |  41 ++
 MAINTAINERS|   6 +
 drivers/base/regmap/internal.h |   5 +-
 drivers/base/regmap/regcache-lzo.c |   2 +-
 drivers/base/regmap/regcache-rbtree.c  |   5 +-
 drivers/base/regmap/regcache.c |  75 +--
 drivers/media/radio/radio-si476x.c |  18 +-
 drivers/mfd/wm8994-core.c  |   5 +-
 include/linux/regmap.h |   4 +-
 include/sound/hda_regmap.h |   3 +-
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 521 +
 sound/soc/codecs/tas571x.h |  33 ++
 sound/soc/codecs/wm8962.c  |   3 +-
 15 files changed, 680 insertions(+), 48 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 3/4] ASoC: tas571x: New driver for TI TAS571x power amplifiers

2015-04-24 Thread Kevin Cernekee
Introduce a new codec driver for the Texas Instruments
TAS5711/TAS5717/TAS5719 power amplifier chips.  These chips are typically
used to take an I2S digital audio input and drive 10-20W into a pair of
speakers.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 sound/soc/codecs/Kconfig   |   5 +
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tas571x.c | 521 +
 sound/soc/codecs/tas571x.h |  33 +++
 4 files changed, 561 insertions(+)
 create mode 100644 sound/soc/codecs/tas571x.c
 create mode 100644 sound/soc/codecs/tas571x.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 061c46587628..befff910d71a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -104,6 +104,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TAS2552 if I2C
select SND_SOC_TAS5086 if I2C
+   select SND_SOC_TAS571X if I2C
select SND_SOC_TFA9879 if I2C
select SND_SOC_TLV320AIC23_I2C if I2C
select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
@@ -611,6 +612,10 @@ config SND_SOC_TAS5086
tristate Texas Instruments TAS5086 speaker amplifier
depends on I2C
 
+config SND_SOC_TAS571X
+   tristate Texas Instruments TAS5711/TAS5717/TAS5719 power amplifiers
+   depends on I2C
+
 config SND_SOC_TFA9879
tristate NXP Semiconductors TFA9879 amplifier
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index abe2d7edf65c..3dcf5ac85e89 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -106,6 +106,7 @@ snd-soc-sta350-objs := sta350.o
 snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tas5086-objs := tas5086.o
+snd-soc-tas571x-objs := tas571x.o
 snd-soc-tfa9879-objs := tfa9879.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
@@ -288,6 +289,7 @@ obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TAS2552)  += snd-soc-tas2552.o
 obj-$(CONFIG_SND_SOC_TAS5086)  += snd-soc-tas5086.o
+obj-$(CONFIG_SND_SOC_TAS571X)  += snd-soc-tas571x.o
 obj-$(CONFIG_SND_SOC_TFA9879)  += snd-soc-tfa9879.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)  += snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C)  += snd-soc-tlv320aic23-i2c.o
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
new file mode 100644
index ..08e358638f2e
--- /dev/null
+++ b/sound/soc/codecs/tas571x.c
@@ -0,0 +1,521 @@
+/*
+ * TAS571x amplifier audio driver
+ *
+ * Copyright (C) 2015 Google, Inc.
+ * Copyright (c) 2013 Daniel Mack zon...@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include linux/clk.h
+#include linux/delay.h
+#include linux/device.h
+#include linux/gpio/consumer.h
+#include linux/i2c.h
+#include linux/init.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/of_device.h
+#include linux/regmap.h
+#include linux/regulator/consumer.h
+#include linux/stddef.h
+#include sound/pcm_params.h
+#include sound/soc.h
+#include sound/tlv.h
+
+#include tas571x.h
+
+#define TAS571X_MAX_SUPPLIES   6
+
+struct tas571x_chip {
+   const char  *const *supply_names;
+   int num_supply_names;
+   const struct snd_kcontrol_new   *controls;
+   int num_controls;
+   const struct regmap_config  *regmap_config;
+   int vol_reg_size;
+};
+
+struct tas571x_private {
+   const struct tas571x_chip   *chip;
+   struct regmap   *regmap;
+   struct regulator_bulk_data  supplies[TAS571X_MAX_SUPPLIES];
+   struct clk  *mclk;
+   unsigned intformat;
+   struct gpio_desc*reset_gpio;
+   struct gpio_desc*pdn_gpio;
+   struct snd_soc_codec_driver codec_driver;
+};
+
+static int tas571x_register_size(struct tas571x_private *priv, unsigned int 
reg)
+{
+   switch (reg) {
+   case TAS571X_MVOL_REG:
+   case TAS571X_CH1_VOL_REG:
+   case TAS571X_CH2_VOL_REG:
+   return priv-chip-vol_reg_size;
+   default:
+   return 1;
+   }
+}
+
+static int tas571x_reg_write(void *context, unsigned int reg,
+unsigned int value)
+{
+   struct i2c_client *client = context;
+   struct tas571x_private *priv = i2c_get_clientdata(client);
+   unsigned int i, size;
+   uint8_t buf[5];
+   int ret;
+
+   size = tas571x_register_size(priv, reg);
+   buf[0] = reg;
+
+   for (i = size; i = 1

[PATCH V2 1/4] regmap: cache: Add was_reset argument to regcache_sync_region()

2015-04-24 Thread Kevin Cernekee
regcache_sync() and regcache_sync_region() currently assume that the
hardware has just emerged from a clean reset, and that all registers are
in their default states.  But that isn't the only possibility; the device
may have been in a different state in which the registers were
inaccessible but have retained their contents, e.g. clock gating.

So we will extend the more versatile of the two functions,
regcache_sync_region(), to let the caller decide what assumptions should
be made.

One driver that can benefit from this is adau1977, which has hacks to
overwrite the registers that regcache_sync() might have missed.  Also,
the powerdown pin on tas571x does not reset the register contents either,
so a similar feature will be required by that driver.

This commit just adds the new argument by changing the function
declarations and call sites, but doesn't wire it up yet.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 drivers/base/regmap/internal.h|  5 ++-
 drivers/base/regmap/regcache-lzo.c|  2 +-
 drivers/base/regmap/regcache-rbtree.c |  5 ++-
 drivers/base/regmap/regcache.c| 75 ---
 drivers/media/radio/radio-si476x.c| 18 ++---
 drivers/mfd/wm8994-core.c |  5 ++-
 include/linux/regmap.h|  4 +-
 include/sound/hda_regmap.h|  3 +-
 sound/soc/codecs/wm8962.c |  3 +-
 9 files changed, 72 insertions(+), 48 deletions(-)

diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index a13587b5c2be..89dfefeb168e 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -155,7 +155,8 @@ struct regcache_ops {
 #endif
int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
-   int (*sync)(struct regmap *map, unsigned int min, unsigned int max);
+   int (*sync)(struct regmap *map, unsigned int min, unsigned int max,
+   bool was_reset);
int (*drop)(struct regmap *map, unsigned int min, unsigned int max);
 };
 
@@ -215,7 +216,7 @@ int regcache_sync(struct regmap *map);
 int regcache_sync_block(struct regmap *map, void *block,
unsigned long *cache_present,
unsigned int block_base, unsigned int start,
-   unsigned int end);
+   unsigned int end, bool was_reset);
 
 static inline const void *regcache_get_val_addr(struct regmap *map,
const void *base,
diff --git a/drivers/base/regmap/regcache-lzo.c 
b/drivers/base/regmap/regcache-lzo.c
index 2d53f6f138e1..52ed0d03ce69 100644
--- a/drivers/base/regmap/regcache-lzo.c
+++ b/drivers/base/regmap/regcache-lzo.c
@@ -332,7 +332,7 @@ out:
 }
 
 static int regcache_lzo_sync(struct regmap *map, unsigned int min,
-unsigned int max)
+unsigned int max, bool was_reset)
 {
struct regcache_lzo_ctx **lzo_blocks;
unsigned int val;
diff --git a/drivers/base/regmap/regcache-rbtree.c 
b/drivers/base/regmap/regcache-rbtree.c
index 81751a49d8bf..8fc1727e635c 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -445,7 +445,7 @@ static int regcache_rbtree_write(struct regmap *map, 
unsigned int reg,
 }
 
 static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
-   unsigned int max)
+   unsigned int max, bool was_reset)
 {
struct regcache_rbtree_ctx *rbtree_ctx;
struct rb_node *node;
@@ -477,7 +477,8 @@ static int regcache_rbtree_sync(struct regmap *map, 
unsigned int min,
 
ret = regcache_sync_block(map, rbnode-block,
  rbnode-cache_present,
- rbnode-base_reg, start, end);
+ rbnode-base_reg, start, end,
+ was_reset);
if (ret != 0)
return ret;
}
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 7eb7b3b98794..d27b45f50497 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -250,7 +250,7 @@ int regcache_write(struct regmap *map,
 }
 
 static int regcache_default_sync(struct regmap *map, unsigned int min,
-unsigned int max)
+unsigned int max, bool was_reset)
 {
unsigned int reg;
 
@@ -266,10 +266,12 @@ static int regcache_default_sync(struct regmap *map, 
unsigned int min,
if (ret)
return ret;
 
-   /* Is this the hardware default?  If so skip. */
-   ret = regcache_lookup_reg(map, reg);
-   if (ret = 0  val == map-reg_defaults[ret].def

[PATCH V2 4/4] MAINTAINERS: Add entry for tas571x ASoC codec driver

2015-04-24 Thread Kevin Cernekee
Add self as maintainer for the new driver.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 MAINTAINERS | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ea0001760035..15153fc37cc4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9878,6 +9878,12 @@ L:   net...@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/ti/netcp*
 
+TI TAS571X FAMILY ASoC CODEC DRIVER
+M: Kevin Cernekee cerne...@chromium.org
+L: alsa-de...@alsa-project.org (moderated for non-subscribers)
+S: Odd Fixes
+F: sound/soc/codecs/tas571x*
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M: Peter Ujfalusi peter.ujfal...@ti.com
 L: alsa-de...@alsa-project.org (moderated for non-subscribers)
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 2/4] ASoC: tas571x: Add DT binding document

2015-04-24 Thread Kevin Cernekee
Document the bindings for the soon-to-be-added tas571x driver.

Signed-off-by: Kevin Cernekee cerne...@chromium.org
---
 .../devicetree/bindings/sound/tas571x.txt  | 41 ++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/tas571x.txt

diff --git a/Documentation/devicetree/bindings/sound/tas571x.txt 
b/Documentation/devicetree/bindings/sound/tas571x.txt
new file mode 100644
index ..0ac31d8d5ac4
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tas571x.txt
@@ -0,0 +1,41 @@
+Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers
+
+The codec is controlled through an I2C interface.  It also has two other
+signals that can be wired up to GPIOs: reset (strongly recommended), and
+powerdown (optional).
+
+Required properties:
+
+- compatible: ti,tas5711, ti,tas5717, or ti,tas5719
+- reg: The I2C address of the device
+- #sound-dai-cells: must be equal to 0
+
+Optional properties:
+
+- reset-gpios: GPIO specifier for the TAS571x's active low reset line
+- pdn-gpios: GPIO specifier for the TAS571x's active low powerdown line
+- clocks: clock phandle for the MCLK input
+- clock-names: should be mclk
+- AVDD-supply: regulator phandle for the AVDD supply (all chips)
+- DVDD-supply: regulator phandle for the DVDD supply (all chips)
+- HPVDD-supply: regulator phandle for the HPVDD supply (5717/5719)
+- PVDD_AB-supply: regulator phandle for the PVDD_AB supply (5717/5719)
+- PVDD_CD-supply: regulator phandle for the PVDD_CD supply (5717/5719)
+- PVDD_A-supply: regulator phandle for the PVDD_A supply (5711)
+- PVDD_B-supply: regulator phandle for the PVDD_B supply (5711)
+- PVDD_C-supply: regulator phandle for the PVDD_C supply (5711)
+- PVDD_D-supply: regulator phandle for the PVDD_D supply (5711)
+
+Example:
+
+   tas5717: audio-codec@2a {
+   compatible = ti,tas5717;
+   reg = 0x2a;
+   #sound-dai-cells = 0;
+
+   reset-gpios = gpio5 1 GPIO_ACTIVE_LOW;
+   pdn-gpios = gpio5 2 GPIO_ACTIVE_LOW;
+
+   clocks = clk_core CLK_I2S;
+   clock-names = mclk;
+   };
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2 1/4] regmap: cache: Add was_reset argument to regcache_sync_region()

2015-04-24 Thread Kevin Cernekee
On Fri, Apr 24, 2015 at 3:36 PM, Kevin Cernekee cerne...@chromium.org wrote:
 regcache_sync() and regcache_sync_region() currently assume that the
 hardware has just emerged from a clean reset, and that all registers are
 in their default states.  But that isn't the only possibility; the device
 may have been in a different state in which the registers were
 inaccessible but have retained their contents, e.g. clock gating.

 So we will extend the more versatile of the two functions,
 regcache_sync_region(), to let the caller decide what assumptions should
 be made.

 One driver that can benefit from this is adau1977, which has hacks to
 overwrite the registers that regcache_sync() might have missed.  Also,
 the powerdown pin on tas571x does not reset the register contents either,
 so a similar feature will be required by that driver.

 This commit just adds the new argument by changing the function
 declarations and call sites, but doesn't wire it up yet.

The last two lines of the changelog were inadvertently carried over
from an older version of the patch, and should be deleted.  Will fix
in V3.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


  1   2   3   4   5   6   >