--- /dev/null
+From 5a56a0b3a45dd0cc5b2f7bec6afd053a474ed9f5 Mon Sep 17 00:00:00 2001
+From: Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
+Date: Mon, 5 Sep 2016 10:20:20 +1200
+Subject: net: Don't delete routes in different VRFs
+
+From: Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
+
+commit 5a56a0b3a45dd0cc5b2f7bec6afd053a474ed9f5 upstream.
+
+When deleting an IP address from an interface, there is a clean-up of
+routes which refer to this local address. However, there was no check to
+see that the VRF matched. This meant that deletion wasn't confined to
+the VRF it should have been.
+
+To solve this, a new field has been added to fib_info to hold a table
+id. When removing fib entries corresponding to a local ip address, this
+table id is also used in the comparison.
+
+The table id is populated when the fib_info is created. This was already
+done in some places, but not in ip_rt_ioctl(). This has now been fixed.
+
+Fixes: 021dd3b8a142 ("net: Add routes to the table associated with the device")
+Acked-by: David Ahern <dsa@cumulusnetworks.com>
+Tested-by: David Ahern <dsa@cumulusnetworks.com>
+Signed-off-by: Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/net/ip_fib.h | 3 ++-
+ net/ipv4/fib_frontend.c | 3 ++-
+ net/ipv4/fib_semantics.c | 8 ++++++--
+ 3 files changed, 10 insertions(+), 4 deletions(-)
+
+--- a/include/net/ip_fib.h
++++ b/include/net/ip_fib.h
+@@ -112,6 +112,7 @@ struct fib_info {
+ unsigned char fib_scope;
+ unsigned char fib_type;
+ __be32 fib_prefsrc;
++ u32 fib_tb_id;
+ u32 fib_priority;
+ struct dst_metrics *fib_metrics;
+ #define fib_mtu fib_metrics->metrics[RTAX_MTU-1]
+@@ -320,7 +321,7 @@ void fib_flush_external(struct net *net)
+ /* Exported by fib_semantics.c */
+ int ip_fib_check_default(__be32 gw, struct net_device *dev);
+ int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force);
+-int fib_sync_down_addr(struct net *net, __be32 local);
++int fib_sync_down_addr(struct net_device *dev, __be32 local);
+ int fib_sync_up(struct net_device *dev, unsigned int nh_flags);
+ void fib_sync_mtu(struct net_device *dev, u32 orig_mtu);
+
+--- a/net/ipv4/fib_frontend.c
++++ b/net/ipv4/fib_frontend.c
+@@ -509,6 +509,7 @@ static int rtentry_to_fib_config(struct
+ if (!dev)
+ return -ENODEV;
+ cfg->fc_oif = dev->ifindex;
++ cfg->fc_table = l3mdev_fib_table(dev);
+ if (colon) {
+ struct in_ifaddr *ifa;
+ struct in_device *in_dev = __in_dev_get_rtnl(dev);
+@@ -1034,7 +1035,7 @@ no_promotions:
+ * First of all, we scan fib_info list searching
+ * for stray nexthop entries, then ignite fib_flush.
+ */
+- if (fib_sync_down_addr(dev_net(dev), ifa->ifa_local))
++ if (fib_sync_down_addr(dev, ifa->ifa_local))
+ fib_flush(dev_net(dev));
+ }
+ }
+--- a/net/ipv4/fib_semantics.c
++++ b/net/ipv4/fib_semantics.c
+@@ -1069,6 +1069,7 @@ struct fib_info *fib_create_info(struct
+ fi->fib_priority = cfg->fc_priority;
+ fi->fib_prefsrc = cfg->fc_prefsrc;
+ fi->fib_type = cfg->fc_type;
++ fi->fib_tb_id = cfg->fc_table;
+
+ fi->fib_nhs = nhs;
+ change_nexthops(fi) {
+@@ -1352,18 +1353,21 @@ nla_put_failure:
+ * referring to it.
+ * - device went down -> we must shutdown all nexthops going via it.
+ */
+-int fib_sync_down_addr(struct net *net, __be32 local)
++int fib_sync_down_addr(struct net_device *dev, __be32 local)
+ {
+ int ret = 0;
+ unsigned int hash = fib_laddr_hashfn(local);
+ struct hlist_head *head = &fib_info_laddrhash[hash];
++ struct net *net = dev_net(dev);
++ int tb_id = l3mdev_fib_table(dev);
+ struct fib_info *fi;
+
+ if (!fib_info_laddrhash || local == 0)
+ return 0;
+
+ hlist_for_each_entry(fi, head, fib_lhash) {
+- if (!net_eq(fi->fib_net, net))
++ if (!net_eq(fi->fib_net, net) ||
++ fi->fib_tb_id != tb_id)
+ continue;
+ if (fi->fib_prefsrc == local) {
+ fi->fib_flags |= RTNH_F_DEAD;
--- /dev/null
+From 9ab179d83b4e31ea277a123492e419067c2f129a Mon Sep 17 00:00:00 2001
+From: David Ahern <dsa@cumulusnetworks.com>
+Date: Thu, 7 Apr 2016 11:10:06 -0700
+Subject: net: vrf: Fix dst reference counting
+
+From: David Ahern <dsa@cumulusnetworks.com>
+
+commit 9ab179d83b4e31ea277a123492e419067c2f129a upstream.
+
+Vivek reported a kernel exception deleting a VRF with an active
+connection through it. The root cause is that the socket has a cached
+reference to a dst that is destroyed. Converting the dst_destroy to
+dst_release and letting proper reference counting kick in does not
+work as the dst has a reference to the device which needs to be released
+as well.
+
+I talked to Hannes about this at netdev and he pointed out the ipv4 and
+ipv6 dst handling has dst_ifdown for just this scenario. Rather than
+continuing with the reinvented dst wheel in VRF just remove it and
+leverage the ipv4 and ipv6 versions.
+
+Fixes: 193125dbd8eb2 ("net: Introduce VRF device driver")
+Fixes: 35402e3136634 ("net: Add IPv6 support to VRF device")
+
+Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/vrf.c | 177 ++++--------------------------------------------
+ include/net/ip6_route.h | 3
+ include/net/route.h | 3
+ net/ipv4/route.c | 7 +
+ net/ipv6/route.c | 7 +
+ 5 files changed, 30 insertions(+), 167 deletions(-)
+
+--- a/drivers/net/vrf.c
++++ b/drivers/net/vrf.c
+@@ -71,41 +71,6 @@ struct pcpu_dstats {
+ struct u64_stats_sync syncp;
+ };
+
+-static struct dst_entry *vrf_ip_check(struct dst_entry *dst, u32 cookie)
+-{
+- return dst;
+-}
+-
+-static int vrf_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
+-{
+- return ip_local_out(net, sk, skb);
+-}
+-
+-static unsigned int vrf_v4_mtu(const struct dst_entry *dst)
+-{
+- /* TO-DO: return max ethernet size? */
+- return dst->dev->mtu;
+-}
+-
+-static void vrf_dst_destroy(struct dst_entry *dst)
+-{
+- /* our dst lives forever - or until the device is closed */
+-}
+-
+-static unsigned int vrf_default_advmss(const struct dst_entry *dst)
+-{
+- return 65535 - 40;
+-}
+-
+-static struct dst_ops vrf_dst_ops = {
+- .family = AF_INET,
+- .local_out = vrf_ip_local_out,
+- .check = vrf_ip_check,
+- .mtu = vrf_v4_mtu,
+- .destroy = vrf_dst_destroy,
+- .default_advmss = vrf_default_advmss,
+-};
+-
+ /* neighbor handling is done with actual device; do not want
+ * to flip skb->dev for those ndisc packets. This really fails
+ * for multiple next protocols (e.g., NEXTHDR_HOP). But it is
+@@ -363,46 +328,6 @@ static netdev_tx_t vrf_xmit(struct sk_bu
+ }
+
+ #if IS_ENABLED(CONFIG_IPV6)
+-static struct dst_entry *vrf_ip6_check(struct dst_entry *dst, u32 cookie)
+-{
+- return dst;
+-}
+-
+-static struct dst_ops vrf_dst_ops6 = {
+- .family = AF_INET6,
+- .local_out = ip6_local_out,
+- .check = vrf_ip6_check,
+- .mtu = vrf_v4_mtu,
+- .destroy = vrf_dst_destroy,
+- .default_advmss = vrf_default_advmss,
+-};
+-
+-static int init_dst_ops6_kmem_cachep(void)
+-{
+- vrf_dst_ops6.kmem_cachep = kmem_cache_create("vrf_ip6_dst_cache",
+- sizeof(struct rt6_info),
+- 0,
+- SLAB_HWCACHE_ALIGN,
+- NULL);
+-
+- if (!vrf_dst_ops6.kmem_cachep)
+- return -ENOMEM;
+-
+- return 0;
+-}
+-
+-static void free_dst_ops6_kmem_cachep(void)
+-{
+- kmem_cache_destroy(vrf_dst_ops6.kmem_cachep);
+-}
+-
+-static int vrf_input6(struct sk_buff *skb)
+-{
+- skb->dev->stats.rx_errors++;
+- kfree_skb(skb);
+- return 0;
+-}
+-
+ /* modelled after ip6_finish_output2 */
+ static int vrf_finish_output6(struct net *net, struct sock *sk,
+ struct sk_buff *skb)
+@@ -445,67 +370,34 @@ static int vrf_output6(struct net *net,
+ !(IP6CB(skb)->flags & IP6SKB_REROUTED));
+ }
+
+-static void vrf_rt6_destroy(struct net_vrf *vrf)
++static void vrf_rt6_release(struct net_vrf *vrf)
+ {
+- dst_destroy(&vrf->rt6->dst);
+- free_percpu(vrf->rt6->rt6i_pcpu);
++ dst_release(&vrf->rt6->dst);
+ vrf->rt6 = NULL;
+ }
+
+ static int vrf_rt6_create(struct net_device *dev)
+ {
+ struct net_vrf *vrf = netdev_priv(dev);
+- struct dst_entry *dst;
++ struct net *net = dev_net(dev);
+ struct rt6_info *rt6;
+- int cpu;
+ int rc = -ENOMEM;
+
+- rt6 = dst_alloc(&vrf_dst_ops6, dev, 0,
+- DST_OBSOLETE_NONE,
+- (DST_HOST | DST_NOPOLICY | DST_NOXFRM));
++ rt6 = ip6_dst_alloc(net, dev,
++ DST_HOST | DST_NOPOLICY | DST_NOXFRM | DST_NOCACHE);
+ if (!rt6)
+ goto out;
+
+- dst = &rt6->dst;
+-
+- rt6->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_KERNEL);
+- if (!rt6->rt6i_pcpu) {
+- dst_destroy(dst);
+- goto out;
+- }
+- for_each_possible_cpu(cpu) {
+- struct rt6_info **p = per_cpu_ptr(rt6->rt6i_pcpu, cpu);
+- *p = NULL;
+- }
+-
+- memset(dst + 1, 0, sizeof(*rt6) - sizeof(*dst));
+-
+- INIT_LIST_HEAD(&rt6->rt6i_siblings);
+- INIT_LIST_HEAD(&rt6->rt6i_uncached);
+-
+- rt6->dst.input = vrf_input6;
+ rt6->dst.output = vrf_output6;
+-
+- rt6->rt6i_table = fib6_get_table(dev_net(dev), vrf->tb_id);
+-
+- atomic_set(&rt6->dst.__refcnt, 2);
+-
++ rt6->rt6i_table = fib6_get_table(net, vrf->tb_id);
++ dst_hold(&rt6->dst);
+ vrf->rt6 = rt6;
+ rc = 0;
+ out:
+ return rc;
+ }
+ #else
+-static int init_dst_ops6_kmem_cachep(void)
+-{
+- return 0;
+-}
+-
+-static void free_dst_ops6_kmem_cachep(void)
+-{
+-}
+-
+-static void vrf_rt6_destroy(struct net_vrf *vrf)
++static void vrf_rt6_release(struct net_vrf *vrf)
+ {
+ }
+
+@@ -577,11 +469,11 @@ static int vrf_output(struct net *net, s
+ !(IPCB(skb)->flags & IPSKB_REROUTED));
+ }
+
+-static void vrf_rtable_destroy(struct net_vrf *vrf)
++static void vrf_rtable_release(struct net_vrf *vrf)
+ {
+ struct dst_entry *dst = (struct dst_entry *)vrf->rth;
+
+- dst_destroy(dst);
++ dst_release(dst);
+ vrf->rth = NULL;
+ }
+
+@@ -590,22 +482,10 @@ static struct rtable *vrf_rtable_create(
+ struct net_vrf *vrf = netdev_priv(dev);
+ struct rtable *rth;
+
+- rth = dst_alloc(&vrf_dst_ops, dev, 2,
+- DST_OBSOLETE_NONE,
+- (DST_HOST | DST_NOPOLICY | DST_NOXFRM));
++ rth = rt_dst_alloc(dev, 0, RTN_UNICAST, 1, 1, 0);
+ if (rth) {
+ rth->dst.output = vrf_output;
+- rth->rt_genid = rt_genid_ipv4(dev_net(dev));
+- rth->rt_flags = 0;
+- rth->rt_type = RTN_UNICAST;
+- rth->rt_is_input = 0;
+- rth->rt_iif = 0;
+- rth->rt_pmtu = 0;
+- rth->rt_gateway = 0;
+- rth->rt_uses_gateway = 0;
+ rth->rt_table_id = vrf->tb_id;
+- INIT_LIST_HEAD(&rth->rt_uncached);
+- rth->rt_uncached_list = NULL;
+ }
+
+ return rth;
+@@ -739,8 +619,8 @@ static void vrf_dev_uninit(struct net_de
+ // struct list_head *head = &queue->all_slaves;
+ // struct slave *slave, *next;
+
+- vrf_rtable_destroy(vrf);
+- vrf_rt6_destroy(vrf);
++ vrf_rtable_release(vrf);
++ vrf_rt6_release(vrf);
+
+ // list_for_each_entry_safe(slave, next, head, list)
+ // vrf_del_slave(dev, slave->dev);
+@@ -772,7 +652,7 @@ static int vrf_dev_init(struct net_devic
+ return 0;
+
+ out_rth:
+- vrf_rtable_destroy(vrf);
++ vrf_rtable_release(vrf);
+ out_stats:
+ free_percpu(dev->dstats);
+ dev->dstats = NULL;
+@@ -805,7 +685,7 @@ static struct rtable *vrf_get_rtable(con
+ struct net_vrf *vrf = netdev_priv(dev);
+
+ rth = vrf->rth;
+- atomic_inc(&rth->dst.__refcnt);
++ dst_hold(&rth->dst);
+ }
+
+ return rth;
+@@ -856,7 +736,7 @@ static struct dst_entry *vrf_get_rt6_dst
+ struct net_vrf *vrf = netdev_priv(dev);
+
+ rt = vrf->rt6;
+- atomic_inc(&rt->dst.__refcnt);
++ dst_hold(&rt->dst);
+ }
+
+ return (struct dst_entry *)rt;
+@@ -1003,19 +883,6 @@ static int __init vrf_init_module(void)
+ {
+ int rc;
+
+- vrf_dst_ops.kmem_cachep =
+- kmem_cache_create("vrf_ip_dst_cache",
+- sizeof(struct rtable), 0,
+- SLAB_HWCACHE_ALIGN,
+- NULL);
+-
+- if (!vrf_dst_ops.kmem_cachep)
+- return -ENOMEM;
+-
+- rc = init_dst_ops6_kmem_cachep();
+- if (rc != 0)
+- goto error2;
+-
+ register_netdevice_notifier(&vrf_notifier_block);
+
+ rc = rtnl_link_register(&vrf_link_ops);
+@@ -1026,22 +893,10 @@ static int __init vrf_init_module(void)
+
+ error:
+ unregister_netdevice_notifier(&vrf_notifier_block);
+- free_dst_ops6_kmem_cachep();
+-error2:
+- kmem_cache_destroy(vrf_dst_ops.kmem_cachep);
+ return rc;
+ }
+
+-static void __exit vrf_cleanup_module(void)
+-{
+- rtnl_link_unregister(&vrf_link_ops);
+- unregister_netdevice_notifier(&vrf_notifier_block);
+- kmem_cache_destroy(vrf_dst_ops.kmem_cachep);
+- free_dst_ops6_kmem_cachep();
+-}
+-
+ module_init(vrf_init_module);
+-module_exit(vrf_cleanup_module);
+ MODULE_AUTHOR("Shrijeet Mukherjee, David Ahern");
+ MODULE_DESCRIPTION("Device driver to instantiate VRF domains");
+ MODULE_LICENSE("GPL");
+--- a/include/net/ip6_route.h
++++ b/include/net/ip6_route.h
+@@ -103,6 +103,9 @@ void fib6_force_start_gc(struct net *net
+ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+ const struct in6_addr *addr, bool anycast);
+
++struct rt6_info *ip6_dst_alloc(struct net *net, struct net_device *dev,
++ int flags);
++
+ /*
+ * support functions for ND
+ *
+--- a/include/net/route.h
++++ b/include/net/route.h
+@@ -210,6 +210,9 @@ unsigned int inet_addr_type_dev_table(st
+ void ip_rt_multicast_event(struct in_device *);
+ int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg);
+ void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt);
++struct rtable *rt_dst_alloc(struct net_device *dev,
++ unsigned int flags, u16 type,
++ bool nopolicy, bool noxfrm, bool will_cache);
+
+ struct in_ifaddr;
+ void fib_add_ifaddr(struct in_ifaddr *);
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -1500,9 +1500,9 @@ static void rt_set_nexthop(struct rtable
+ #endif
+ }
+
+-static struct rtable *rt_dst_alloc(struct net_device *dev,
+- unsigned int flags, u16 type,
+- bool nopolicy, bool noxfrm, bool will_cache)
++struct rtable *rt_dst_alloc(struct net_device *dev,
++ unsigned int flags, u16 type,
++ bool nopolicy, bool noxfrm, bool will_cache)
+ {
+ struct rtable *rt;
+
+@@ -1531,6 +1531,7 @@ static struct rtable *rt_dst_alloc(struc
+
+ return rt;
+ }
++EXPORT_SYMBOL(rt_dst_alloc);
+
+ /* called in rcu_read_lock() section */
+ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -339,9 +339,9 @@ static struct rt6_info *__ip6_dst_alloc(
+ return rt;
+ }
+
+-static struct rt6_info *ip6_dst_alloc(struct net *net,
+- struct net_device *dev,
+- int flags)
++struct rt6_info *ip6_dst_alloc(struct net *net,
++ struct net_device *dev,
++ int flags)
+ {
+ struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags);
+
+@@ -365,6 +365,7 @@ static struct rt6_info *ip6_dst_alloc(st
+
+ return rt;
+ }
++EXPORT_SYMBOL(ip6_dst_alloc);
+
+ static void ip6_dst_destroy(struct dst_entry *dst)
+ {
--- /dev/null
+From 549d7b317c761dbf4ed0c2945aec3acc9ca7ae14 Mon Sep 17 00:00:00 2001
+From: "H. Nikolaus Schaller" <hns@goldelico.com>
+Date: Thu, 17 Dec 2015 11:12:53 +0100
+Subject: power: bq27xxx: fix reading for bq27000 and bq27010
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: H. Nikolaus Schaller <hns@goldelico.com>
+
+commit 549d7b317c761dbf4ed0c2945aec3acc9ca7ae14 upstream.
+
+bug: the driver reports funny capacity values:
+
+root@letux:/sys/class/power_supply/bq27000-battery# cat uevent
+POWER_SUPPLY_NAME=bq27000-battery
+POWER_SUPPLY_STATUS=Charging
+POWER_SUPPLY_PRESENT=1
+POWER_SUPPLY_VOLTAGE_NOW=3702000
+POWER_SUPPLY_CURRENT_NOW=-464635
+POWER_SUPPLY_CAPACITY=1536 <- over 100% is magic
+POWER_SUPPLY_CAPACITY_LEVEL=Normal
+POWER_SUPPLY_TEMP=311
+POWER_SUPPLY_TIME_TO_FULL_NOW=10440
+POWER_SUPPLY_TECHNOLOGY=Li-ion
+POWER_SUPPLY_CHARGE_FULL=805450
+POWER_SUPPLY_CHARGE_NOW=1068
+POWER_SUPPLY_CHARGE_FULL_DESIGN=8844998 <- battery has just 1200 mAh
+POWER_SUPPLY_CYCLE_COUNT=21
+POWER_SUPPLY_ENERGY_NOW=0
+POWER_SUPPLY_POWER_AVG=0
+POWER_SUPPLY_HEALTH=Good
+POWER_SUPPLY_MANUFACTURER=Texas Instruments
+
+reason: the state of charge and the design capacity register are single
+byte only. The design capacity returns the higer order byte.
+
+tested: GTA04 with Openmoko/FIC HF08x battery (using hdq)
+
+Fixes: d74534c27775 ("power: bq27xxx_battery: Add support for additional bq27xxx family devices")
+Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
+Acked-by: Andrew F. Davis <afd@ti.com>
+Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
+Signed-off-by: Sebastian Reichel <sre@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/power/bq27xxx_battery.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+--- a/drivers/power/bq27xxx_battery.c
++++ b/drivers/power/bq27xxx_battery.c
+@@ -471,7 +471,10 @@ static int bq27xxx_battery_read_soc(stru
+ {
+ int soc;
+
+- soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false);
++ if (di->chip == BQ27000 || di->chip == BQ27010)
++ soc = bq27xxx_read(di, BQ27XXX_REG_SOC, true);
++ else
++ soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false);
+
+ if (soc < 0)
+ dev_dbg(di->dev, "error reading State-of-Charge\n");
+@@ -536,7 +539,10 @@ static int bq27xxx_battery_read_dcap(str
+ {
+ int dcap;
+
+- dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false);
++ if (di->chip == BQ27000 || di->chip == BQ27010)
++ dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, true);
++ else
++ dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false);
+
+ if (dcap < 0) {
+ dev_dbg(di->dev, "error reading initial last measured discharge\n");
+@@ -544,7 +550,7 @@ static int bq27xxx_battery_read_dcap(str
+ }
+
+ if (di->chip == BQ27000 || di->chip == BQ27010)
+- dcap *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
++ dcap = (dcap << 8) * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
+ else
+ dcap *= 1000;
+
--- /dev/null
+From 099867a16a0fa9fd5aafc32e3b1a6f8a90f17834 Mon Sep 17 00:00:00 2001
+From: "H. Nikolaus Schaller" <hns@goldelico.com>
+Date: Thu, 17 Dec 2015 11:12:54 +0100
+Subject: power: bq27xxx: fix register numbers of bq27500
+
+From: H. Nikolaus Schaller <hns@goldelico.com>
+
+commit 099867a16a0fa9fd5aafc32e3b1a6f8a90f17834 upstream.
+
+bug: according to data sheet some register numbers are wrong.
+
+tested: no
+
+Fixes: d74534c27775 ("power: bq27xxx_battery: Add support for additional bq27xxx family devices")
+Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
+Acked-by: Andrew F. Davis <afd@ti.com>
+Signed-off-by: Sebastian Reichel <sre@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/power/bq27xxx_battery.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/power/bq27xxx_battery.c
++++ b/drivers/power/bq27xxx_battery.c
+@@ -198,10 +198,10 @@ static u8 bq27500_regs[] = {
+ INVALID_REG_ADDR, /* TTECP - NA */
+ 0x0c, /* NAC */
+ 0x12, /* LMD(FCC) */
+- 0x1e, /* CYCT */
++ 0x2a, /* CYCT */
+ INVALID_REG_ADDR, /* AE - NA */
+- 0x20, /* SOC(RSOC) */
+- 0x2e, /* DCAP(ILMD) */
++ 0x2c, /* SOC(RSOC) */
++ 0x3c, /* DCAP(ILMD) */
+ INVALID_REG_ADDR, /* AP - NA */
+ };
+
--- /dev/null
+From 265b60497a57da56a4be7d5c72983ae89dc0765e Mon Sep 17 00:00:00 2001
+From: Liu Xiang <liu.xiang6@zte.com.cn>
+Date: Sat, 9 Jan 2016 22:10:39 +0800
+Subject: power: bq27xxx_battery: Fix bq27541 AveragePower register address
+
+From: Liu Xiang <liu.xiang6@zte.com.cn>
+
+commit 265b60497a57da56a4be7d5c72983ae89dc0765e upstream.
+
+Currently in bq27541 driver, the average power register address is
+incorrectly set to 0x76, which would result in an error:
+bq27xxx-battery 2-0055: error reading average power register 10: -11
+According to the bq27541 datasheet, fix this problem by setting
+the average power register address to 0x24.
+
+Fixes: d74534c27775 ("power: bq27xxx_battery: Add support for additional bq27xxx family devices")
+Signed-off-by: Liu Xiang <liu.xiang6@zte.com.cn>
+Acked-by: Andrew F. Davis <afd@ti.com>
+Signed-off-by: Sebastian Reichel <sre@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/power/bq27xxx_battery.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/power/bq27xxx_battery.c
++++ b/drivers/power/bq27xxx_battery.c
+@@ -242,7 +242,7 @@ static u8 bq27541_regs[] = {
+ INVALID_REG_ADDR, /* AE - NA */
+ 0x2c, /* SOC(RSOC) */
+ 0x3c, /* DCAP */
+- 0x76, /* AP */
++ 0x24, /* AP */
+ };
+
+ static u8 bq27545_regs[] = {
--- /dev/null
+From 6b9140f39c2aaf76791197fbab0839c0e4af56e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sasha.levin@oracle.com>
+Date: Tue, 22 Dec 2015 12:43:36 -0500
+Subject: power: test_power: correctly handle empty writes
+
+From: Sasha Levin <sasha.levin@oracle.com>
+
+commit 6b9140f39c2aaf76791197fbab0839c0e4af56e8 upstream.
+
+Writing 0 length data into test_power makes it access an invalid array
+location and kill the system.
+
+Fixes: f17ef9b2d ("power: Make test_power driver more dynamic.")
+Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
+Signed-off-by: Sebastian Reichel <sre@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/power/test_power.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/power/test_power.c
++++ b/drivers/power/test_power.c
+@@ -301,6 +301,8 @@ static int map_get_value(struct battery_
+ buf[MAX_KEYLENGTH-1] = '\0';
+
+ cr = strnlen(buf, MAX_KEYLENGTH) - 1;
++ if (cr < 0)
++ return def_val;
+ if (buf[cr] == '\n')
+ buf[cr] = '\0';
+
--- /dev/null
+From 362761299eea7dfc3a4870551de36e08758b9254 Mon Sep 17 00:00:00 2001
+From: Marcin Niestroj <m.niestroj@grinn-global.com>
+Date: Tue, 14 Jun 2016 15:29:24 +0200
+Subject: power_supply: tps65217-charger: Fix NULL deref during property export
+
+From: Marcin Niestroj <m.niestroj@grinn-global.com>
+
+commit 362761299eea7dfc3a4870551de36e08758b9254 upstream.
+
+This bug leads to:
+
+[ 1.906411] Unable to handle kernel NULL pointer dereference at virtual address 0000000c
+[ 1.914878] pgd = c0004000
+[ 1.917786] [0000000c] *pgd=00000000
+[ 1.921536] Internal error: Oops: 5 [#1] SMP ARM
+[ 1.926357] Modules linked in:
+[ 1.929556] CPU: 0 PID: 14 Comm: kworker/0:1 Not tainted 4.4.5 #18
+[ 1.936006] Hardware name: Generic AM33XX (Flattened Device Tree)
+[ 1.942383] Workqueue: events power_supply_changed_work
+[ 1.947842] task: de2c41c0 ti: de2c8000 task.ti: de2c8000
+[ 1.953483] PC is at tps65217_ac_get_property+0x14/0x28
+[ 1.958937] LR is at tps65217_ac_get_property+0x10/0x28
+
+Driver was trying to use drv_data in property get handler. However drv_data
+was not set, so it caused NULL pointer dereference. This patch properly
+sets drv_data during probe by power_supply_config parameter, so the
+property get handler works as desired.
+
+Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
+Fixes: 3636859b280c ("power_supply: Add support for tps65217-charger")
+Signed-off-by: Sebastian Reichel <sre@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/power/tps65217_charger.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/power/tps65217_charger.c
++++ b/drivers/power/tps65217_charger.c
+@@ -197,6 +197,7 @@ static int tps65217_charger_probe(struct
+ {
+ struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+ struct tps65217_charger *charger;
++ struct power_supply_config cfg = {};
+ int ret;
+
+ dev_dbg(&pdev->dev, "%s\n", __func__);
+@@ -209,9 +210,12 @@ static int tps65217_charger_probe(struct
+ charger->tps = tps;
+ charger->dev = &pdev->dev;
+
++ cfg.of_node = pdev->dev.of_node;
++ cfg.drv_data = charger;
++
+ charger->ac = devm_power_supply_register(&pdev->dev,
+ &tps65217_charger_desc,
+- NULL);
++ &cfg);
+ if (IS_ERR(charger->ac)) {
+ dev_err(&pdev->dev, "failed: power supply register\n");
+ return PTR_ERR(charger->ac);
net-ethernet-ti-davinci_emac-fix-fixed-link-phydev-and-of-node-leaks.patch
net-dsa-move-dsa-slave-destroy-code-to-slave.c.patch
net-dsa-slave-fix-fixed-link-phydev-leaks.patch
+power-bq27xxx-fix-reading-for-bq27000-and-bq27010.patch
+power-bq27xxx-fix-register-numbers-of-bq27500.patch
+power-test_power-correctly-handle-empty-writes.patch
+power-bq27xxx_battery-fix-bq27541-averagepower-register-address.patch
+power_supply-tps65217-charger-fix-null-deref-during-property-export.patch
+net-vrf-fix-dst-reference-counting.patch
+net-don-t-delete-routes-in-different-vrfs.patch