Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorDavid S. Miller <davem@davemloft.net>
Wed, 24 Jun 2015 09:58:51 +0000 (02:58 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 24 Jun 2015 09:58:51 +0000 (02:58 -0700)
Conflicts:
drivers/net/ethernet/mellanox/mlx4/main.c
net/packet/af_packet.c

Both conflicts were cases of simple overlapping changes.

Signed-off-by: David S. Miller <davem@davemloft.net>
29 files changed:
drivers/isdn/hisax/Kconfig
drivers/net/can/dev.c
drivers/net/can/slcan.c
drivers/net/can/vcan.c
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/rocker/rocker.c
drivers/net/ethernet/stmicro/stmmac/descs.h
drivers/net/ethernet/stmicro/stmmac/enh_desc.c
drivers/net/ethernet/stmicro/stmmac/norm_desc.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/xen-netback/xenbus.c
include/net/netns/sctp.h
include/net/sctp/structs.h
net/bridge/br_ioctl.c
net/bridge/br_multicast.c
net/bridge/br_stp_if.c
net/can/af_can.c
net/core/neighbour.c
net/ipv4/af_inet.c
net/ipv4/ip_sockglue.c
net/ipv4/tcp.c
net/ipv4/tcp_fastopen.c
net/ipv6/datagram.c
net/mac80211/key.c
net/packet/af_packet.c
net/rose/af_rose.c
net/sctp/socket.c

index 97465ac..eb83d94 100644 (file)
@@ -237,7 +237,7 @@ config HISAX_MIC
 
 config HISAX_NETJET
        bool "NETjet card"
-       depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
+       depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN) || MICROBLAZE))
        depends on VIRT_TO_BUS
        help
          This enables HiSax support for the NetJet from Traverse
@@ -249,7 +249,7 @@ config HISAX_NETJET
 
 config HISAX_NETJET_U
        bool "NETspider U card"
-       depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
+       depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN) || MICROBLAZE))
        depends on VIRT_TO_BUS
        help
          This enables HiSax support for the Netspider U interface ISDN card
index b0f6924..e9b1810 100644 (file)
@@ -440,6 +440,9 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
                struct can_frame *cf = (struct can_frame *)skb->data;
                u8 dlc = cf->can_dlc;
 
+               if (!(skb->tstamp.tv64))
+                       __net_timestamp(skb);
+
                netif_rx(priv->echo_skb[idx]);
                priv->echo_skb[idx] = NULL;
 
@@ -575,6 +578,7 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
        if (unlikely(!skb))
                return NULL;
 
+       __net_timestamp(skb);
        skb->protocol = htons(ETH_P_CAN);
        skb->pkt_type = PACKET_BROADCAST;
        skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -603,6 +607,7 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
        if (unlikely(!skb))
                return NULL;
 
+       __net_timestamp(skb);
        skb->protocol = htons(ETH_P_CANFD);
        skb->pkt_type = PACKET_BROADCAST;
        skb->ip_summed = CHECKSUM_UNNECESSARY;
index c837eb9..f64f529 100644 (file)
@@ -207,6 +207,7 @@ static void slc_bump(struct slcan *sl)
        if (!skb)
                return;
 
+       __net_timestamp(skb);
        skb->dev = sl->dev;
        skb->protocol = htons(ETH_P_CAN);
        skb->pkt_type = PACKET_BROADCAST;
index 674f367..0ce868d 100644 (file)
@@ -78,6 +78,9 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
        skb->dev       = dev;
        skb->ip_summed = CHECKSUM_UNNECESSARY;
 
+       if (!(skb->tstamp.tv64))
+               __net_timestamp(skb);
+
        netif_rx_ni(skb);
 }
 
