From 06928b3870d213cb42b00e2949419f2d44b9d45f Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 12 Jan 2016 20:17:08 +0100 Subject: net: bpf: reject invalid shifts On ARM64, a BUG() is triggered in the eBPF JIT if a filter with a constant shift that can't be encoded in the immediate field of the UBFM/SBFM instructions is passed to the JIT. Since these shifts amounts, which are negative or >= regsize, are invalid, reject them in the eBPF verifier and the classic BPF filter checker, for all architectures. Signed-off-by: Rabin Vincent Acked-by: Alexei Starovoitov Acked-by: Daniel Borkmann Signed-off-by: David S. Miller diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index a7945d1..d1d3e8f 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -1121,6 +1121,16 @@ static int check_alu_op(struct verifier_env *env, struct bpf_insn *insn) return -EINVAL; } + if ((opcode == BPF_LSH || opcode == BPF_RSH || + opcode == BPF_ARSH) && BPF_SRC(insn->code) == BPF_K) { + int size = BPF_CLASS(insn->code) == BPF_ALU64 ? 64 : 32; + + if (insn->imm < 0 || insn->imm >= size) { + verbose("invalid shift %d\n", insn->imm); + return -EINVAL; + } + } + /* pattern match 'bpf_add Rx, imm' instruction */ if (opcode == BPF_ADD && BPF_CLASS(insn->code) == BPF_ALU64 && regs[insn->dst_reg].type == FRAME_PTR && diff --git a/net/core/filter.c b/net/core/filter.c index 672eefb..37157c4 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -777,6 +777,11 @@ static int bpf_check_classic(const struct sock_filter *filter, if (ftest->k == 0) return -EINVAL; break; + case BPF_ALU | BPF_LSH | BPF_K: + case BPF_ALU | BPF_RSH | BPF_K: + if (ftest->k >= 32) + return -EINVAL; + break; case BPF_LD | BPF_MEM: case BPF_LDX | BPF_MEM: case BPF_ST: -- cgit v0.10.2 From ccdf6ce6a8dba374668ae9b4d763e19903611c38 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 11 Jan 2016 14:26:19 +0200 Subject: net: netlink: Fix multicast group storage allocation for families with more than one groups Multicast groups are stored in global buffer. Check for needed buffer size incorrectly compares buffer size to first id for family. This means that for families with more than one mcast id one may allocate too small buffer and end up writing rest of the groups to some unallocated memory. Fix the buffer size check to compare allocated space to last mcast id for the family. Tested on ARM using kernel 3.14 Signed-off-by: Matti Vaittinen Signed-off-by: David S. Miller diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index bc0e504..a992083 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -185,7 +185,7 @@ static int genl_allocate_reserve_groups(int n_groups, int *first_id) } } - if (id >= mc_groups_longs * BITS_PER_LONG) { + if (id + n_groups >= mc_groups_longs * BITS_PER_LONG) { unsigned long new_longs = mc_groups_longs + BITS_TO_LONGS(n_groups); size_t nlen = new_longs * sizeof(unsigned long); -- cgit v0.10.2 From f1640c3ddeec12804bc9a21feee85fc15aca95f6 Mon Sep 17 00:00:00 2001 From: wangweidong Date: Wed, 13 Jan 2016 11:06:41 +0800 Subject: bgmac: fix a missing check for build_skb when build_skb failed, it may occure a NULL pointer. So add a 'NULL check' for it. Signed-off-by: Weidong Wang Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index c7798d3..3974152 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -466,6 +466,11 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, len -= ETH_FCS_LEN; skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE); + if (unlikely(skb)) { + bgmac_err(bgmac, "build_skb failed\n"); + put_page(virt_to_head_page(buf)); + break; + } skb_put(skb, BGMAC_RX_FRAME_OFFSET + BGMAC_RX_BUF_OFFSET + len); skb_pull(skb, BGMAC_RX_FRAME_OFFSET + -- cgit v0.10.2 From af63cf51b7f960aa73b32bac683cd4078f08fa0e Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Mon, 30 Nov 2015 17:34:01 +0100 Subject: batman-adv: fix lockdep splat when doing mcast_free While testing, we got something like this: WARNING: CPU: 0 PID: 238 at net/batman-adv/multicast.c:142 batadv_mcast_mla_tt_retract+0x94/0x205 [batman_adv]() [...] Call Trace: [] dump_stack+0x4b/0x64 [] warn_slowpath_common+0xbc/0x120 [] ? batadv_mcast_mla_tt_retract+0x94/0x205 [batman_adv] [] warn_slowpath_null+0x15/0x20 [] batadv_mcast_mla_tt_retract+0x94/0x205 [batman_adv] [] batadv_mcast_free+0x36/0x39 [batman_adv] [] batadv_mesh_free+0x7d/0x13f [batman_adv] [] batadv_softif_free+0x15/0x25 [batman_adv] [...] Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index eb76386..75fa501 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@ -802,7 +802,9 @@ void batadv_mcast_free(struct batadv_priv *bat_priv) batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 1); batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 1); + spin_lock_bh(&bat_priv->tt.commit_lock); batadv_mcast_mla_tt_retract(bat_priv, NULL); + spin_unlock_bh(&bat_priv->tt.commit_lock); } /** -- cgit v0.10.2 From bab7c6c3deac70966a3000402c0ea6d0c20edd15 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 5 Jan 2016 12:06:17 +0100 Subject: batman-adv: Fix list removal of batadv_hardif_neigh_node The neigh_list with batadv_hardif_neigh_node objects is accessed with only rcu_read_lock in batadv_hardif_neigh_get and batadv_iv_neigh_print. Thus it is not allowed to kfree the object before the rcu grace period ends (which may still protects context accessing this object). Therefore the object has first to be removed from the neigh_list and then it has either wait with synchronize_rcu or call_rcu till the grace period ends before it can be freed. Fixes: cef63419f7db ("batman-adv: add list of unique single hop neighbors per hard-interface") Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 3c782a33..ae6d18c 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -211,10 +211,6 @@ static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu) hardif_neigh = container_of(rcu, struct batadv_hardif_neigh_node, rcu); - spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); - hlist_del_init_rcu(&hardif_neigh->list); - spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); - batadv_hardif_free_ref_now(hardif_neigh->if_incoming); kfree(hardif_neigh); } @@ -227,8 +223,13 @@ static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu) static void batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh) { - if (atomic_dec_and_test(&hardif_neigh->refcount)) + if (atomic_dec_and_test(&hardif_neigh->refcount)) { + spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); + hlist_del_init_rcu(&hardif_neigh->list); + spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); + batadv_hardif_neigh_free_rcu(&hardif_neigh->rcu); + } } /** @@ -238,8 +239,13 @@ batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh) */ void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh) { - if (atomic_dec_and_test(&hardif_neigh->refcount)) + if (atomic_dec_and_test(&hardif_neigh->refcount)) { + spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); + hlist_del_init_rcu(&hardif_neigh->list); + spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); + call_rcu(&hardif_neigh->rcu, batadv_hardif_neigh_free_rcu); + } } /** -- cgit v0.10.2 From b8e429a2feac623a34e21099a4a69de29b6d873e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 13 Jan 2016 10:28:06 -0500 Subject: genetlink: Fix off-by-one in genl_allocate_reserve_groups() The bug fix for adding n_groups to the computation forgot to adjust ">=" to ">" to keep the condition correct. Signed-off-by: David S. Miller diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index d3f6b06..f830326 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -185,7 +185,7 @@ static int genl_allocate_reserve_groups(int n_groups, int *first_id) } } - if (id + n_groups >= mc_groups_longs * BITS_PER_LONG) { + if (id + n_groups > mc_groups_longs * BITS_PER_LONG) { unsigned long new_longs = mc_groups_longs + BITS_TO_LONGS(n_groups); size_t nlen = new_longs * sizeof(unsigned long); -- cgit v0.10.2 From 00ae40e71d85ea3fed1b906951ffd80e0321a96d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 13 Jan 2016 15:28:23 +0300 Subject: mlxsw: fix SWITCHDEV_OBJ_ID_PORT_MDB There is a missing break statement so we always return -EOPNOTSUPP. Fixes: 3a49b4fde2a1 ('mlxsw: Adding layer 2 multicast support') Signed-off-by: Dan Carpenter Acked-by: Jiri Pirko Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index ffe894e..45479ef 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1015,6 +1015,7 @@ static int mlxsw_sp_port_obj_del(struct net_device *dev, case SWITCHDEV_OBJ_ID_PORT_MDB: err = mlxsw_sp_port_mdb_del(mlxsw_sp_port, SWITCHDEV_OBJ_PORT_MDB(obj)); + break; default: err = -EOPNOTSUPP; break; -- cgit v0.10.2 From 3b780bed3138c2a8061c218df7e321beec9a6ec9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 13 Jan 2016 11:45:39 -0500 Subject: x25_asy: Free x25_asy on x25_asy_open() failure. Based upon a report by Dmitry Vyukov. Signed-off-by: David S. Miller diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index cd39025..1bc5e93 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -571,8 +571,10 @@ static int x25_asy_open_tty(struct tty_struct *tty) /* Perform the low-level X.25 async init */ err = x25_asy_open(sl->dev); - if (err) + if (err) { + x25_asy_free(sl); return err; + } /* Done. We have linked the TTY line to a channel. */ return 0; } -- cgit v0.10.2 From 7356f4e42490d91939521c70b04812d5a07bd0f2 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 13 Jan 2016 12:43:53 -0500 Subject: 3c59x: balance page maps and unmaps debug kernel noticed a screw up in 3c59x. skbs being mapped as page were being unmapped as singles. Easy fix. Tested by myself Signed-off-by: Neil Horman CC: Steffen Klassert Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 1c5f3b2..4c3bc31 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -2460,7 +2460,7 @@ boomerang_interrupt(int irq, void *dev_id) #if DO_ZEROCOPY int i; for (i=0; i<=skb_shinfo(skb)->nr_frags; i++) - pci_unmap_single(VORTEX_PCI(vp), + pci_unmap_page(VORTEX_PCI(vp), le32_to_cpu(vp->tx_ring[entry].frag[i].addr), le32_to_cpu(vp->tx_ring[entry].frag[i].length)&0xFFF, PCI_DMA_TODEVICE); -- cgit v0.10.2 From 6e144419e4da11a9a4977c8d899d7247d94ca338 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 13 Jan 2016 12:43:54 -0500 Subject: 3c59x: fix another page map/single unmap imbalance libdma debug found another page map/unmap imbalance in 3c59x. Multi fragment frames are mapped such that the lead fragment was mapped as a single entry, while all other fragments were mapped as pages. However, on unmapping they were all unmapped as pages. Fix is pretty easy, just unmap the lead frag as a single entry, and bump the for loop initalization up by one so that all subsequent frags get unmapped as pages Signed-off-by: Neil Horman CC: "David S. Miller" CC: Steffen Klassert Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 4c3bc31..79e1a02 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -2459,7 +2459,12 @@ boomerang_interrupt(int irq, void *dev_id) struct sk_buff *skb = vp->tx_skbuff[entry]; #if DO_ZEROCOPY int i; - for (i=0; i<=skb_shinfo(skb)->nr_frags; i++) + pci_unmap_single(VORTEX_PCI(vp), + le32_to_cpu(vp->tx_ring[entry].frag[0].addr), + le32_to_cpu(vp->tx_ring[entry].frag[0].length), + PCI_DMA_TODEVICE); + + for (i=1; i<=skb_shinfo(skb)->nr_frags; i++) pci_unmap_page(VORTEX_PCI(vp), le32_to_cpu(vp->tx_ring[entry].frag[i].addr), le32_to_cpu(vp->tx_ring[entry].frag[i].length)&0xFFF, -- cgit v0.10.2 From 701a0fd5231866db08cebcd502894699f49cb960 Mon Sep 17 00:00:00 2001 From: wangweidong Date: Wed, 13 Jan 2016 11:11:09 +0800 Subject: hip04_eth: fix missing error handle for build_skb failed when build_skb failed, we should goto refill the buffer. Signed-off-by: Weidong Wang Acked-by: Ding Tainhong Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c index 253f8ed..0c4afe9 100644 --- a/drivers/net/ethernet/hisilicon/hip04_eth.c +++ b/drivers/net/ethernet/hisilicon/hip04_eth.c @@ -500,8 +500,10 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget) while (cnt && !last) { buf = priv->rx_buf[priv->rx_head]; skb = build_skb(buf, priv->rx_buf_size); - if (unlikely(!skb)) + if (unlikely(!skb)) { net_dbg_ratelimited("build_skb failed\n"); + goto refill; + } dma_unmap_single(&ndev->dev, priv->rx_phys[priv->rx_head], RX_BUF_SIZE, DMA_FROM_DEVICE); @@ -528,6 +530,7 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget) rx++; } +refill: buf = netdev_alloc_frag(priv->rx_buf_size); if (!buf) goto done; -- cgit v0.10.2 From 5d19c619ab3f0551864684f09c2a2f22ee972bef Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Thu, 14 Jan 2016 15:46:28 +0100 Subject: fsl/fman: Delete one function call "put_device" in dtsec_config() The Coccinelle semantic patch script "deref_null.cocci" pointed a problem out in the implementation of the function "dtsec_config". A null pointer was assigned to the data structure member "tbiphy" of the variable "dtsec" if a matching device was not found. A call of the function "put_device" was unnecessary then because a previous call of the function "get_device" was not triggered. Thus remove the function call "put_device" after the printing of the desired error message. Signed-off-by: Markus Elfring Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c index 6b1261c..7c92eb8 100644 --- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c +++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c @@ -1434,7 +1434,6 @@ struct fman_mac *dtsec_config(struct fman_mac_params *params) dtsec->tbiphy = of_phy_find_device(params->internal_phy_node); if (!dtsec->tbiphy) { pr_err("of_phy_find_device (TBI PHY) failed\n"); - put_device(&dtsec->tbiphy->mdio.dev); goto err_dtsec_drv_param; } -- cgit v0.10.2 From 9207f9d45b0ad071baa128e846d7e7ed85016df3 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Fri, 8 Jan 2016 15:21:46 +0300 Subject: net: preserve IP control block during GSO segmentation Skb_gso_segment() uses skb control block during segmentation. This patch adds 32-bytes room for previous control block which will be copied into all resulting segments. This patch fixes kernel crash during fragmenting forwarded packets. Fragmentation requires valid IP CB in skb for clearing ip options. Also patch removes custom save/restore in ovs code, now it's redundant. Signed-off-by: Konstantin Khlebnikov Link: http://lkml.kernel.org/r/CALYGNiP-0MZ-FExV2HutTvE9U-QQtkKSoE--KN=JQE5STYsjAA@mail.gmail.com Signed-off-by: David S. Miller diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 07f9ccd..11f935c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3551,7 +3551,8 @@ struct skb_gso_cb { int encap_level; __u16 csum_start; }; -#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)(skb)->cb) +#define SKB_SGO_CB_OFFSET 32 +#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)((skb)->cb + SKB_SGO_CB_OFFSET)) static inline int skb_tnl_header_len(const struct sk_buff *inner_skb) { diff --git a/net/core/dev.c b/net/core/dev.c index 0ca95d5..cc9e365 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2695,6 +2695,8 @@ static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path) * * It may return NULL if the skb requires no segmentation. This is * only possible when GSO is used for verifying header integrity. + * + * Segmentation preserves SKB_SGO_CB_OFFSET bytes of previous skb cb. */ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, netdev_features_t features, bool tx_path) @@ -2709,6 +2711,9 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, return ERR_PTR(err); } + BUILD_BUG_ON(SKB_SGO_CB_OFFSET + + sizeof(*SKB_GSO_CB(skb)) > sizeof(skb->cb)); + SKB_GSO_CB(skb)->mac_offset = skb_headroom(skb); SKB_GSO_CB(skb)->encap_level = 0; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 512a447..64878ef 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -239,6 +239,7 @@ static int ip_finish_output_gso(struct net *net, struct sock *sk, * from host network stack. */ features = netif_skb_features(skb); + BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_SGO_CB_OFFSET); segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); if (IS_ERR_OR_NULL(segs)) { kfree_skb(skb); diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 91a8b00..deadfda 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -336,12 +336,10 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, unsigned short gso_type = skb_shinfo(skb)->gso_type; struct sw_flow_key later_key; struct sk_buff *segs, *nskb; - struct ovs_skb_cb ovs_cb; int err; - ovs_cb = *OVS_CB(skb); + BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_SGO_CB_OFFSET); segs = __skb_gso_segment(skb, NETIF_F_SG, false); - *OVS_CB(skb) = ovs_cb; if (IS_ERR(segs)) return PTR_ERR(segs); if (segs == NULL) @@ -359,7 +357,6 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, /* Queue all of the segments. */ skb = segs; do { - *OVS_CB(skb) = ovs_cb; if (gso_type & SKB_GSO_UDP && skb != segs) key = &later_key; diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index cc3676e..ff4a91f 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -167,6 +167,8 @@ static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb { struct sk_buff *segs; + BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_SGO_CB_OFFSET); + BUILD_BUG_ON(sizeof(*IP6CB(skb)) > SKB_SGO_CB_OFFSET); segs = skb_gso_segment(skb, 0); kfree_skb(skb); if (IS_ERR(segs)) -- cgit v0.10.2 From b70ce2ab41cb67ab3d661eda078f7c4029bbca95 Mon Sep 17 00:00:00 2001 From: yankejian Date: Wed, 13 Jan 2016 15:09:58 +0800 Subject: dts: hisi: fixes no syscon fault when init mdio When linux start up, we get the log below: "Hi-HNS_MDIO 803c0000.mdio: no syscon hisilicon,peri-c-subctrl mdio_bus mdio@803c0000: mdio sys ctl reg has not maped" The source code about the subctrl is dealt syscon, but dts doesn't. It cause such fault, so this patch adds the syscon info on dts files to fixes it. Signed-off-by: Kejian Yan Acked-by: Rob Herring Signed-off-by: David S. Miller diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt index 6ac7c00..e3ccab1 100644 --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt @@ -187,6 +187,22 @@ Example: reg = <0xb0000000 0x10000>; }; +Hisilicon HiP05 PERISUB system controller + +Required properties: +- compatible : "hisilicon,hip05-perisubc", "syscon"; +- reg : Register address and size + +The HiP05 PERISUB system controller is shared by peripheral controllers in +HiP05 Soc to implement some basic configurations. The peripheral +controllers include mdio, ddr, iic, uart, timer and so on. + +Example: + /* for HiP05 perisub-ctrl-c system */ + peri_c_subctrl: syscon@80000000 { + compatible = "hisilicon,hip05-perisubc", "syscon"; + reg = <0x0 0x80000000 0x0 0x10000>; + }; ----------------------------------------------------------------------- Hisilicon CPU controller diff --git a/arch/arm64/boot/dts/hisilicon/hip05.dtsi b/arch/arm64/boot/dts/hisilicon/hip05.dtsi index 4ff16d0..c1ea999 100644 --- a/arch/arm64/boot/dts/hisilicon/hip05.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip05.dtsi @@ -246,6 +246,11 @@ clock-frequency = <200000000>; }; + peri_c_subctrl: syscon@80000000 { + compatible = "hisilicon,hip05-perisubc", "syscon"; + reg = < 0x0 0x80000000 0x0 0x10000>; + }; + uart0: uart@80300000 { compatible = "snps,dw-apb-uart"; reg = <0x0 0x80300000 0x0 0x10000>; diff --git a/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi b/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi index 606dd5a..da7b6e6 100644 --- a/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi @@ -10,8 +10,8 @@ soc0: soc@000000000 { #address-cells = <1>; #size-cells = <0>; compatible = "hisilicon,hns-mdio"; - reg = <0x0 0x803c0000 0x0 0x10000 - 0x0 0x80000000 0x0 0x10000>; + reg = <0x0 0x803c0000 0x0 0x10000>; + subctrl-vbase = <&peri_c_subctrl>; soc0_phy0: ethernet-phy@0 { reg = <0x0>; -- cgit v0.10.2 From 28052e75834a84b006893735debedb8ee6b6cbc0 Mon Sep 17 00:00:00 2001 From: yankejian Date: Wed, 13 Jan 2016 15:09:59 +0800 Subject: net: hns: fixes no syscon error when init mdio As dtsi files use the normal naming conventions using '-' instead of '_' inside of property names, the driver needs to update the phandle name strings of the of_parse_phandle func. Signed-off-by: Kejian Yan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index 58c96c4..765ddb3 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -458,7 +458,7 @@ static int hns_mdio_probe(struct platform_device *pdev) } mdio_dev->subctrl_vbase = - syscon_node_to_regmap(of_parse_phandle(np, "subctrl_vbase", 0)); + syscon_node_to_regmap(of_parse_phandle(np, "subctrl-vbase", 0)); if (IS_ERR(mdio_dev->subctrl_vbase)) { dev_warn(&pdev->dev, "no syscon hisilicon,peri-c-subctrl\n"); mdio_dev->subctrl_vbase = NULL; -- cgit v0.10.2 From 65a5124a71e85c35fa8d047a471950325855dccf Mon Sep 17 00:00:00 2001 From: Xin Long Date: Thu, 14 Jan 2016 13:49:34 +0800 Subject: sctp: support to lookup with ep+paddr in transport rhashtable Now, when we sendmsg, we translate the ep to laddr by selecting the first element of the list, and then do a lookup for a transport. But sctp_hash_cmp() will compare it against asoc addr_list, which may be a subset of ep addr_list, meaning that this chosen laddr may not be there, and thus making it impossible to find the transport. So we fix it by using ep + paddr to lookup transports in hashtable. In sctp_hash_cmp, if .ep is set, we will check if this ep == asoc->ep, or we will do the laddr check. Fixes: d6c0256a60e6 ("sctp: add the rhashtable apis for sctp global transport hashtable") Signed-off-by: Xin Long Acked-by: Marcelo Ricardo Leitner Reported-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/sctp/input.c b/net/sctp/input.c index d9a6e66..b9a536b 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -784,6 +784,7 @@ hit: /* rhashtable for transport */ struct sctp_hash_cmp_arg { + const struct sctp_endpoint *ep; const union sctp_addr *laddr; const union sctp_addr *paddr; const struct net *net; @@ -797,15 +798,20 @@ static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg, struct sctp_association *asoc = t->asoc; const struct net *net = x->net; - if (x->laddr->v4.sin_port != htons(asoc->base.bind_addr.port)) - return 1; if (!sctp_cmp_addr_exact(&t->ipaddr, x->paddr)) return 1; if (!net_eq(sock_net(asoc->base.sk), net)) return 1; - if (!sctp_bind_addr_match(&asoc->base.bind_addr, - x->laddr, sctp_sk(asoc->base.sk))) - return 1; + if (x->ep) { + if (x->ep != asoc->ep) + return 1; + } else { + if (x->laddr->v4.sin_port != htons(asoc->base.bind_addr.port)) + return 1; + if (!sctp_bind_addr_match(&asoc->base.bind_addr, + x->laddr, sctp_sk(asoc->base.sk))) + return 1; + } return 0; } @@ -832,9 +838,11 @@ static inline u32 sctp_hash_key(const void *data, u32 len, u32 seed) const struct sctp_hash_cmp_arg *x = data; const union sctp_addr *paddr = x->paddr; const struct net *net = x->net; - u16 lport = x->laddr->v4.sin_port; + u16 lport; u32 addr; + lport = x->ep ? htons(x->ep->base.bind_addr.port) : + x->laddr->v4.sin_port; if (paddr->sa.sa_family == AF_INET6) addr = jhash(&paddr->v6.sin6_addr, 16, seed); else @@ -864,12 +872,9 @@ void sctp_transport_hashtable_destroy(void) void sctp_hash_transport(struct sctp_transport *t) { - struct sctp_sockaddr_entry *addr; struct sctp_hash_cmp_arg arg; - addr = list_entry(t->asoc->base.bind_addr.address_list.next, - struct sctp_sockaddr_entry, list); - arg.laddr = &addr->a; + arg.ep = t->asoc->ep; arg.paddr = &t->ipaddr; arg.net = sock_net(t->asoc->base.sk); @@ -891,6 +896,7 @@ struct sctp_transport *sctp_addrs_lookup_transport( const union sctp_addr *paddr) { struct sctp_hash_cmp_arg arg = { + .ep = NULL, .laddr = laddr, .paddr = paddr, .net = net, @@ -904,13 +910,15 @@ struct sctp_transport *sctp_epaddr_lookup_transport( const struct sctp_endpoint *ep, const union sctp_addr *paddr) { - struct sctp_sockaddr_entry *addr; struct net *net = sock_net(ep->base.sk); + struct sctp_hash_cmp_arg arg = { + .ep = ep, + .paddr = paddr, + .net = net, + }; - addr = list_entry(ep->base.bind_addr.address_list.next, - struct sctp_sockaddr_entry, list); - - return sctp_addrs_lookup_transport(net, &addr->a, paddr); + return rhashtable_lookup_fast(&sctp_transport_hashtable, &arg, + sctp_hash_params); } /* Look up an association. */ -- cgit v0.10.2 From 244683749e3c632ab45655098259d5514c179c8a Mon Sep 17 00:00:00 2001 From: Nathan Sullivan Date: Thu, 14 Jan 2016 13:27:27 -0600 Subject: net: macb: clear interrupts when disabling them Disabling interrupts with the IDR register does not stop the macb hardware from asserting its interrupt line if there are interrupts pending. Always clear the interrupts using ISR, and be sure to write it on hardware that is not read-to-clear, like Zynq. Not doing so will cause interrupts when the driver doesn't expect them. Signed-off-by: Nathan Sullivan Acked-by: Nicolas Ferre Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index c563475..9d9984a 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1040,6 +1040,8 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) /* close possible race with dev_close */ if (unlikely(!netif_running(dev))) { queue_writel(queue, IDR, -1); + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + queue_writel(queue, ISR, -1); break; } @@ -1561,6 +1563,8 @@ static void macb_reset_hw(struct macb *bp) for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { queue_writel(queue, IDR, -1); queue_readl(queue, ISR); + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + queue_writel(queue, ISR, -1); } } -- cgit v0.10.2 From 113c74d83eef870e43a0d9279044e9d5435f0d07 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Thu, 14 Jan 2016 21:57:18 +0100 Subject: net: phy: turn carrier off on phy attach The operstate of a networking device initially IF_OPER_UNKNOWN aka "unknown", updated on carrier state changes (with carrier state being on by default). This means it will stay unknown unless the carrier state goes to off at some point, which is not the case if the phy is already up/connected at startup. Explicitly turn off the carrier on phy attach, leaving the phy state machine to turn the carrier on when it has done the initial negotiation. Signed-off-by: Sjoerd Simons Signed-off-by: David S. Miller diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 903737a..bad3f00 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -901,6 +901,11 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, phydev->state = PHY_READY; + /* Initial carrier state is off as the phy is about to be + * (re)initialized. + */ + netif_carrier_off(phydev->attached_dev); + /* Do initial configuration here, now that * we have certain key parameters * (dev_flags and interface) -- cgit v0.10.2 From 34ae6a1aa0540f0f781dd265366036355fdc8930 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 15 Jan 2016 04:56:56 -0800 Subject: ipv6: update skb->csum when CE mark is propagated When a tunnel decapsulates the outer header, it has to comply with RFC 6080 and eventually propagate CE mark into inner header. It turns out IP6_ECN_set_ce() does not correctly update skb->csum for CHECKSUM_COMPLETE packets, triggering infamous "hw csum failure" messages and stack traces. Signed-off-by: Eric Dumazet Acked-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h index 84b2083..0dc0a51 100644 --- a/include/net/inet_ecn.h +++ b/include/net/inet_ecn.h @@ -111,11 +111,24 @@ static inline void ipv4_copy_dscp(unsigned int dscp, struct iphdr *inner) struct ipv6hdr; -static inline int IP6_ECN_set_ce(struct ipv6hdr *iph) +/* Note: + * IP_ECN_set_ce() has to tweak IPV4 checksum when setting CE, + * meaning both changes have no effect on skb->csum if/when CHECKSUM_COMPLETE + * In IPv6 case, no checksum compensates the change in IPv6 header, + * so we have to update skb->csum. + */ +static inline int IP6_ECN_set_ce(struct sk_buff *skb, struct ipv6hdr *iph) { + __be32 from, to; + if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph))) return 0; - *(__be32*)iph |= htonl(INET_ECN_CE << 20); + + from = *(__be32 *)iph; + to = from | htonl(INET_ECN_CE << 20); + *(__be32 *)iph = to; + if (skb->ip_summed == CHECKSUM_COMPLETE) + skb->csum = csum_add(csum_sub(skb->csum, from), to); return 1; } @@ -142,7 +155,7 @@ static inline int INET_ECN_set_ce(struct sk_buff *skb) case cpu_to_be16(ETH_P_IPV6): if (skb_network_header(skb) + sizeof(struct ipv6hdr) <= skb_tail_pointer(skb)) - return IP6_ECN_set_ce(ipv6_hdr(skb)); + return IP6_ECN_set_ce(skb, ipv6_hdr(skb)); break; } diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index f7fbdba..372855e 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c @@ -23,7 +23,7 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) struct ipv6hdr *inner_iph = ipipv6_hdr(skb); if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos)) - IP6_ECN_set_ce(inner_iph); + IP6_ECN_set_ce(skb, inner_iph); } /* Add encapsulation header. -- cgit v0.10.2 From fb3311853c0f23391fc3441d49a46d076de57757 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 15 Jan 2016 14:44:31 +0100 Subject: net: sctp: Move sequence start handling into sctp_transport_get_idx() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net/sctp/proc.c: In function ‘sctp_transport_get_idx’: net/sctp/proc.c:313: warning: ‘obj’ may be used uninitialized in this function This is currently a false positive, as all callers check for a zero offset first, and handle this case in the exact same way. Move the check and handling into sctp_transport_get_idx() to kill the compiler warning, and avoid future bugs. Signed-off-by: Geert Uytterhoeven Acked-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller diff --git a/net/sctp/proc.c b/net/sctp/proc.c index dfa7eec..684c5b3 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -310,7 +310,7 @@ static struct sctp_transport *sctp_transport_get_next(struct seq_file *seq) static struct sctp_transport *sctp_transport_get_idx(struct seq_file *seq, loff_t pos) { - void *obj; + void *obj = SEQ_START_TOKEN; while (pos && (obj = sctp_transport_get_next(seq)) && !IS_ERR(obj)) pos--; @@ -347,7 +347,7 @@ static void *sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos) if (err) return ERR_PTR(err); - return *pos ? sctp_transport_get_idx(seq, *pos) : SEQ_START_TOKEN; + return sctp_transport_get_idx(seq, *pos); } static void sctp_assocs_seq_stop(struct seq_file *seq, void *v) @@ -462,7 +462,7 @@ static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos) if (err) return ERR_PTR(err); - return *pos ? sctp_transport_get_idx(seq, *pos) : SEQ_START_TOKEN; + return sctp_transport_get_idx(seq, *pos); } static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos) -- cgit v0.10.2 From 99a2dea50d5deff134b6c346f53a3ad1f583ee96 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Fri, 15 Jan 2016 14:55:34 +0000 Subject: xen-netback: use skb to determine number of required guest Rx requests Using the MTU or GSO size to determine the number of required guest Rx requests for an skb was subtly broken since these value may change at runtime. After 1650d5455bd2dc6b5ee134bd6fc1a3236c266b5b (xen-netback: always fully coalesce guest Rx packets) we always fully pack a packet into its guest Rx slots. Calculating the number of required slots from the packet length is then easy. Signed-off-by: David Vrabel Signed-off-by: David S. Miller diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 1049c34..61b97c3 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -149,20 +149,19 @@ static inline pending_ring_idx_t pending_index(unsigned i) return i & (MAX_PENDING_REQS-1); } -static int xenvif_rx_ring_slots_needed(struct xenvif *vif) -{ - if (vif->gso_mask) - return DIV_ROUND_UP(vif->dev->gso_max_size, XEN_PAGE_SIZE) + 1; - else - return DIV_ROUND_UP(vif->dev->mtu, XEN_PAGE_SIZE); -} - static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) { RING_IDX prod, cons; + struct sk_buff *skb; int needed; - needed = xenvif_rx_ring_slots_needed(queue->vif); + skb = skb_peek(&queue->rx_queue); + if (!skb) + return false; + + needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE); + if (skb_is_gso(skb)) + needed++; do { prod = queue->rx.sring->req_prod; @@ -2005,8 +2004,7 @@ static bool xenvif_rx_queue_ready(struct xenvif_queue *queue) static bool xenvif_have_rx_work(struct xenvif_queue *queue) { - return (!skb_queue_empty(&queue->rx_queue) - && xenvif_rx_ring_slots_available(queue)) + return xenvif_rx_ring_slots_available(queue) || (queue->vif->stall_timeout && (xenvif_rx_queue_stalled(queue) || xenvif_rx_queue_ready(queue))) -- cgit v0.10.2 From 4a658527271bce43afb1cf4feec89afe6716ca59 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Fri, 15 Jan 2016 14:55:35 +0000 Subject: xen-netback: delete NAPI instance when queue fails to initialize When xenvif_connect() fails it may leave a stale NAPI instance added to the device. Make sure we delete it in the error path. Signed-off-by: David Vrabel Signed-off-by: David S. Miller diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index e7bd63e..3bba6ce 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -615,6 +615,7 @@ err_tx_unbind: queue->tx_irq = 0; err_unmap: xenvif_unmap_frontend_rings(queue); + netif_napi_del(&queue->napi); err: module_put(THIS_MODULE); return err; -- cgit v0.10.2 From 9c6f3ffe8200327d1cf2aad2ff2b414adaacbe96 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Fri, 15 Jan 2016 14:55:36 +0000 Subject: xen-netback: free queues after freeing the net device If a queue still has a NAPI instance added to the net device, freeing the queues early results in a use-after-free. The shouldn't ever happen because we disconnect and tear down all queues before freeing the net device, but doing this makes it obviously safe. Signed-off-by: David Vrabel Signed-off-by: David S. Miller diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 3bba6ce..f5231a2 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -685,22 +685,16 @@ void xenvif_deinit_queue(struct xenvif_queue *queue) void xenvif_free(struct xenvif *vif) { - struct xenvif_queue *queue = NULL; + struct xenvif_queue *queues = vif->queues; unsigned int num_queues = vif->num_queues; unsigned int queue_index; unregister_netdev(vif->dev); - - for (queue_index = 0; queue_index < num_queues; ++queue_index) { - queue = &vif->queues[queue_index]; - xenvif_deinit_queue(queue); - } - - vfree(vif->queues); - vif->queues = NULL; - vif->num_queues = 0; - free_netdev(vif->dev); + for (queue_index = 0; queue_index < num_queues; ++queue_index) + xenvif_deinit_queue(&queues[queue_index]); + vfree(queues); + module_put(THIS_MODULE); } -- cgit v0.10.2 From f147d0b320f02e799a8eec4b95f9f989f65b8a34 Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Sat, 16 Jan 2016 00:05:09 +0900 Subject: net: smsc: Add support h8300 Add H8/300 platform support for smc91x Signed-off-by: Yoshinori Sato Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/smsc/Kconfig b/drivers/net/ethernet/smsc/Kconfig index eb9230e..63aca9f 100644 --- a/drivers/net/ethernet/smsc/Kconfig +++ b/drivers/net/ethernet/smsc/Kconfig @@ -7,7 +7,7 @@ config NET_VENDOR_SMSC default y depends on ARM || ARM64 || ATARI_ETHERNAT || BLACKFIN || COLDFIRE || \ ISA || M32R || MAC || MIPS || MN10300 || NIOS2 || PCI || \ - PCMCIA || SUPERH || XTENSA + PCMCIA || SUPERH || XTENSA || H8300 ---help--- If you have a network (Ethernet) card belonging to this class, say Y. @@ -38,7 +38,7 @@ config SMC91X select MII depends on !OF || GPIOLIB depends on ARM || ARM64 || ATARI_ETHERNAT || BLACKFIN || COLDFIRE || \ - M32R || MIPS || MN10300 || NIOS2 || SUPERH || XTENSA + M32R || MIPS || MN10300 || NIOS2 || SUPERH || XTENSA || H8300 ---help--- This is a driver for SMC's 91x series of Ethernet chipsets, including the SMC91C94 and the SMC91C111. Say Y if you want it diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index a3c129e..1a55c79 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -172,6 +172,17 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l) #define SMC_IRQ_FLAGS 0 +#elif defined(CONFIG_H8300) +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 0 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 0 + +#define SMC_inb(a, r) ioread8((a) + (r)) +#define SMC_outb(v, a, r) iowrite8(v, (a) + (r)) +#define SMC_insb(a, r, p, l) ioread8_rep((a) + (r), p, l) +#define SMC_outsb(a, r, p, l) iowrite8_rep((a) + (r), p, l) + #else /* -- cgit v0.10.2 From c6894dec8ea9ae05747124dce98b3b5c2e69b168 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Fri, 15 Jan 2016 19:03:54 +0100 Subject: bridge: fix lockdep addr_list_lock false positive splat After promisc mode management was introduced a bridge device could do dev_set_promiscuity from its ndo_change_rx_flags() callback which in turn can be called after the bridge's addr_list_lock has been taken (e.g. by dev_uc_add). This causes a false positive lockdep splat because the port interfaces' addr_list_lock is taken when br_manage_promisc() runs after the bridge's addr list lock was already taken. To remove the false positive introduce a custom bridge addr_list_lock class and set it on bridge init. A simple way to reproduce this is with the following: $ brctl addbr br0 $ ip l add l br0 br0.100 type vlan id 100 $ ip l set br0 up $ ip l set br0.100 up $ echo 1 > /sys/class/net/br0/bridge/vlan_filtering $ brctl addif br0 eth0 Splat: [ 43.684325] ============================================= [ 43.684485] [ INFO: possible recursive locking detected ] [ 43.684636] 4.4.0-rc8+ #54 Not tainted [ 43.684755] --------------------------------------------- [ 43.684906] brctl/1187 is trying to acquire lock: [ 43.685047] (_xmit_ETHER){+.....}, at: [] dev_set_rx_mode+0x1e/0x40 [ 43.685460] but task is already holding lock: [ 43.685618] (_xmit_ETHER){+.....}, at: [] dev_uc_add+0x27/0x80 [ 43.686015] other info that might help us debug this: [ 43.686316] Possible unsafe locking scenario: [ 43.686743] CPU0 [ 43.686967] ---- [ 43.687197] lock(_xmit_ETHER); [ 43.687544] lock(_xmit_ETHER); [ 43.687886] *** DEADLOCK *** [ 43.688438] May be due to missing lock nesting notation [ 43.688882] 2 locks held by brctl/1187: [ 43.689134] #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_lock+0x17/0x20 [ 43.689852] #1: (_xmit_ETHER){+.....}, at: [] dev_uc_add+0x27/0x80 [ 43.690575] stack backtrace: [ 43.690970] CPU: 0 PID: 1187 Comm: brctl Not tainted 4.4.0-rc8+ #54 [ 43.691270] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.8.1-20150318_183358- 04/01/2014 [ 43.691770] ffffffff826a25c0 ffff8800369fb8e0 ffffffff81360ceb ffffffff826a25c0 [ 43.692425] ffff8800369fb9b8 ffffffff810d0466 ffff8800369fb968 ffffffff81537139 [ 43.693071] ffff88003a08c880 0000000000000000 00000000ffffffff 0000000002080020 [ 43.693709] Call Trace: [ 43.693931] [] dump_stack+0x4b/0x70 [ 43.694199] [] __lock_acquire+0x1e46/0x1e90 [ 43.694483] [] ? netlink_broadcast_filtered+0x139/0x3e0 [ 43.694789] [] ? nlmsg_notify+0x5a/0xc0 [ 43.695064] [] lock_acquire+0xe5/0x1f0 [ 43.695340] [] ? dev_set_rx_mode+0x1e/0x40 [ 43.695623] [] _raw_spin_lock_bh+0x45/0x80 [ 43.695901] [] ? dev_set_rx_mode+0x1e/0x40 [ 43.696180] [] dev_set_rx_mode+0x1e/0x40 [ 43.696460] [] dev_set_promiscuity+0x3c/0x50 [ 43.696750] [] br_port_set_promisc+0x25/0x50 [bridge] [ 43.697052] [] br_manage_promisc+0x8a/0xe0 [bridge] [ 43.697348] [] br_dev_change_rx_flags+0x1e/0x20 [bridge] [ 43.697655] [] __dev_set_promiscuity+0x132/0x1f0 [ 43.697943] [] __dev_set_rx_mode+0x82/0x90 [ 43.698223] [] dev_uc_add+0x5e/0x80 [ 43.698498] [] vlan_device_event+0x542/0x650 [8021q] [ 43.698798] [] notifier_call_chain+0x5d/0x80 [ 43.699083] [] raw_notifier_call_chain+0x16/0x20 [ 43.699374] [] call_netdevice_notifiers_info+0x6e/0x80 [ 43.699678] [] call_netdevice_notifiers+0x16/0x20 [ 43.699973] [] br_add_if+0x47e/0x4c0 [bridge] [ 43.700259] [] add_del_if+0x6e/0x80 [bridge] [ 43.700548] [] br_dev_ioctl+0xaf/0xc0 [bridge] [ 43.700836] [] dev_ifsioc+0x30c/0x3c0 [ 43.701106] [] dev_ioctl+0xf9/0x6f0 [ 43.701379] [] ? mntput_no_expire+0x5/0x450 [ 43.701665] [] ? mntput_no_expire+0xae/0x450 [ 43.701947] [] sock_do_ioctl+0x42/0x50 [ 43.702219] [] sock_ioctl+0x1e5/0x290 [ 43.702500] [] do_vfs_ioctl+0x2cb/0x5c0 [ 43.702771] [] SyS_ioctl+0x79/0x90 [ 43.703033] [] entry_SYSCALL_64_fastpath+0x16/0x7a CC: Vlad Yasevich CC: Stephen Hemminger CC: Bridge list CC: Andy Gospodarek CC: Roopa Prabhu Fixes: 2796d0c648c9 ("bridge: Automatically manage port promiscuous mode.") Reported-by: Andy Gospodarek Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 5e88d3e..2c8095a 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -28,6 +28,8 @@ const struct nf_br_ops __rcu *nf_br_ops __read_mostly; EXPORT_SYMBOL_GPL(nf_br_ops); +static struct lock_class_key bridge_netdev_addr_lock_key; + /* net device transmit always called with BH disabled */ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -87,6 +89,11 @@ out: return NETDEV_TX_OK; } +static void br_set_lockdep_class(struct net_device *dev) +{ + lockdep_set_class(&dev->addr_list_lock, &bridge_netdev_addr_lock_key); +} + static int br_dev_init(struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); @@ -99,6 +106,7 @@ static int br_dev_init(struct net_device *dev) err = br_vlan_init(br); if (err) free_percpu(br->stats); + br_set_lockdep_class(dev); return err; } -- cgit v0.10.2 From 750afbf8ee9c6a1c74a1fe5fc9852146b1d72687 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 15 Jan 2016 16:07:13 -0500 Subject: bgmac: Fix reversed test of build_skb() return value. Fixes: f1640c3ddeec ("bgmac: fix a missing check for build_skb") Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 3974152..06f6cff 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -466,7 +466,7 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, len -= ETH_FCS_LEN; skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE); - if (unlikely(skb)) { + if (unlikely(!skb)) { bgmac_err(bgmac, "build_skb failed\n"); put_page(virt_to_head_page(buf)); break; -- cgit v0.10.2