index c5f299d..56316db 100644 (file)
@@ -487,6 +487,9 @@ static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
 {
        struct sk_buff *new_skb;
 
+       if (skb_linearize(skb))
+               return NULL;
+
        /* Alloc new skb */
        new_skb = netdev_alloc_skb(dev, skb->len + 4);
        if (!new_skb)
@@ -512,12 +515,27 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        cbd_t __iomem *bdp;
        int curidx;
        u16 sc;
-       int nr_frags = skb_shinfo(skb)->nr_frags;
+       int nr_frags;
        skb_frag_t *frag;
        int len;
-
 #ifdef CONFIG_FS_ENET_MPC5121_FEC
-       if (((unsigned long)skb->data) & 0x3) {
+       int is_aligned = 1;
+       int i;
+
+       if (!IS_ALIGNED((unsigned long)skb->data, 4)) {
+               is_aligned = 0;
+       } else {
+               nr_frags = skb_shinfo(skb)->nr_frags;
+               frag = skb_shinfo(skb)->frags;
+               for (i = 0; i < nr_frags; i++, frag++) {
+                       if (!IS_ALIGNED(frag->page_offset, 4)) {
+                               is_aligned = 0;
+                               break;
+                       }
+               }
+       }
+
+       if (!is_aligned) {
                skb = tx_skb_align_workaround(dev, skb);
                if (!skb) {
                        /*
@@ -529,6 +547,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
                }
        }
 #endif
+
        spin_lock(&fep->tx_lock);
 
        /*
@@ -536,6 +555,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
         */
        bdp = fep->cur_tx;
 
+       nr_frags = skb_shinfo(skb)->nr_frags;
        if (fep->tx_free <= nr_frags || (CBDR_SC(bdp) & BD_ENET_TX_READY)) {
                netif_stop_queue(dev);
                spin_unlock(&fep->tx_lock);
index ecce826..5bdf782 100644 (file)
@@ -1013,6 +1013,12 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
                val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
                val |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
                mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val);
+       } else {
+               val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
+               val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE |
+                      MVNETA_GMAC_AN_SPEED_EN |
+                      MVNETA_GMAC_AN_DUPLEX_EN);
+               mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
        }
 
        mvneta_set_ucast_table(pp, -1);
index 4e69cf5..33e68b1 100644 (file)
@@ -479,6 +479,14 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
                }
        }
 
+       if (mlx4_is_master(dev) && (dev->caps.num_ports == 2) &&
+           (port_type_array[0] == MLX4_PORT_TYPE_IB) &&
+           (port_type_array[1] == MLX4_PORT_TYPE_ETH)) {
+               mlx4_warn(dev,
+                         "Granular QoS per VF not supported with IB/Eth configuration\n");
+               dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_QOS_VPP;
+       }
+
        dev->caps.max_counters = dev_cap->max_counters;
 
        dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps;
index 83e913b..2d8578c 100644 (file)
@@ -5297,7 +5297,7 @@ static int __init rocker_module_init(void)
        return 0;
 
 err_pci_register_driver:
-       unregister_netdevice_notifier(&rocker_netevent_nb);
+       unregister_netevent_notifier(&rocker_netevent_nb);
        unregister_netdevice_notifier(&rocker_netdevice_nb);
        return err;
 }
index ad39960..799c292 100644 (file)
@@ -158,6 +158,8 @@ struct dma_desc {
                        u32 buffer2_size:13;
                        u32 reserved4:3;
                } etx;          /* -- enhanced -- */
+
+               u64 all_flags;
        } des01;
        unsigned int des2;
        unsigned int des3;
index 1e2bcf5..7d94444 100644 (file)
@@ -240,6 +240,7 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x,
 static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
                                  int mode, int end)
 {
+       p->des01.all_flags = 0;
        p->des01.erx.own = 1;
        p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1;
 
@@ -254,7 +255,7 @@ static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
 
 static void enh_desc_init_tx_desc(struct dma_desc *p, int mode, int end)
 {
-       p->des01.etx.own = 0;
+       p->des01.all_flags = 0;
        if (mode == STMMAC_CHAIN_MODE)
                ehn_desc_tx_set_on_chain(p, end);
        else
index 35ad4f4..48c3456 100644 (file)
@@ -123,6 +123,7 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
 static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode,
                               int end)
 {
+       p->des01.all_flags = 0;
        p->des01.rx.own = 1;
        p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1;
 
@@ -137,7 +138,7 @@ static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode,
 
 static void ndesc_init_tx_desc(struct dma_desc *p, int mode, int end)
 {
-       p->des01.tx.own = 0;
+       p->des01.all_flags = 0;
        if (mode == STMMAC_CHAIN_MODE)
                ndesc_tx_set_on_chain(p, end);
        else
index a515673..50f7a7a 100644 (file)
@@ -1195,41 +1195,41 @@ static int alloc_dma_desc_resources(struct stmmac_priv *priv)
                goto err_tx_skbuff;
 
        if (priv->extend_desc) {
-               priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
-                                                  sizeof(struct
-                                                         dma_extended_desc),
-                                                  &priv->dma_rx_phy,
-                                                  GFP_KERNEL);
+               priv->dma_erx = dma_zalloc_coherent(priv->device, rxsize *
+                                                   sizeof(struct
+                                                          dma_extended_desc),
+                                                   &priv->dma_rx_phy,
+                                                   GFP_KERNEL);
                if (!priv->dma_erx)
                        goto err_dma;
 
-               priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
-                                                  sizeof(struct
-                                                         dma_extended_desc),
-                                                  &priv->dma_tx_phy,
-                                                  GFP_KERNEL);
+               priv->dma_etx = dma_zalloc_coherent(priv->device, txsize *
+                                                   sizeof(struct
+                                                          dma_extended_desc),
+                                                   &priv->dma_tx_phy,
+                                                   GFP_KERNEL);
                if (!priv->dma_etx) {
                        dma_free_coherent(priv->device, priv->dma_rx_size *
-                                       sizeof(struct dma_extended_desc),
-                                       priv->dma_erx, priv->dma_rx_phy);
+                                         sizeof(struct dma_extended_desc),
+                                         priv->dma_erx, priv->dma_rx_phy);
                        goto err_dma;
                }
        } else {
-               priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
-                                                 sizeof(struct dma_desc),
-                                                 &priv->dma_rx_phy,
-                                                 GFP_KERNEL);
+               priv->dma_rx = dma_zalloc_coherent(priv->device, rxsize *
+                                                  sizeof(struct dma_desc),
+                                                  &priv->dma_rx_phy,
+                                                  GFP_KERNEL);
                if (!priv->dma_rx)
                        goto err_dma;
 
-               priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
-                                                 sizeof(struct dma_desc),
-                                                 &priv->dma_tx_phy,
-                                                 GFP_KERNEL);
+               priv->dma_tx = dma_zalloc_coherent(priv->device, txsize *
+                                                  sizeof(struct dma_desc),
+                                                  &priv->dma_tx_phy,
+                                                  GFP_KERNEL);
                if (!priv->dma_tx) {
                        dma_free_coherent(priv->device, priv->dma_rx_size *
-                                       sizeof(struct dma_desc),
-                                       priv->dma_rx, priv->dma_rx_phy);
+                                         sizeof(struct dma_desc),
+                                         priv->dma_rx, priv->dma_rx_phy);
                        goto err_dma;
                }
        }
index 968787a..ec383b0 100644 (file)
@@ -681,6 +681,9 @@ static int xen_register_watchers(struct xenbus_device *dev, struct xenvif *vif)
        char *node;
        unsigned maxlen = strlen(dev->nodename) + sizeof("/rate");
 
+       if (vif->credit_watch.node)
+               return -EADDRINUSE;
+
        node = kmalloc(maxlen, GFP_KERNEL);
        if (!node)
                return -ENOMEM;
@@ -770,6 +773,7 @@ static void connect(struct backend_info *be)
        }
 
        xen_net_read_rate(dev, &credit_bytes, &credit_usec);
+       xen_unregister_watchers(be->vif);
        xen_register_watchers(dev, be->vif);
        read_xenbus_vif_flags(be);
 
index 3573a81..8ba379f 100644 (file)
@@ -31,6 +31,7 @@ struct netns_sctp {
        struct list_head addr_waitq;
        struct timer_list addr_wq_timer;
        struct list_head auto_asconf_splist;
+       /* Lock that protects both addr_waitq and auto_asconf_splist */
        spinlock_t addr_wq_lock;
 
        /* Lock that protects the local_addr_list writers */
index 2bb2fcf..495c87e 100644 (file)
@@ -223,6 +223,10 @@ struct sctp_sock {
        atomic_t pd_mode;
        /* Receive to here while partial delivery is in effect. */
        struct sk_buff_head pd_lobby;
+
+       /* These must be the last fields, as they will skipped on copies,
+        * like on accept and peeloff operations
+        */
        struct list_head auto_asconf_list;
        int do_auto_asconf;
 };
index a9a4a1b..8d423bc 100644 (file)
@@ -247,9 +247,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
-               spin_lock_bh(&br->lock);
                br_stp_set_bridge_priority(br, args[1]);
-               spin_unlock_bh(&br->lock);
                return 0;
 
        case BRCTL_SET_PORT_PRIORITY:
index 2e246a1..742a6c2 100644 (file)
@@ -37,6 +37,8 @@
 
 static void br_multicast_start_querier(struct net_bridge *br,
                                       struct bridge_mcast_own_query *query);
+static void br_multicast_add_router(struct net_bridge *br,
+                                   struct net_bridge_port *port);
 unsigned int br_mdb_rehash_seq;
 
 static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
@@ -936,6 +938,8 @@ void br_multicast_enable_port(struct net_bridge_port *port)
 #if IS_ENABLED(CONFIG_IPV6)
        br_multicast_enable(&port->ip6_own_query);
 #endif
+       if (port->multicast_router == 2 && hlist_unhashed(&port->rlist))
+               br_multicast_add_router(br, port);
 
 out:
        spin_unlock(&br->multicast_lock);
index 4114687..7832d07 100644 (file)
@@ -243,12 +243,13 @@ bool br_stp_recalculate_bridge_id(struct net_bridge *br)
        return true;
 }
 
-/* called under bridge lock */
+/* Acquires and releases bridge lock */
 void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio)
 {
        struct net_bridge_port *p;
        int wasroot;
 
+       spin_lock_bh(&br->lock);
        wasroot = br_is_root_bridge(br);
 
        list_for_each_entry(p, &br->port_list, list) {
@@ -266,6 +267,7 @@ void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio)
        br_port_state_selection(br);
        if (br_is_root_bridge(br) && !wasroot)
                br_become_root_bridge(br);
+       spin_unlock_bh(&br->lock);
 }
 
 /* called under bridge lock */
index d4d404b..7933e62 100644 (file)
@@ -310,8 +310,12 @@ int can_send(struct sk_buff *skb, int loop)
                return err;
        }
 
-       if (newskb)
+       if (newskb) {
+               if (!(newskb->tstamp.tv64))
+                       __net_timestamp(newskb);
+
                netif_rx_ni(newskb);
+       }
 
        /* update statistics */
        can_stats.tx_frames++;
index 3a74df7..84195da 100644 (file)
@@ -958,6 +958,8 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
        rc = 0;
        if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
                goto out_unlock_bh;
+       if (neigh->dead)
+               goto out_dead;
 
        if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
                if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
@@ -1014,6 +1016,13 @@ out_unlock_bh:
                write_unlock(&neigh->lock);
        local_bh_enable();
        return rc;
+
+out_dead:
+       if (neigh->nud_state & NUD_STALE)
+               goto out_unlock_bh;
+       write_unlock_bh(&neigh->lock);
+       kfree_skb(skb);
+       return 1;
 }
 EXPORT_SYMBOL(__neigh_event_send);
 
@@ -1077,6 +1086,8 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
        if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
            (old & (NUD_NOARP | NUD_PERMANENT)))
                goto out;
+       if (neigh->dead)
+               goto out;
 
        if (!(new & NUD_VALID)) {
                neigh_del_timer(neigh);
@@ -1228,6 +1239,8 @@ EXPORT_SYMBOL(neigh_update);
  */
 void __neigh_set_probe_once(struct neighbour *neigh)
 {
+       if (neigh->dead)
+               return;
        neigh->updated = jiffies;
        if (!(neigh->nud_state & NUD_FAILED))
                return;
index cc858ef..9532ee8 100644 (file)
@@ -228,6 +228,8 @@ int inet_listen(struct socket *sock, int backlog)
                                err = 0;
                        if (err)
                                goto out;
+
+                       tcp_fastopen_init_key_once(true);
                }
                err = inet_csk_listen_start(sk, backlog);
                if (err)
index 04ae299..c3c359a 100644 (file)
@@ -432,6 +432,15 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf
                kfree_skb(skb);
 }
 
+/* For some errors we have valid addr_offset even with zero payload and
+ * zero port. Also, addr_offset should be supported if port is set.
+ */
+static inline bool ipv4_datagram_support_addr(struct sock_exterr_skb *serr)
+{
+       return serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
+              serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL || serr->port;
+}
+
 /* IPv4 supports cmsg on all imcp errors and some timestamps
  *
  * Timestamp code paths do not initialize the fields expected by cmsg:
@@ -498,7 +507,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 
        serr = SKB_EXT_ERR(skb);
 
-       if (sin && serr->port) {
+       if (sin && ipv4_datagram_support_addr(serr)) {
                sin->sin_family = AF_INET;
                sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) +
                                                   serr->addr_offset);
index 697b86d..7f40567 100644 (file)
@@ -2573,10 +2573,13 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
 
        case TCP_FASTOPEN:
                if (val >= 0 && ((1 << sk->sk_state) & (TCPF_CLOSE |
-                   TCPF_LISTEN)))
+                   TCPF_LISTEN))) {
+                       tcp_fastopen_init_key_once(true);
+
                        err = fastopen_init_queue(sk, val);
-               else
+               } else {
                        err = -EINVAL;
+               }
                break;
        case TCP_TIMESTAMP:
                if (!tp->repair)
index 46b087a..f9c0fb8 100644 (file)
@@ -78,8 +78,6 @@ static bool __tcp_fastopen_cookie_gen(const void *path,
        struct tcp_fastopen_context *ctx;
        bool ok = false;
 
-       tcp_fastopen_init_key_once(true);
-
        rcu_read_lock();
        ctx = rcu_dereference(tcp_fastopen_ctx);
        if (ctx) {
index 762a58c..62d908e 100644 (file)
@@ -325,6 +325,16 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu)
        kfree_skb(skb);
 }
 
+/* For some errors we have valid addr_offset even with zero payload and
+ * zero port. Also, addr_offset should be supported if port is set.
+ */
+static inline bool ipv6_datagram_support_addr(struct sock_exterr_skb *serr)
+{
+       return serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6 ||
+              serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
+              serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL || serr->port;
+}
+
 /* IPv6 supports cmsg on all origins aside from SO_EE_ORIGIN_LOCAL.
  *
  * At one point, excluding local errors was a quick test to identify icmp/icmp6
@@ -389,7 +399,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 
        serr = SKB_EXT_ERR(skb);
 
-       if (sin && serr->port) {
+       if (sin && ipv6_datagram_support_addr(serr)) {
                const unsigned char *nh = skb_network_header(skb);
                sin->sin6_family = AF_INET6;
                sin->sin6_flowinfo = 0;
index 8abc31e..b22df3a 100644 (file)
@@ -66,12 +66,15 @@ update_vlan_tailroom_need_count(struct ieee80211_sub_if_data *sdata, int delta)
        if (sdata->vif.type != NL80211_IFTYPE_AP)
                return;
 
-       mutex_lock(&sdata->local->mtx);
+       /* crypto_tx_tailroom_needed_cnt is protected by this */
+       assert_key_lock(sdata->local);
+
+       rcu_read_lock();
 
-       list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+       list_for_each_entry_rcu(vlan, &sdata->u.ap.vlans, u.vlan.list)
                vlan->crypto_tx_tailroom_needed_cnt += delta;
 
-       mutex_unlock(&sdata->local->mtx);
+       rcu_read_unlock();
 }
 
 static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
@@ -95,6 +98,8 @@ static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
         * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net
         */
 
+       assert_key_lock(sdata->local);
+
        update_vlan_tailroom_need_count(sdata, 1);
 
        if (!sdata->crypto_tx_tailroom_needed_cnt++) {
@@ -109,6 +114,8 @@ static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
 static void decrease_tailroom_need_count(struct ieee80211_sub_if_data *sdata,
                                         int delta)
 {
+       assert_key_lock(sdata->local);
+
        WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt < delta);
 
        update_vlan_tailroom_need_count(sdata, -delta);
index f5c8703..c9e8741 100644 (file)
@@ -1322,16 +1322,6 @@ static void packet_sock_destruct(struct sock *sk)
        sk_refcnt_debug_dec(sk);
 }
 
-static int fanout_rr_next(struct packet_fanout *f, unsigned int num)
-{
-       int x = atomic_read(&f->rr_cur) + 1;
-
-       if (x >= num)
-               x = 0;
-
-       return x;
-}
-
 static bool fanout_flow_is_huge(struct packet_sock *po, struct sk_buff *skb)
 {
        u32 rxhash;
@@ -1357,13 +1347,9 @@ static unsigned int fanout_demux_lb(struct packet_fanout *f,
                                    struct sk_buff *skb,
                                    unsigned int num)
 {
-       int cur, old;
+       unsigned int val = atomic_inc_return(&f->rr_cur);
 
-       cur = atomic_read(&f->rr_cur);
-       while ((old = atomic_cmpxchg(&f->rr_cur, cur,
-                                    fanout_rr_next(f, num))) != cur)
-               cur = old;
-       return cur;
+       return val % num;
 }
 
 static unsigned int fanout_demux_cpu(struct packet_fanout *f,
@@ -1435,7 +1421,7 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
                             struct packet_type *pt, struct net_device *orig_dev)
 {
        struct packet_fanout *f = pt->af_packet_priv;
-       unsigned int num = f->num_members;
+       unsigned int num = READ_ONCE(f->num_members);
        struct packet_sock *po;
        unsigned int idx;
 
index 36dbc2d..129d357 100644 (file)
@@ -192,7 +192,8 @@ static void rose_kill_by_device(struct net_device *dev)
 
                if (rose->device == dev) {
                        rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
-                       rose->neighbour->use--;
+                       if (rose->neighbour)
+                               rose->neighbour->use--;
                        rose->device = NULL;
                }
        }
index f09de7f..5f6c4e6 100644 (file)
@@ -1528,8 +1528,10 @@ static void sctp_close(struct sock *sk, long timeout)
 
        /* Supposedly, no process has access to the socket, but
         * the net layers still may.
+        * Also, sctp_destroy_sock() needs to be called with addr_wq_lock
+        * held and that should be grabbed before socket lock.
         */
-       local_bh_disable();
+       spin_lock_bh(&net->sctp.addr_wq_lock);
        bh_lock_sock(sk);
 
        /* Hold the sock, since sk_common_release() will put sock_put()
@@ -1539,7 +1541,7 @@ static void sctp_close(struct sock *sk, long timeout)
        sk_common_release(sk);
 
        bh_unlock_sock(sk);
-       local_bh_enable();
+       spin_unlock_bh(&net->sctp.addr_wq_lock);
 
        sock_put(sk);
 
@@ -3580,6 +3582,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
        if ((val && sp->do_auto_asconf) || (!val && !sp->do_auto_asconf))
                return 0;
 
+       spin_lock_bh(&sock_net(sk)->sctp.addr_wq_lock);
        if (val == 0 && sp->do_auto_asconf) {
                list_del(&sp->auto_asconf_list);
                sp->do_auto_asconf = 0;
@@ -3588,6 +3591,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
                    &sock_net(sk)->sctp.auto_asconf_splist);
                sp->do_auto_asconf = 1;
        }
+       spin_unlock_bh(&sock_net(sk)->sctp.addr_wq_lock);
        return 0;
 }
 
@@ -4121,18 +4125,28 @@ static int sctp_init_sock(struct sock *sk)
        local_bh_disable();
        percpu_counter_inc(&sctp_sockets_allocated);
        sock_prot_inuse_add(net, sk->sk_prot, 1);
+
+       /* Nothing can fail after this block, otherwise
+        * sctp_destroy_sock() will be called without addr_wq_lock held
+        */
        if (net->sctp.default_auto_asconf) {
+               spin_lock(&sock_net(sk)->sctp.addr_wq_lock);
                list_add_tail(&sp->auto_asconf_list,
                    &net->sctp.auto_asconf_splist);
                sp->do_auto_asconf = 1;
-       } else
+               spin_unlock(&sock_net(sk)->sctp.addr_wq_lock);
+       } else {
                sp->do_auto_asconf = 0;
+       }
+
        local_bh_enable();
 
        return 0;
 }
 
-/* Cleanup any SCTP per socket resources.  */
+/* Cleanup any SCTP per socket resources. Must be called with
+ * sock_net(sk)->sctp.addr_wq_lock held if sp->do_auto_asconf is true
+ */
 static void sctp_destroy_sock(struct sock *sk)
 {
        struct sctp_sock *sp;
@@ -7195,6 +7209,19 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
        newinet->mc_list = NULL;
 }
 
+static inline void sctp_copy_descendant(struct sock *sk_to,
+                                       const struct sock *sk_from)
+{
+       int ancestor_size = sizeof(struct inet_sock) +
+                           sizeof(struct sctp_sock) -
+                           offsetof(struct sctp_sock, auto_asconf_list);
+
+       if (sk_from->sk_family == PF_INET6)
+               ancestor_size += sizeof(struct ipv6_pinfo);
+
+       __inet_sk_copy_descendant(sk_to, sk_from, ancestor_size);
+}
+
 /* Populate the fields of the newsk from the oldsk and migrate the assoc
  * and its messages to the newsk.
  */
@@ -7209,7 +7236,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
        struct sk_buff *skb, *tmp;
        struct sctp_ulpevent *event;
        struct sctp_bind_hashbucket *head;
-       struct list_head tmplist;
 
        /* Migrate socket buffer sizes and all the socket level options to the
         * new socket.
@@ -7217,12 +7243,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
        newsk->sk_sndbuf = oldsk->sk_sndbuf;
        newsk->sk_rcvbuf = oldsk->sk_rcvbuf;
        /* Brute force copy old sctp opt. */
-       if (oldsp->do_auto_asconf) {
-               memcpy(&tmplist, &newsp->auto_asconf_list, sizeof(tmplist));
-               inet_sk_copy_descendant(newsk, oldsk);
-               memcpy(&newsp->auto_asconf_list, &tmplist, sizeof(tmplist));
-       } else
-               inet_sk_copy_descendant(newsk, oldsk);
+       sctp_copy_descendant(newsk, oldsk);
 
        /* Restore the ep value that was overwritten with the above structure
         * copy.