Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorDavid S. Miller <davem@davemloft.net>
Wed, 18 Dec 2013 21:42:06 +0000 (16:42 -0500)
committerDavid S. Miller <davem@davemloft.net>
Wed, 18 Dec 2013 21:42:06 +0000 (16:42 -0500)
Conflicts:
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/macvtap.c

Both minor merge hassles, simple overlapping changes.

Signed-off-by: David S. Miller <davem@davemloft.net>
33 files changed:
1  2 
Documentation/networking/ip-sysctl.txt
MAINTAINERS
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/macvtap.c
drivers/net/phy/micrel.c
drivers/net/tun.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/xen-netback/netback.c
include/linux/netdevice.h
include/net/sctp/structs.h
net/core/neighbour.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/sched/sch_htb.c
net/sctp/associola.c
net/sctp/output.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sctp/sysctl.c
net/tipc/core.c
net/unix/af_unix.c

@@@ -16,8 -16,12 +16,12 @@@ ip_default_ttl - INTEGE
        Default: 64 (as recommended by RFC1700)
  
  ip_no_pmtu_disc - BOOLEAN
-       Disable Path MTU Discovery.
-       default FALSE
+       Disable Path MTU Discovery. If enabled and a
+       fragmentation-required ICMP is received, the PMTU to this
+       destination will be set to min_pmtu (see below). You will need
+       to raise min_pmtu to the smallest interface MTU on your system
+       manually if you want to avoid locally generated fragments.
+       Default: FALSE
  
  min_pmtu - INTEGER
        default 552 - minimum discovered Path MTU
@@@ -156,16 -160,6 +160,16 @@@ tcp_app_win - INTEGE
        buffer. Value 0 is special, it means that nothing is reserved.
        Default: 31
  
 +tcp_autocorking - BOOLEAN
 +      Enable TCP auto corking :
 +      When applications do consecutive small write()/sendmsg() system calls,
 +      we try to coalesce these small writes as much as possible, to lower
 +      total amount of sent packets. This is done if at least one prior
 +      packet for the flow is waiting in Qdisc queues or device transmit
 +      queue. Applications can still use TCP_CORK for optimal behavior
 +      when they know how/when to uncork their sockets.
 +      Default : 1
 +
  tcp_available_congestion_control - STRING
        Shows the available congestion control choices that are registered.
        More congestion control algorithms may be available as modules,
diff --combined MAINTAINERS
@@@ -893,20 -893,15 +893,15 @@@ F:      arch/arm/include/asm/hardware/dec212
  F:    arch/arm/mach-footbridge/
  
  ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
+ M:    Shawn Guo <shawn.guo@linaro.org>
  M:    Sascha Hauer <kernel@pengutronix.de>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
- T:    git git://git.pengutronix.de/git/imx/linux-2.6.git
+ T:    git git://git.linaro.org/people/shawnguo/linux-2.6.git
  F:    arch/arm/mach-imx/
+ F:    arch/arm/boot/dts/imx*
  F:    arch/arm/configs/imx*_defconfig
  
- ARM/FREESCALE IMX6
- M:    Shawn Guo <shawn.guo@linaro.org>
- L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
- S:    Maintained
- T:    git git://git.linaro.org/people/shawnguo/linux-2.6.git
- F:    arch/arm/mach-imx/*imx6*
  ARM/FREESCALE MXS ARM ARCHITECTURE
  M:    Shawn Guo <shawn.guo@linaro.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -1458,6 -1453,17 +1453,6 @@@ T:     git git://github.com/kvalo/ath.gi
  S:    Supported
  F:    drivers/net/wireless/ath/ath6kl/
  
 -ATHEROS ATH9K WIRELESS DRIVER
 -M:    "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
 -M:    Jouni Malinen <jouni@qca.qualcomm.com>
 -M:    Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
 -M:    Senthil Balasubramanian <senthilb@qca.qualcomm.com>
 -L:    linux-wireless@vger.kernel.org
 -L:    ath9k-devel@lists.ath9k.org
 -W:    http://wireless.kernel.org/en/users/Drivers/ath9k
 -S:    Supported
 -F:    drivers/net/wireless/ath/ath9k/
 -
  WILOCITY WIL6210 WIRELESS DRIVER
  M:    Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
  L:    linux-wireless@vger.kernel.org
@@@ -1923,7 -1929,8 +1918,8 @@@ S:      Maintaine
  F:    drivers/gpio/gpio-bt8xx.c
  
  BTRFS FILE SYSTEM
- M:    Chris Mason <chris.mason@fusionio.com>
+ M:    Chris Mason <clm@fb.com>
+ M:    Josef Bacik <jbacik@fb.com>
  L:    linux-btrfs@vger.kernel.org
  W:    http://btrfs.wiki.kernel.org/
  Q:    http://patchwork.kernel.org/project/linux-btrfs/list/
@@@ -2126,7 -2133,8 +2122,8 @@@ S:      Maintaine
  F:    Documentation/zh_CN/
  
  CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
- M:    Alexander Shishkin <alexander.shishkin@linux.intel.com>
+ M:    Peter Chen <Peter.Chen@freescale.com>
+ T:    git://github.com/hzpeterchen/linux-usb.git
  L:    linux-usb@vger.kernel.org
  S:    Maintained
  F:    drivers/usb/chipidea/
@@@ -3753,9 -3761,11 +3750,11 @@@ F:    include/uapi/linux/gigaset_dev.
  
  GPIO SUBSYSTEM
  M:    Linus Walleij <linus.walleij@linaro.org>
- S:    Maintained
+ M:    Alexandre Courbot <gnurou@gmail.com>
  L:    linux-gpio@vger.kernel.org
- F:    Documentation/gpio.txt
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
+ S:    Maintained
+ F:    Documentation/gpio/
  F:    drivers/gpio/
  F:    include/linux/gpio*
  F:    include/asm-generic/gpio.h
@@@ -4032,6 -4042,14 +4031,14 @@@ W:    http://artax.karlin.mff.cuni.cz/~mik
  S:    Maintained
  F:    fs/hpfs/
  
+ HSI SUBSYSTEM
+ M:    Sebastian Reichel <sre@debian.org>
+ S:    Maintained
+ F:    Documentation/ABI/testing/sysfs-bus-hsi
+ F:    drivers/hsi/
+ F:    include/linux/hsi/
+ F:    include/uapi/linux/hsi/
  HSO 3G MODEM DRIVER
  M:    Jan Dumon <j.dumon@option.com>
  W:    http://www.pharscape.org
@@@ -5895,12 -5913,21 +5902,21 @@@ M:   Steffen Klassert <steffen.klassert@s
  M:    Herbert Xu <herbert@gondor.apana.org.au>
  M:    "David S. Miller" <davem@davemloft.net>
  L:    netdev@vger.kernel.org
- T:    git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git
  S:    Maintained
  F:    net/xfrm/
  F:    net/key/
  F:    net/ipv4/xfrm*
+ F:    net/ipv4/esp4.c
+ F:    net/ipv4/ah4.c
+ F:    net/ipv4/ipcomp.c
+ F:    net/ipv4/ip_vti.c
  F:    net/ipv6/xfrm*
+ F:    net/ipv6/esp6.c
+ F:    net/ipv6/ah6.c
+ F:    net/ipv6/ipcomp6.c
+ F:    net/ipv6/ip6_vti.c
  F:    include/uapi/linux/xfrm.h
  F:    include/net/xfrm.h
  
@@@ -5966,10 -5993,10 +5982,10 @@@ F:   drivers/nfc
  F:    include/linux/platform_data/pn544.h
  
  NFS, SUNRPC, AND LOCKD CLIENTS
- M:    Trond Myklebust <Trond.Myklebust@netapp.com>
+ M:    Trond Myklebust <trond.myklebust@primarydata.com>
  L:    linux-nfs@vger.kernel.org
  W:    http://client.linux-nfs.org
- T:    git git://git.linux-nfs.org/pub/linux/nfs-2.6.git
+ T:    git git://git.linux-nfs.org/projects/trondmy/linux-nfs.git
  S:    Maintained
  F:    fs/lockd/
  F:    fs/nfs/
@@@ -6236,8 -6263,8 +6252,8 @@@ OPEN FIRMWARE AND FLATTENED DEVICE TRE
  M:    Rob Herring <rob.herring@calxeda.com>
  M:    Pawel Moll <pawel.moll@arm.com>
  M:    Mark Rutland <mark.rutland@arm.com>
- M:    Stephen Warren <swarren@wwwdotorg.org>
  M:    Ian Campbell <ijc+devicetree@hellion.org.uk>
+ M:    Kumar Gala <galak@codeaurora.org>
  L:    devicetree@vger.kernel.org
  S:    Maintained
  F:    Documentation/devicetree/
@@@ -6447,19 -6474,52 +6463,52 @@@ F:   drivers/pci
  F:    include/linux/pci*
  F:    arch/x86/pci/
  
+ PCI DRIVER FOR IMX6
+ M:    Richard Zhu <r65037@freescale.com>
+ M:    Shawn Guo <shawn.guo@linaro.org>
+ L:    linux-pci@vger.kernel.org
+ L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+ S:    Maintained
+ F:    drivers/pci/host/*imx6*
+ PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
+ M:    Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ M:    Jason Cooper <jason@lakedaemon.net>
+ L:    linux-pci@vger.kernel.org
+ L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+ S:    Maintained
+ F:    drivers/pci/host/*mvebu*
  PCI DRIVER FOR NVIDIA TEGRA
  M:    Thierry Reding <thierry.reding@gmail.com>
  L:    linux-tegra@vger.kernel.org
+ L:    linux-pci@vger.kernel.org
  S:    Supported
  F:    Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
  F:    drivers/pci/host/pci-tegra.c
  
+ PCI DRIVER FOR RENESAS R-CAR
+ M:    Simon Horman <horms@verge.net.au>
+ L:    linux-pci@vger.kernel.org
+ L:    linux-sh@vger.kernel.org
+ S:    Maintained
+ F:    drivers/pci/host/*rcar*
  PCI DRIVER FOR SAMSUNG EXYNOS
  M:    Jingoo Han <jg1.han@samsung.com>
  L:    linux-pci@vger.kernel.org
+ L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+ L:    linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
  S:    Maintained
  F:    drivers/pci/host/pci-exynos.c
  
+ PCI DRIVER FOR SYNOPSIS DESIGNWARE
+ M:    Mohit Kumar <mohit.kumar@st.com>
+ M:    Jingoo Han <jg1.han@samsung.com>
+ L:    linux-pci@vger.kernel.org
+ S:    Maintained
+ F:    drivers/pci/host/*designware*
  PCMCIA SUBSYSTEM
  P:    Linux PCMCIA Team
  L:    linux-pcmcia@lists.infradead.org
@@@ -6915,14 -6975,6 +6964,14 @@@ T:    git git://linuxtv.org/anttip/media_t
  S:    Maintained
  F:    drivers/media/tuners/qt1010*
  
 +QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
 +M:    QCA ath9k Development <ath9k-devel@qca.qualcomm.com>
 +L:    linux-wireless@vger.kernel.org
 +L:    ath9k-devel@lists.ath9k.org
 +W:    http://wireless.kernel.org/en/users/Drivers/ath9k
 +S:    Supported
 +F:    drivers/net/wireless/ath/ath9k/
 +
  QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
  M:    Kalle Valo <kvalo@qca.qualcomm.com>
  L:    ath10k@lists.infradead.org
@@@ -8563,11 -8615,12 +8612,11 @@@ S:   Maintaine
  F:    sound/soc/codecs/twl4030*
  
  TI WILINK WIRELESS DRIVERS
 -M:    Luciano Coelho <luca@coelho.fi>
  L:    linux-wireless@vger.kernel.org
  W:    http://wireless.kernel.org/en/users/Drivers/wl12xx
  W:    http://wireless.kernel.org/en/users/Drivers/wl1251
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
 -S:    Maintained
 +S:    Orphan
  F:    drivers/net/wireless/ti/
  F:    include/linux/wl12xx.h
  
@@@ -94,10 -94,10 +94,10 @@@ static inline void _tg3_flag_clear(enu
  
  #define DRV_MODULE_NAME               "tg3"
  #define TG3_MAJ_NUM                   3
 -#define TG3_MIN_NUM                   134
 +#define TG3_MIN_NUM                   135
  #define DRV_MODULE_VERSION    \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
 -#define DRV_MODULE_RELDATE    "Sep 16, 2013"
 +#define DRV_MODULE_RELDATE    "Nov 14, 2013"
  
  #define RESET_KIND_SHUTDOWN   0
  #define RESET_KIND_INIT               1
@@@ -4403,12 -4403,9 +4403,12 @@@ static void tg3_phy_copper_begin(struc
                        if (tg3_flag(tp, WOL_SPEED_100MB))
                                adv |= ADVERTISED_100baseT_Half |
                                       ADVERTISED_100baseT_Full;
 -                      if (tp->phy_flags & TG3_PHYFLG_1G_ON_VAUX_OK)
 -                              adv |= ADVERTISED_1000baseT_Half |
 -                                     ADVERTISED_1000baseT_Full;
 +                      if (tp->phy_flags & TG3_PHYFLG_1G_ON_VAUX_OK) {
 +                              if (!(tp->phy_flags &
 +                                    TG3_PHYFLG_DISABLE_1G_HD_ADV))
 +                                      adv |= ADVERTISED_1000baseT_Half;
 +                              adv |= ADVERTISED_1000baseT_Full;
 +                      }
  
                        fc = FLOW_CTRL_TX | FLOW_CTRL_RX;
                } else {
@@@ -9969,7 -9966,6 +9969,7 @@@ static int tg3_reset_hw(struct tg3 *tp
        if (tg3_asic_rev(tp) == ASIC_REV_5719)
                val |= BUFMGR_MODE_NO_TX_UNDERRUN;
        if (tg3_asic_rev(tp) == ASIC_REV_5717 ||
 +          tg3_asic_rev(tp) == ASIC_REV_5762 ||
            tg3_chip_rev_id(tp) == CHIPREV_ID_5719_A0 ||
            tg3_chip_rev_id(tp) == CHIPREV_ID_5720_A0)
                val |= BUFMGR_MODE_MBLOW_ATTN_ENAB;
@@@ -10755,7 -10751,6 +10755,7 @@@ static void tg3_periodic_fetch_stats(st
  
        TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT);
        if (tg3_asic_rev(tp) != ASIC_REV_5717 &&
 +          tg3_asic_rev(tp) != ASIC_REV_5762 &&
            tg3_chip_rev_id(tp) != CHIPREV_ID_5719_A0 &&
            tg3_chip_rev_id(tp) != CHIPREV_ID_5720_A0) {
                TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT);
@@@ -11751,6 -11746,8 +11751,6 @@@ static void tg3_get_nstats(struct tg3 *
                get_stat64(&hw_stats->rx_frame_too_long_errors) +
                get_stat64(&hw_stats->rx_undersize_packets);
  
 -      stats->rx_over_errors = old_stats->rx_over_errors +
 -              get_stat64(&hw_stats->rxbds_empty);
        stats->rx_frame_errors = old_stats->rx_frame_errors +
                get_stat64(&hw_stats->rx_align_errors);
        stats->tx_aborted_errors = old_stats->tx_aborted_errors +
@@@ -13597,13 -13594,14 +13597,13 @@@ static void tg3_self_test(struct net_de
  
  }
  
 -static int tg3_hwtstamp_ioctl(struct net_device *dev,
 -                            struct ifreq *ifr, int cmd)
 +static int tg3_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
  {
        struct tg3 *tp = netdev_priv(dev);
        struct hwtstamp_config stmpconf;
  
        if (!tg3_flag(tp, PTP_CAPABLE))
 -              return -EINVAL;
 +              return -EOPNOTSUPP;
  
        if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf)))
                return -EFAULT;
                -EFAULT : 0;
  }
  
 +static int tg3_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
 +{
 +      struct tg3 *tp = netdev_priv(dev);
 +      struct hwtstamp_config stmpconf;
 +
 +      if (!tg3_flag(tp, PTP_CAPABLE))
 +              return -EOPNOTSUPP;
 +
 +      stmpconf.flags = 0;
 +      stmpconf.tx_type = (tg3_flag(tp, TX_TSTAMP_EN) ?
 +                          HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF);
 +
 +      switch (tp->rxptpctl) {
 +      case 0:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_NONE;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_ALL_V1_EVENTS:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_DELAY_REQ:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_SYNC;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_DELAY_REQ:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_DELAY_REQ:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ;
 +              break;
 +      case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_DELAY_REQ:
 +              stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
 +              break;
 +      default:
 +              WARN_ON_ONCE(1);
 +              return -ERANGE;
 +      }
 +
 +      return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ?
 +              -EFAULT : 0;
 +}
 +
  static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  {
        struct mii_ioctl_data *data = if_mii(ifr);
                return err;
  
        case SIOCSHWTSTAMP:
 -              return tg3_hwtstamp_ioctl(dev, ifr, cmd);
 +              return tg3_hwtstamp_set(dev, ifr);
 +
 +      case SIOCGHWTSTAMP:
 +              return tg3_hwtstamp_get(dev, ifr);
  
        default:
                /* do nothing */
@@@ -14922,8 -14856,7 +14922,8 @@@ static void tg3_get_eeprom_hw_cfg(struc
        tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
        if (val == NIC_SRAM_DATA_SIG_MAGIC) {
                u32 nic_cfg, led_cfg;
 -              u32 nic_phy_id, ver, cfg2 = 0, cfg4 = 0, eeprom_phy_id;
 +              u32 cfg2 = 0, cfg4 = 0, cfg5 = 0;
 +              u32 nic_phy_id, ver, eeprom_phy_id;
                int eeprom_phy_serdes = 0;
  
                tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
                if (tg3_asic_rev(tp) == ASIC_REV_5785)
                        tg3_read_mem(tp, NIC_SRAM_DATA_CFG_4, &cfg4);
  
 +              if (tg3_asic_rev(tp) == ASIC_REV_5717 ||
 +                  tg3_asic_rev(tp) == ASIC_REV_5719 ||
 +                  tg3_asic_rev(tp) == ASIC_REV_5720)
 +                      tg3_read_mem(tp, NIC_SRAM_DATA_CFG_5, &cfg5);
 +
                if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
                    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
                        eeprom_phy_serdes = 1;
                        tg3_flag_set(tp, RGMII_EXT_IBND_RX_EN);
                if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN)
                        tg3_flag_set(tp, RGMII_EXT_IBND_TX_EN);
 +
 +              if (cfg5 & NIC_SRAM_DISABLE_1G_HALF_ADV)
 +                      tp->phy_flags |= TG3_PHYFLG_DISABLE_1G_HD_ADV;
        }
  done:
        if (tg3_flag(tp, WOL_CAP))
@@@ -15195,11 -15120,9 +15195,11 @@@ static void tg3_phy_init_link_config(st
  {
        u32 adv = ADVERTISED_Autoneg;
  
 -      if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY))
 -              adv |= ADVERTISED_1000baseT_Half |
 -                     ADVERTISED_1000baseT_Full;
 +      if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
 +              if (!(tp->phy_flags & TG3_PHYFLG_DISABLE_1G_HD_ADV))
 +                      adv |= ADVERTISED_1000baseT_Half;
 +              adv |= ADVERTISED_1000baseT_Full;
 +      }
  
        if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
                adv |= ADVERTISED_100baseT_Half |
@@@ -16547,7 -16470,6 +16547,7 @@@ static int tg3_get_invariants(struct tg
  
        /* Set these bits to enable statistics workaround. */
        if (tg3_asic_rev(tp) == ASIC_REV_5717 ||
 +          tg3_asic_rev(tp) == ASIC_REV_5762 ||
            tg3_chip_rev_id(tp) == CHIPREV_ID_5719_A0 ||
            tg3_chip_rev_id(tp) == CHIPREV_ID_5720_A0) {
                tp->coalesce_mode |= HOSTCC_MODE_ATTN;
        /* Clear this out for sanity. */
        tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
  
+       /* Clear TG3PCI_REG_BASE_ADDR to prevent hangs. */
+       tw32(TG3PCI_REG_BASE_ADDR, 0);
        pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
                              &pci_state_reg);
        if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 &&
@@@ -98,10 -98,6 +98,6 @@@ static void set_multicast_list(struct n
   * detected as not set during a prior frame transmission, then the
   * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
   * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
-  * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
-  * detected as not set during a prior frame transmission, then the
-  * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
-  * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
   * frames not being transmitted until there is a 0-to-1 transition on
   * ENET_TDAR[TDAR].
   */
@@@ -1683,12 -1679,8 +1679,12 @@@ static int fec_enet_ioctl(struct net_de
        if (!phydev)
                return -ENODEV;
  
 -      if (cmd == SIOCSHWTSTAMP && fep->bufdesc_ex)
 -              return fec_ptp_ioctl(ndev, rq, cmd);
 +      if (fep->bufdesc_ex) {
 +              if (cmd == SIOCSHWTSTAMP)
 +                      return fec_ptp_set(ndev, rq);
 +              if (cmd == SIOCGHWTSTAMP)
 +                      return fec_ptp_get(ndev, rq);
 +      }
  
        return phy_mii_ioctl(phydev, rq, cmd);
  }
@@@ -36,7 -36,7 +36,7 @@@ static const char i40e_driver_string[] 
  
  #define DRV_VERSION_MAJOR 0
  #define DRV_VERSION_MINOR 3
 -#define DRV_VERSION_BUILD 11
 +#define DRV_VERSION_BUILD 14
  #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
             __stringify(DRV_VERSION_MINOR) "." \
             __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@@ -48,7 -48,7 +48,7 @@@ static void i40e_vsi_reinit_locked(stru
  static void i40e_handle_reset_warning(struct i40e_pf *pf);
  static int i40e_add_vsi(struct i40e_vsi *vsi);
  static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi);
 -static int i40e_setup_pf_switch(struct i40e_pf *pf);
 +static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit);
  static int i40e_setup_misc_vector(struct i40e_pf *pf);
  static void i40e_determine_queue_usage(struct i40e_pf *pf);
  static int i40e_setup_pf_filter_control(struct i40e_pf *pf);
@@@ -354,9 -354,9 +354,13 @@@ static struct rtnl_link_stats64 *i40e_g
        struct rtnl_link_stats64 *vsi_stats = i40e_get_vsi_stats_struct(vsi);
        int i;
  
++
 +      if (test_bit(__I40E_DOWN, &vsi->state))
 +              return stats;
 +
+       if (!vsi->tx_rings)
+               return stats;
        rcu_read_lock();
        for (i = 0; i < vsi->num_queue_pairs; i++) {
                struct i40e_ring *tx_ring, *rx_ring;
@@@ -577,11 -577,10 +581,11 @@@ static void i40e_update_veb_stats(struc
        i40e_stat_update32(hw, I40E_GLSW_TDPC(idx),
                           veb->stat_offsets_loaded,
                           &oes->tx_discards, &es->tx_discards);
 -      i40e_stat_update32(hw, I40E_GLSW_RUPP(idx),
 -                         veb->stat_offsets_loaded,
 -                         &oes->rx_unknown_protocol, &es->rx_unknown_protocol);
 -
 +      if (hw->revision_id > 0)
 +              i40e_stat_update32(hw, I40E_GLSW_RUPP(idx),
 +                                 veb->stat_offsets_loaded,
 +                                 &oes->rx_unknown_protocol,
 +                                 &es->rx_unknown_protocol);
        i40e_stat_update48(hw, I40E_GLSW_GORCH(idx), I40E_GLSW_GORCL(idx),
                           veb->stat_offsets_loaded,
                           &oes->rx_bytes, &es->rx_bytes);
@@@ -2244,10 -2243,7 +2248,10 @@@ static int i40e_configure_rx_ring(struc
        rx_ctx.tphwdesc_ena = 1;
        rx_ctx.tphdata_ena = 1;
        rx_ctx.tphhead_ena = 1;
 -      rx_ctx.lrxqthresh = 2;
 +      if (hw->revision_id == 0)
 +              rx_ctx.lrxqthresh = 0;
 +      else
 +              rx_ctx.lrxqthresh = 2;
        rx_ctx.crcstrip = 1;
        rx_ctx.l2tsel = 1;
        rx_ctx.showiv = 1;
@@@ -2489,8 -2485,8 +2493,8 @@@ static void i40e_enable_misc_int_causes
        wr32(hw, I40E_PFINT_ICR0_ENA, val);
  
        /* SW_ITR_IDX = 0, but don't change INTENA */
 -      wr32(hw, I40E_PFINT_DYN_CTL0, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK |
 -                                      I40E_PFINT_DYN_CTLN_INTENA_MSK_MASK);
 +      wr32(hw, I40E_PFINT_DYN_CTL0, I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK |
 +                                      I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK);
  
        /* OTHER_ITR_IDX = 0 */
        wr32(hw, I40E_PFINT_STAT_CTL0, 0);
@@@ -2759,11 -2755,6 +2763,11 @@@ static irqreturn_t i40e_intr(int irq, v
  
        ena_mask = rd32(hw, I40E_PFINT_ICR0_ENA);
  
 +      /* if interrupt but no bits showing, must be SWINT */
 +      if (((icr0 & ~I40E_PFINT_ICR0_INTEVENT_MASK) == 0) ||
 +          (icr0 & I40E_PFINT_ICR0_SWINT_MASK))
 +              pf->sw_int_count++;
 +
        /* only q0 is used in MSI/Legacy mode, and none are used in MSIX */
        if (icr0 & I40E_PFINT_ICR0_QUEUE_0_MASK) {
  
                val = rd32(hw, I40E_GLGEN_RSTAT);
                val = (val & I40E_GLGEN_RSTAT_RESET_TYPE_MASK)
                       >> I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT;
 -              if (val & I40E_RESET_CORER)
 +              if (val == I40E_RESET_CORER)
                        pf->corer_count++;
 -              else if (val & I40E_RESET_GLOBR)
 +              else if (val == I40E_RESET_GLOBR)
                        pf->globr_count++;
 -              else if (val & I40E_RESET_EMPR)
 +              else if (val == I40E_RESET_EMPR)
                        pf->empr_count++;
        }
  
@@@ -3028,9 -3019,6 +3032,9 @@@ static int i40e_vsi_control_tx(struct i
                }
        }
  
 +      if (hw->revision_id == 0)
 +              mdelay(50);
 +
        return 0;
  }
  
@@@ -3969,15 -3957,6 +3973,15 @@@ static int i40e_open(struct net_device 
        if (err)
                goto err_setup_rx;
  
 +      /* Notify the stack of the actual queue counts. */
 +      err = netif_set_real_num_tx_queues(netdev, pf->num_tx_queues);
 +      if (err)
 +              goto err_set_queues;
 +
 +      err = netif_set_real_num_rx_queues(netdev, pf->num_rx_queues);
 +      if (err)
 +              goto err_set_queues;
 +
        err = i40e_up_complete(vsi);
        if (err)
                goto err_up_complete;
  
  err_up_complete:
        i40e_down(vsi);
 +err_set_queues:
        i40e_vsi_free_irq(vsi);
  err_setup_rx:
        i40e_vsi_free_rx_resources(vsi);
@@@ -4076,24 -4054,6 +4080,24 @@@ void i40e_do_reset(struct i40e_pf *pf, 
                wr32(&pf->hw, I40E_GLGEN_RTRIG, val);
                i40e_flush(&pf->hw);
  
 +      } else if (reset_flags & (1 << __I40E_EMP_RESET_REQUESTED)) {
 +
 +              /* Request a Firmware Reset
 +               *
 +               * Same as Global reset, plus restarting the
 +               * embedded firmware engine.
 +               */
 +              /* enable EMP Reset */
 +              val = rd32(&pf->hw, I40E_GLGEN_RSTENA_EMP);
 +              val |= I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK;
 +              wr32(&pf->hw, I40E_GLGEN_RSTENA_EMP, val);
 +
 +              /* force the reset */
 +              val = rd32(&pf->hw, I40E_GLGEN_RTRIG);
 +              val |= I40E_GLGEN_RTRIG_EMPFWR_MASK;
 +              wr32(&pf->hw, I40E_GLGEN_RTRIG, val);
 +              i40e_flush(&pf->hw);
 +
        } else if (reset_flags & (1 << __I40E_PF_RESET_REQUESTED)) {
  
                /* Request a PF Reset
  }
  
  /**
 + * i40e_do_reset_safe - Protected reset path for userland calls.
 + * @pf: board private structure
 + * @reset_flags: which reset is requested
 + *
 + **/
 +void i40e_do_reset_safe(struct i40e_pf *pf, u32 reset_flags)
 +{
 +      rtnl_lock();
 +      i40e_do_reset(pf, reset_flags);
 +      rtnl_unlock();
 +}
 +
 +/**
   * i40e_handle_lan_overflow_event - Handler for LAN queue overflow event
   * @pf: board private structure
   * @e: event info posted on ARQ
@@@ -4389,7 -4336,6 +4393,7 @@@ static void i40e_reset_subtask(struct i
  {
        u32 reset_flags = 0;
  
 +      rtnl_lock();
        if (test_bit(__I40E_REINIT_REQUESTED, &pf->state)) {
                reset_flags |= (1 << __I40E_REINIT_REQUESTED);
                clear_bit(__I40E_REINIT_REQUESTED, &pf->state);
         */
        if (test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state)) {
                i40e_handle_reset_warning(pf);
 -              return;
 +              goto unlock;
        }
  
        /* If we're already down or resetting, just bail */
            !test_bit(__I40E_DOWN, &pf->state) &&
            !test_bit(__I40E_CONFIG_BUSY, &pf->state))
                i40e_do_reset(pf, reset_flags);
 +
 +unlock:
 +      rtnl_unlock();
  }
  
  /**
@@@ -4649,13 -4592,6 +4653,13 @@@ static int i40e_get_capabilities(struc
                }
        } while (err);
  
 +      if (pf->hw.revision_id == 0 && pf->hw.func_caps.npar_enable) {
 +              pf->hw.func_caps.num_msix_vectors += 1;
 +              pf->hw.func_caps.num_tx_qp =
 +                      min_t(int, pf->hw.func_caps.num_tx_qp,
 +                            I40E_MAX_NPAR_QPS);
 +      }
 +
        if (pf->hw.debug_mask & I40E_DEBUG_USER)
                dev_info(&pf->pdev->dev,
                         "pf=%d, num_vfs=%d, msix_pf=%d, msix_vf=%d, fd_g=%d, fd_b=%d, pf_max_q=%d num_vsi=%d\n",
                         pf->hw.func_caps.num_tx_qp,
                         pf->hw.func_caps.num_vsis);
  
 +#define DEF_NUM_VSI (1 + (pf->hw.func_caps.fcoe ? 1 : 0) \
 +                     + pf->hw.func_caps.num_vfs)
 +      if (pf->hw.revision_id == 0 && (DEF_NUM_VSI > pf->hw.func_caps.num_vsis)) {
 +              dev_info(&pf->pdev->dev,
 +                       "got num_vsis %d, setting num_vsis to %d\n",
 +                       pf->hw.func_caps.num_vsis, DEF_NUM_VSI);
 +              pf->hw.func_caps.num_vsis = DEF_NUM_VSI;
 +      }
 +
        return 0;
  }
  
@@@ -4746,20 -4673,22 +4750,20 @@@ static void i40e_fdir_teardown(struct i
  }
  
  /**
 - * i40e_handle_reset_warning - prep for the core to reset
 + * i40e_prep_for_reset - prep for the core to reset
   * @pf: board private structure
   *
 - * Close up the VFs and other things in prep for a Core Reset,
 - * then get ready to rebuild the world.
 - **/
 -static void i40e_handle_reset_warning(struct i40e_pf *pf)
 + * Close up the VFs and other things in prep for pf Reset.
 +  **/
 +static int i40e_prep_for_reset(struct i40e_pf *pf)
  {
 -      struct i40e_driver_version dv;
        struct i40e_hw *hw = &pf->hw;
        i40e_status ret;
        u32 v;
  
        clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state);
        if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
 -              return;
 +              return 0;
  
        dev_info(&pf->pdev->dev, "Tearing down internal switch for reset\n");
  
  
        i40e_shutdown_adminq(&pf->hw);
  
 +      /* call shutdown HMC */
 +      ret = i40e_shutdown_lan_hmc(hw);
 +      if (ret) {
 +              dev_info(&pf->pdev->dev, "shutdown_lan_hmc failed: %d\n", ret);
 +              clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state);
 +      }
 +      return ret;
 +}
 +
 +/**
 + * i40e_reset_and_rebuild - reset and rebuid using a saved config
 + * @pf: board private structure
 + * @reinit: if the Main VSI needs to re-initialized.
 + **/
 +static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
 +{
 +      struct i40e_driver_version dv;
 +      struct i40e_hw *hw = &pf->hw;
 +      i40e_status ret;
 +      u32 v;
 +
        /* Now we wait for GRST to settle out.
         * We don't have to delete the VEBs or VSIs from the hw switch
         * because the reset will make them disappear.
                goto end_core_reset;
        }
  
 -      /* call shutdown HMC */
 -      ret = i40e_shutdown_lan_hmc(hw);
 -      if (ret) {
 -              dev_info(&pf->pdev->dev, "shutdown_lan_hmc failed: %d\n", ret);
 -              goto end_core_reset;
 -      }
 -
        ret = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
                                hw->func_caps.num_rx_qp,
                                pf->fcoe_hmc_cntx_num, pf->fcoe_hmc_filt_num);
        }
  
        /* do basic switch setup */
 -      ret = i40e_setup_pf_switch(pf);
 +      ret = i40e_setup_pf_switch(pf, reinit);
        if (ret)
                goto end_core_reset;
  
@@@ -4916,22 -4831,6 +4920,22 @@@ end_core_reset
  }
  
  /**
 + * i40e_handle_reset_warning - prep for the pf to reset, reset and rebuild
 + * @pf: board private structure
 + *
 + * Close up the VFs and other things in prep for a Core Reset,
 + * then get ready to rebuild the world.
 + **/
 +static void i40e_handle_reset_warning(struct i40e_pf *pf)
 +{
 +      i40e_status ret;
 +
 +      ret = i40e_prep_for_reset(pf);
 +      if (!ret)
 +              i40e_reset_and_rebuild(pf, false);
 +}
 +
 +/**
   * i40e_handle_mdd_event
   * @pf: pointer to the pf structure
   *
@@@ -5107,42 -5006,6 +5111,42 @@@ static int i40e_set_num_rings_in_vsi(st
  }
  
  /**
 + * i40e_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the vsi
 + * @type: VSI pointer
 + * @alloc_qvectors: a bool to specify if q_vectors need to be allocated.
 + *
 + * On error: returns error code (negative)
 + * On success: returns 0
 + **/
 +static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi, bool alloc_qvectors)
 +{
 +      int size;
 +      int ret = 0;
 +
 +      /* allocate memory for both Tx and Rx ring pointers */
 +      size = sizeof(struct i40e_ring *) * vsi->alloc_queue_pairs * 2;
 +      vsi->tx_rings = kzalloc(size, GFP_KERNEL);
 +      if (!vsi->tx_rings)
 +              return -ENOMEM;
 +      vsi->rx_rings = &vsi->tx_rings[vsi->alloc_queue_pairs];
 +
 +      if (alloc_qvectors) {
 +              /* allocate memory for q_vector pointers */
 +              size = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors;
 +              vsi->q_vectors = kzalloc(size, GFP_KERNEL);
 +              if (!vsi->q_vectors) {
 +                      ret = -ENOMEM;
 +                      goto err_vectors;
 +              }
 +      }
 +      return ret;
 +
 +err_vectors:
 +      kfree(vsi->tx_rings);
 +      return ret;
 +}
 +
 +/**
   * i40e_vsi_mem_alloc - Allocates the next available struct vsi in the PF
   * @pf: board private structure
   * @type: type of VSI
@@@ -5154,6 -5017,8 +5158,6 @@@ static int i40e_vsi_mem_alloc(struct i4
  {
        int ret = -ENODEV;
        struct i40e_vsi *vsi;
 -      int sz_vectors;
 -      int sz_rings;
        int vsi_idx;
        int i;
  
        if (ret)
                goto err_rings;
  
 -      /* allocate memory for ring pointers */
 -      sz_rings = sizeof(struct i40e_ring *) * vsi->alloc_queue_pairs * 2;
 -      vsi->tx_rings = kzalloc(sz_rings, GFP_KERNEL);
 -      if (!vsi->tx_rings) {
 -              ret = -ENOMEM;
 +      ret = i40e_vsi_alloc_arrays(vsi, true);
 +      if (ret)
                goto err_rings;
 -      }
 -      vsi->rx_rings = &vsi->tx_rings[vsi->alloc_queue_pairs];
 -
 -      /* allocate memory for q_vector pointers */
 -      sz_vectors = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors;
 -      vsi->q_vectors = kzalloc(sz_vectors, GFP_KERNEL);
 -      if (!vsi->q_vectors) {
 -              ret = -ENOMEM;
 -              goto err_vectors;
 -      }
  
        /* Setup default MSIX irq handler for VSI */
        i40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings);
        ret = vsi_idx;
        goto unlock_pf;
  
 -err_vectors:
 -      kfree(vsi->tx_rings);
  err_rings:
        pf->next_vsi = i - 1;
        kfree(vsi);
@@@ -5223,26 -5103,6 +5227,26 @@@ unlock_pf
  }
  
  /**
 + * i40e_vsi_free_arrays - Free queue and vector pointer arrays for the VSI
 + * @type: VSI pointer
 + * @free_qvectors: a bool to specify if q_vectors need to be freed.
 + *
 + * On error: returns error code (negative)
 + * On success: returns 0
 + **/
 +static void i40e_vsi_free_arrays(struct i40e_vsi *vsi, bool free_qvectors)
 +{
 +      /* free the ring and vector containers */
 +      if (free_qvectors) {
 +              kfree(vsi->q_vectors);
 +              vsi->q_vectors = NULL;
 +      }
 +      kfree(vsi->tx_rings);
 +      vsi->tx_rings = NULL;
 +      vsi->rx_rings = NULL;
 +}
 +
 +/**
   * i40e_vsi_clear - Deallocate the VSI provided
   * @vsi: the VSI being un-configured
   **/
@@@ -5278,7 -5138,9 +5282,7 @@@ static int i40e_vsi_clear(struct i40e_v
        i40e_put_lump(pf->qp_pile, vsi->base_queue, vsi->idx);
        i40e_put_lump(pf->irq_pile, vsi->base_vector, vsi->idx);
  
 -      /* free the ring and vector containers */
 -      kfree(vsi->q_vectors);
 -      kfree(vsi->tx_rings);
 +      i40e_vsi_free_arrays(vsi, true);
  
        pf->vsi[vsi->idx] = NULL;
        if (vsi->idx < pf->next_vsi)
@@@ -5301,7 -5163,7 +5305,7 @@@ static s32 i40e_vsi_clear_rings(struct 
        int i;
  
        if (vsi->tx_rings[0])
 -              for (i = 0; i < vsi->alloc_queue_pairs; i++) {
 +              for (i = 0; i < vsi->num_queue_pairs; i++) {
                        kfree_rcu(vsi->tx_rings[i], rcu);
                        vsi->tx_rings[i] = NULL;
                        vsi->rx_rings[i] = NULL;
@@@ -5320,11 -5182,10 +5324,11 @@@ static int i40e_alloc_rings(struct i40e
        int i;
  
        /* Set basic values in the rings to be used later during open() */
 -      for (i = 0; i < vsi->alloc_queue_pairs; i++) {
 +      for (i = 0; i < vsi->num_queue_pairs; i++) {
                struct i40e_ring *tx_ring;
                struct i40e_ring *rx_ring;
  
 +              /* allocate space for both Tx and Rx in one shot */
                tx_ring = kzalloc(sizeof(struct i40e_ring) * 2, GFP_KERNEL);
                if (!tx_ring)
                        goto err_out;
@@@ -5428,18 -5289,15 +5432,18 @@@ static int i40e_init_msix(struct i40e_p
        /* The number of vectors we'll request will be comprised of:
         *   - Add 1 for "other" cause for Admin Queue events, etc.
         *   - The number of LAN queue pairs
 -       *        already adjusted for the NUMA node
 -       *        assumes symmetric Tx/Rx pairing
 +       *      - Queues being used for RSS.
 +       *              We don't need as many as max_rss_size vectors.
 +       *              use rss_size instead in the calculation since that
 +       *              is governed by number of cpus in the system.
 +       *      - assumes symmetric Tx/Rx pairing
         *   - The number of VMDq pairs
         * Once we count this up, try the request.
         *
         * If we can't get what we want, we'll simplify to nearly nothing
         * and try again.  If that still fails, we punt.
         */
 -      pf->num_lan_msix = pf->num_lan_qps;
 +      pf->num_lan_msix = pf->num_lan_qps - (pf->rss_size_max - pf->rss_size);
        pf->num_vmdq_msix = pf->num_vmdq_qps;
        v_budget = 1 + pf->num_lan_msix;
        v_budget += (pf->num_vmdq_vsis * pf->num_vmdq_msix);
@@@ -5655,34 -5513,15 +5659,34 @@@ static int i40e_setup_misc_vector(struc
   **/
  static int i40e_config_rss(struct i40e_pf *pf)
  {
 -      struct i40e_hw *hw = &pf->hw;
 -      u32 lut = 0;
 -      int i, j;
 -      u64 hena;
 +      const u64 default_hena =
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6) |
 +                      ((u64)1 << I40E_FILTER_PCTYPE_L2_PAYLOAD);
 +
        /* Set of random keys generated using kernel random number generator */
        static const u32 seed[I40E_PFQF_HKEY_MAX_INDEX + 1] = {0x41b01687,
                                0x183cfd8c, 0xce880440, 0x580cbc3c, 0x35897377,
                                0x328b25e1, 0x4fa98922, 0xb7d90c14, 0xd5bad70d,
                                0xcd15a2c1, 0xe8580225, 0x4a1e9d11, 0xfe5731be};
 +      struct i40e_hw *hw = &pf->hw;
 +      u32 lut = 0;
 +      int i, j;
 +      u64 hena;
  
        /* Fill out hash function seed */
        for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++)
        /* By default we enable TCP/UDP with IPv4/IPv6 ptypes */
        hena = (u64)rd32(hw, I40E_PFQF_HENA(0)) |
                ((u64)rd32(hw, I40E_PFQF_HENA(1)) << 32);
 -      hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
 -              ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
 -              ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) |
 -              ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) |
 -              ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) |
 -              ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
 -              ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
 -              ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) |
 -              ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4)|
 -              ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6);
 +      hena |= default_hena;
        wr32(hw, I40E_PFQF_HENA(0), (u32)hena);
        wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
  
  }
  
  /**
 + * i40e_reconfig_rss_queues - change number of queues for rss and rebuild
 + * @pf: board private structure
 + * @queue_count: the requested queue count for rss.
 + *
 + * returns 0 if rss is not enabled, if enabled returns the final rss queue
 + * count which may be different from the requested queue count.
 + **/
 +int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count)
 +{
 +      if (!(pf->flags & I40E_FLAG_RSS_ENABLED))
 +              return 0;
 +
 +      queue_count = min_t(int, queue_count, pf->rss_size_max);
 +      queue_count = rounddown_pow_of_two(queue_count);
 +
 +      if (queue_count != pf->rss_size) {
 +              if (pf->queues_left < (queue_count - pf->rss_size)) {
 +                      dev_info(&pf->pdev->dev,
 +                              "Not enough queues to do RSS on %d queues: remaining queues %d\n",
 +                              queue_count, pf->queues_left);
 +                      return pf->rss_size;
 +              }
 +              i40e_prep_for_reset(pf);
 +
 +              pf->num_lan_qps += (queue_count - pf->rss_size);
 +              pf->queues_left -= (queue_count - pf->rss_size);
 +              pf->rss_size = queue_count;
 +
 +              i40e_reset_and_rebuild(pf, true);
 +              i40e_config_rss(pf);
 +      }
 +      dev_info(&pf->pdev->dev, "RSS count:  %d\n", pf->rss_size);
 +      return pf->rss_size;
 +}
 +
 +/**
   * i40e_sw_init - Initialize general software structures (struct i40e_pf)
   * @pf: board private structure to initialize
   *
@@@ -5770,7 -5582,6 +5774,7 @@@ static int i40e_sw_init(struct i40e_pf 
  
        pf->msg_enable = netif_msg_init(I40E_DEFAULT_MSG_ENABLE,
                                (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK));
 +      pf->hw.debug_mask = pf->msg_enable | I40E_DEBUG_DIAG;
        if (debug != -1 && debug != I40E_DEFAULT_MSG_ENABLE) {
                if (I40E_DEBUG_USER & debug)
                        pf->hw.debug_mask = debug;
                    I40E_FLAG_MQ_ENABLED      |
                    I40E_FLAG_RX_1BUF_ENABLED;
  
 +      /* Depending on PF configurations, it is possible that the RSS
 +       * maximum might end up larger than the available queues
 +       */
        pf->rss_size_max = 0x1 << pf->hw.func_caps.rss_table_entry_width;
 +      pf->rss_size_max = min_t(int, pf->rss_size_max,
 +                               pf->hw.func_caps.num_tx_qp);
        if (pf->hw.func_caps.rss) {
                pf->flags |= I40E_FLAG_RSS_ENABLED;
 -              pf->rss_size = min_t(int, pf->rss_size_max,
 -                                   nr_cpus_node(numa_node_id()));
 +              pf->rss_size = min_t(int, pf->rss_size_max, num_online_cpus());
        } else {
                pf->rss_size = 1;
        }
                pf->num_req_vfs = min_t(int,
                                        pf->hw.func_caps.num_vfs,
                                        I40E_MAX_VF_COUNT);
 +              dev_info(&pf->pdev->dev,
 +                       "Number of VFs being requested for PF[%d] = %d\n",
 +                       pf->hw.pf_id, pf->num_req_vfs);
        }
  #endif /* CONFIG_PCI_IOV */
        pf->eeprom_version = 0xDEAD;
@@@ -6329,69 -6133,6 +6333,69 @@@ vector_setup_out
  }
  
  /**
 + * i40e_vsi_reinit_setup - return and reallocate resources for a VSI
 + * @vsi: pointer to the vsi.
 + *
 + * This re-allocates a vsi's queue resources.
 + *
 + * Returns pointer to the successfully allocated and configured VSI sw struct
 + * on success, otherwise returns NULL on failure.
 + **/
 +static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi)
 +{
 +      struct i40e_pf *pf = vsi->back;
 +      u8 enabled_tc;
 +      int ret;
 +
 +      i40e_put_lump(pf->qp_pile, vsi->base_queue, vsi->idx);
 +      i40e_vsi_clear_rings(vsi);
 +
 +      i40e_vsi_free_arrays(vsi, false);
 +      i40e_set_num_rings_in_vsi(vsi);
 +      ret = i40e_vsi_alloc_arrays(vsi, false);
 +      if (ret)
 +              goto err_vsi;
 +
 +      ret = i40e_get_lump(pf, pf->qp_pile, vsi->alloc_queue_pairs, vsi->idx);
 +      if (ret < 0) {
 +              dev_info(&pf->pdev->dev, "VSI %d get_lump failed %d\n",
 +                       vsi->seid, ret);
 +              goto err_vsi;
 +      }
 +      vsi->base_queue = ret;
 +
 +      /* Update the FW view of the VSI. Force a reset of TC and queue
 +       * layout configurations.
 +       */
 +      enabled_tc = pf->vsi[pf->lan_vsi]->tc_config.enabled_tc;
 +      pf->vsi[pf->lan_vsi]->tc_config.enabled_tc = 0;
 +      pf->vsi[pf->lan_vsi]->seid = pf->main_vsi_seid;
 +      i40e_vsi_config_tc(pf->vsi[pf->lan_vsi], enabled_tc);
 +
 +      /* assign it some queues */
 +      ret = i40e_alloc_rings(vsi);
 +      if (ret)
 +              goto err_rings;
 +
 +      /* map all of the rings to the q_vectors */
 +      i40e_vsi_map_rings_to_vectors(vsi);
 +      return vsi;
 +
 +err_rings:
 +      i40e_vsi_free_q_vectors(vsi);
 +      if (vsi->netdev_registered) {
 +              vsi->netdev_registered = false;
 +              unregister_netdev(vsi->netdev);
 +              free_netdev(vsi->netdev);
 +              vsi->netdev = NULL;
 +      }
 +      i40e_aq_delete_element(&pf->hw, vsi->seid, NULL);
 +err_vsi:
 +      i40e_vsi_clear(vsi);
 +      return NULL;
 +}
 +
 +/**
   * i40e_vsi_setup - Set up a VSI by a given type
   * @pf: board private structure
   * @type: VSI type
@@@ -6763,13 -6504,11 +6767,13 @@@ void i40e_veb_release(struct i40e_veb *
  static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi)
  {
        bool is_default = (vsi->idx == vsi->back->lan_vsi);
 +      bool is_cloud = false;
        int ret;
  
        /* get a VEB from the hardware */
        ret = i40e_aq_add_veb(&veb->pf->hw, veb->uplink_seid, vsi->seid,
 -                            veb->enabled_tc, is_default, &veb->seid, NULL);
 +                            veb->enabled_tc, is_default,
 +                            is_cloud, &veb->seid, NULL);
        if (ret) {
                dev_info(&veb->pf->pdev->dev,
                         "couldn't add VEB, err %d, aq_err %d\n",
@@@ -7034,13 -6773,11 +7038,13 @@@ int i40e_fetch_switch_configuration(str
  /**
   * i40e_setup_pf_switch - Setup the HW switch on startup or after reset
   * @pf: board private structure
 + * @reinit: if the Main VSI needs to re-initialized.
   *
   * Returns 0 on success, negative value on failure
   **/
 -static int i40e_setup_pf_switch(struct i40e_pf *pf)
 +static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
  {
 +      u32 rxfc = 0, txfc = 0, rxfc_reg;
        int ret;
  
        /* find out what's out there already */
                i40e_fdir_setup(pf);
  
        /* first time setup */
 -      if (pf->lan_vsi == I40E_NO_VSI) {
 +      if (pf->lan_vsi == I40E_NO_VSI || reinit) {
                struct i40e_vsi *vsi = NULL;
                u16 uplink_seid;
  
                        uplink_seid = pf->veb[pf->lan_veb]->seid;
                else
                        uplink_seid = pf->mac_seid;
 -
 -              vsi = i40e_vsi_setup(pf, I40E_VSI_MAIN, uplink_seid, 0);
 +              if (pf->lan_vsi == I40E_NO_VSI)
 +                      vsi = i40e_vsi_setup(pf, I40E_VSI_MAIN, uplink_seid, 0);
 +              else if (reinit)
 +                      vsi = i40e_vsi_reinit_setup(pf->vsi[pf->lan_vsi]);
                if (!vsi) {
                        dev_info(&pf->pdev->dev, "setup of MAIN VSI failed\n");
                        i40e_fdir_teardown(pf);
                 * into the pf, since this newer code pushes the pf queue
                 * info down a level into a VSI
                 */
 -              pf->num_rx_queues = vsi->alloc_queue_pairs;
 -              pf->num_tx_queues = vsi->alloc_queue_pairs;
 +              pf->num_rx_queues = vsi->num_queue_pairs;
 +              pf->num_tx_queues = vsi->num_queue_pairs;
        } else {
                /* force a reset of TC and queue layout configurations */
                u8 enabled_tc = pf->vsi[pf->lan_vsi]->tc_config.enabled_tc;
        i40e_aq_get_link_info(&pf->hw, true, NULL, NULL);
        i40e_link_event(pf);
  
 -      /* Initialize user-specifics link properties */
 +      /* Initialize user-specific link properties */
        pf->fc_autoneg_status = ((pf->hw.phy.link_info.an_info &
                                  I40E_AQ_AN_COMPLETED) ? true : false);
 -      pf->hw.fc.requested_mode = I40E_FC_DEFAULT;
 -      if (pf->hw.phy.link_info.an_info &
 -         (I40E_AQ_LINK_PAUSE_TX | I40E_AQ_LINK_PAUSE_RX))
 +      /* requested_mode is set in probe or by ethtool */
 +      if (!pf->fc_autoneg_status)
 +              goto no_autoneg;
 +
 +      if ((pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) &&
 +          (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX))
                pf->hw.fc.current_mode = I40E_FC_FULL;
        else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX)
                pf->hw.fc.current_mode = I40E_FC_TX_PAUSE;
        else if (pf->hw.phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX)
                pf->hw.fc.current_mode = I40E_FC_RX_PAUSE;
        else
 -              pf->hw.fc.current_mode = I40E_FC_DEFAULT;
 +              pf->hw.fc.current_mode = I40E_FC_NONE;
 +
 +      /* sync the flow control settings with the auto-neg values */
 +      switch (pf->hw.fc.current_mode) {
 +      case I40E_FC_FULL:
 +              txfc = 1;
 +              rxfc = 1;
 +              break;
 +      case I40E_FC_TX_PAUSE:
 +              txfc = 1;
 +              rxfc = 0;
 +              break;
 +      case I40E_FC_RX_PAUSE:
 +              txfc = 0;
 +              rxfc = 1;
 +              break;
 +      case I40E_FC_NONE:
 +      case I40E_FC_DEFAULT:
 +              txfc = 0;
 +              rxfc = 0;
 +              break;
 +      case I40E_FC_PFC:
 +              /* TBD */
 +              break;
 +      /* no default case, we have to handle all possibilities here */
 +      }
 +
 +      wr32(&pf->hw, I40E_PRTDCB_FCCFG, txfc << I40E_PRTDCB_FCCFG_TFCE_SHIFT);
 +
 +      rxfc_reg = rd32(&pf->hw, I40E_PRTDCB_MFLCN) &
 +                 ~I40E_PRTDCB_MFLCN_RFCE_MASK;
 +      rxfc_reg |= (rxfc << I40E_PRTDCB_MFLCN_RFCE_SHIFT);
  
 +      wr32(&pf->hw, I40E_PRTDCB_MFLCN, rxfc_reg);
 +
 +      goto fc_complete;
 +
 +no_autoneg:
 +      /* disable L2 flow control, user can turn it on if they wish */
 +      wr32(&pf->hw, I40E_PRTDCB_FCCFG, 0);
 +      wr32(&pf->hw, I40E_PRTDCB_MFLCN, rd32(&pf->hw, I40E_PRTDCB_MFLCN) &
 +                                       ~I40E_PRTDCB_MFLCN_RFCE_MASK);
 +
 +fc_complete:
        return ret;
  }
  
@@@ -7185,7 -6875,7 +7189,7 @@@ static u16 i40e_set_rss_size(struct i40
        int num_tc0;
  
        num_tc0 = min_t(int, queues_left, pf->rss_size_max);
 -      num_tc0 = min_t(int, num_tc0, nr_cpus_node(numa_node_id()));
 +      num_tc0 = min_t(int, num_tc0, num_online_cpus());
        num_tc0 = rounddown_pow_of_two(num_tc0);
  
        return num_tc0;
@@@ -7236,7 -6926,7 +7240,7 @@@ static void i40e_determine_queue_usage(
                pf->rss_size = i40e_set_rss_size(pf, queues_left);
  
                queues_left -= pf->rss_size;
 -              pf->num_lan_qps = pf->rss_size;
 +              pf->num_lan_qps = pf->rss_size_max;
  
        } else if (pf->flags & I40E_FLAG_RSS_ENABLED      &&
                   !(pf->flags & I40E_FLAG_FDIR_ENABLED)  &&
                        return;
                }
  
 -              pf->num_lan_qps = pf->rss_size + accum_tc_size;
 +              pf->num_lan_qps = pf->rss_size_max + accum_tc_size;
  
        } else if (pf->flags & I40E_FLAG_RSS_ENABLED   &&
                  (pf->flags & I40E_FLAG_FDIR_ENABLED) &&
                        return;
                }
  
 -              pf->num_lan_qps = pf->rss_size;
 +              pf->num_lan_qps = pf->rss_size_max;
  
        } else if (pf->flags & I40E_FLAG_RSS_ENABLED   &&
                  (pf->flags & I40E_FLAG_FDIR_ENABLED) &&
                        return;
                }
  
 -              pf->num_lan_qps = pf->rss_size + accum_tc_size;
 +              pf->num_lan_qps = pf->rss_size_max + accum_tc_size;
  
        } else {
                dev_info(&pf->pdev->dev,
                queues_left -= (pf->num_vmdq_vsis * pf->num_vmdq_qps);
        }
  
 +      pf->queues_left = queues_left;
        return;
  }
  
@@@ -7364,7 -7053,6 +7368,7 @@@ static int i40e_probe(struct pci_dev *p
        struct i40e_driver_version dv;
        struct i40e_pf *pf;
        struct i40e_hw *hw;
 +      static u16 pfs_found;
        int err = 0;
        u32 len;
  
        hw->subsystem_device_id = pdev->subsystem_device;
        hw->bus.device = PCI_SLOT(pdev->devfn);
        hw->bus.func = PCI_FUNC(pdev->devfn);
 +      pf->instance = pfs_found;
 +
 +      /* do a special CORER for clearing PXE mode once at init */
 +      if (hw->revision_id == 0 &&
 +          (rd32(hw, I40E_GLLAN_RCTL_0) & I40E_GLLAN_RCTL_0_PXE_MODE_MASK)) {
 +              wr32(hw, I40E_GLGEN_RTRIG, I40E_GLGEN_RTRIG_CORER_MASK);
 +              i40e_flush(hw);
 +              msleep(200);
 +              pf->corer_count++;
 +
 +              i40e_clear_pxe_mode(hw);
 +      }
  
        /* Reset here to make sure all is clean and to define PF 'n' */
        err = i40e_pf_reset(hw);
                goto err_pf_reset;
        }
  
 +      /* set up a default setting for link flow control */
 +      pf->hw.fc.requested_mode = I40E_FC_NONE;
 +
        err = i40e_init_adminq(hw);
        dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw));
 +      if (((hw->nvm.version & I40E_NVM_VERSION_HI_MASK)
 +               >> I40E_NVM_VERSION_HI_SHIFT) != I40E_CURRENT_NVM_VERSION_HI) {
 +              dev_info(&pdev->dev,
 +                       "warning: NVM version not supported, supported version: %02x.%02x\n",
 +                       I40E_CURRENT_NVM_VERSION_HI,
 +                       I40E_CURRENT_NVM_VERSION_LO);
 +      }
        if (err) {
                dev_info(&pdev->dev,
                         "init_adminq failed: %d expecting API %02x.%02x\n",
                goto err_switch_setup;
        }
  
 -      err = i40e_setup_pf_switch(pf);
 +      err = i40e_setup_pf_switch(pf, false);
        if (err) {
                dev_info(&pdev->dev, "setup_pf_switch failed: %d\n", err);
                goto err_vsis;
                i40e_flush(hw);
        }
  
 +      pfs_found++;
 +
        i40e_dbg_pf_init(pf);
  
        /* tell the firmware that we're starting */
@@@ -7749,11 -7413,7 +7753,11 @@@ static pci_ers_result_t i40e_pci_error_
        dev_info(&pdev->dev, "%s: error %d\n", __func__, error);
  
        /* shutdown all operations */
 -      i40e_pf_quiesce_all_vsi(pf);
 +      if (!test_bit(__I40E_SUSPENDED, &pf->state)) {
 +              rtnl_lock();
 +              i40e_prep_for_reset(pf);
 +              rtnl_unlock();
 +      }
  
        /* Request a slot reset */
        return PCI_ERS_RESULT_NEED_RESET;
@@@ -7816,95 -7476,9 +7820,95 @@@ static void i40e_pci_error_resume(struc
        struct i40e_pf *pf = pci_get_drvdata(pdev);
  
        dev_info(&pdev->dev, "%s\n", __func__);
 +      if (test_bit(__I40E_SUSPENDED, &pf->state))
 +              return;
 +
 +      rtnl_lock();
        i40e_handle_reset_warning(pf);
 +      rtnl_lock();
 +}
 +
 +/**
 + * i40e_shutdown - PCI callback for shutting down
 + * @pdev: PCI device information struct
 + **/
 +static void i40e_shutdown(struct pci_dev *pdev)
 +{
 +      struct i40e_pf *pf = pci_get_drvdata(pdev);
 +
 +      set_bit(__I40E_SUSPENDED, &pf->state);
 +      set_bit(__I40E_DOWN, &pf->state);
 +      rtnl_lock();
 +      i40e_prep_for_reset(pf);
 +      rtnl_unlock();
 +
 +      if (system_state == SYSTEM_POWER_OFF) {
 +              pci_wake_from_d3(pdev, false);    /* No WoL support yet */
 +              pci_set_power_state(pdev, PCI_D3hot);
 +      }
 +}
 +
 +#ifdef CONFIG_PM
 +/**
 + * i40e_suspend - PCI callback for moving to D3
 + * @pdev: PCI device information struct
 + **/
 +static int i40e_suspend(struct pci_dev *pdev, pm_message_t state)
 +{
 +      struct i40e_pf *pf = pci_get_drvdata(pdev);
 +
 +      set_bit(__I40E_SUSPENDED, &pf->state);
 +      set_bit(__I40E_DOWN, &pf->state);
 +      rtnl_lock();
 +      i40e_prep_for_reset(pf);
 +      rtnl_unlock();
 +
 +      pci_wake_from_d3(pdev, false);    /* No WoL support yet */
 +      pci_set_power_state(pdev, PCI_D3hot);
 +
 +      return 0;
  }
  
 +/**
 + * i40e_resume - PCI callback for waking up from D3
 + * @pdev: PCI device information struct
 + **/
 +static int i40e_resume(struct pci_dev *pdev)
 +{
 +      struct i40e_pf *pf = pci_get_drvdata(pdev);
 +      u32 err;
 +
 +      pci_set_power_state(pdev, PCI_D0);
 +      pci_restore_state(pdev);
 +      /* pci_restore_state() clears dev->state_saves, so
 +       * call pci_save_state() again to restore it.
 +       */
 +      pci_save_state(pdev);
 +
 +      err = pci_enable_device_mem(pdev);
 +      if (err) {
 +              dev_err(&pdev->dev,
 +                      "%s: Cannot enable PCI device from suspend\n",
 +                      __func__);
 +              return err;
 +      }
 +      pci_set_master(pdev);
 +
 +      /* no wakeup events while running */
 +      pci_wake_from_d3(pdev, false);
 +
 +      /* handling the reset will rebuild the device state */
 +      if (test_and_clear_bit(__I40E_SUSPENDED, &pf->state)) {
 +              clear_bit(__I40E_DOWN, &pf->state);
 +              rtnl_lock();
 +              i40e_reset_and_rebuild(pf, false);
 +              rtnl_unlock();
 +      }
 +
 +      return 0;
 +}
 +
 +#endif
  static const struct pci_error_handlers i40e_err_handler = {
        .error_detected = i40e_pci_error_detected,
        .slot_reset = i40e_pci_error_slot_reset,
@@@ -7916,11 -7490,6 +7920,11 @@@ static struct pci_driver i40e_driver = 
        .id_table = i40e_pci_tbl,
        .probe    = i40e_probe,
        .remove   = i40e_remove,
 +#ifdef CONFIG_PM
 +      .suspend  = i40e_suspend,
 +      .resume   = i40e_resume,
 +#endif
 +      .shutdown = i40e_shutdown,
        .err_handler = &i40e_err_handler,
        .sriov_configure = i40e_pci_sriov_configure,
  };
@@@ -15,7 -15,6 +15,7 @@@
  
  #define RSS_HASHTYPE_IP_TCP           0x3
  #define QLC_83XX_FW_MBX_CMD           0
 +#define QLC_SKIP_INACTIVE_PCI_REGS    7
  
  static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
        {QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
@@@ -35,7 -34,7 +35,7 @@@
        {QLCNIC_CMD_READ_MAX_MTU, 4, 2},
        {QLCNIC_CMD_READ_MAX_LRO, 4, 2},
        {QLCNIC_CMD_MAC_ADDRESS, 4, 3},
 -      {QLCNIC_CMD_GET_PCI_INFO, 1, 66},
 +      {QLCNIC_CMD_GET_PCI_INFO, 1, 129},
        {QLCNIC_CMD_GET_NIC_INFO, 2, 19},
        {QLCNIC_CMD_SET_NIC_INFO, 32, 1},
        {QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3},
@@@ -69,7 -68,7 +69,7 @@@
        {QLCNIC_CMD_CONFIG_VPORT, 4, 4},
        {QLCNIC_CMD_BC_EVENT_SETUP, 2, 1},
        {QLCNIC_CMD_DCB_QUERY_CAP, 1, 2},
 -      {QLCNIC_CMD_DCB_QUERY_PARAM, 2, 50},
 +      {QLCNIC_CMD_DCB_QUERY_PARAM, 1, 50},
  };
  
  const u32 qlcnic_83xx_ext_reg_tbl[] = {
@@@ -290,7 -289,6 +290,7 @@@ int qlcnic_83xx_setup_intr(struct qlcni
                if (qlcnic_sriov_vf_check(adapter))
                        return -EINVAL;
                num_msix = 1;
 +              adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
        }
        /* setup interrupt mapping table for fw */
        ahw->intr_tbl = vzalloc(num_msix *
@@@ -449,8 -447,9 +449,9 @@@ irqreturn_t qlcnic_83xx_intr(int irq, v
  
        qlcnic_83xx_poll_process_aen(adapter);
  
-       if (ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
-               ahw->diag_cnt++;
+       if (ahw->diag_test) {
+               if (ahw->diag_test == QLCNIC_INTERRUPT_TEST)
+                       ahw->diag_cnt++;
                qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
                return IRQ_HANDLED;
        }
@@@ -638,7 -637,7 +639,7 @@@ int qlcnic_83xx_get_port_info(struct ql
  void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
  {
        struct qlcnic_hardware_context *ahw = adapter->ahw;
 -      u16 act_pci_fn = ahw->act_pci_func;
 +      u16 act_pci_fn = ahw->total_nic_func;
        u16 count;
  
        ahw->max_mc_count = QLC_83XX_MAX_MC_COUNT;
@@@ -1347,11 -1346,6 +1348,6 @@@ static int qlcnic_83xx_diag_alloc_res(s
        }
  
        if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
-               /* disable and free mailbox interrupt */
-               if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-                       qlcnic_83xx_enable_mbx_poll(adapter);
-                       qlcnic_83xx_free_mbx_intr(adapter);
-               }
                adapter->ahw->loopback_state = 0;
                adapter->ahw->hw_ops->setup_link_event(adapter, 1);
        }
@@@ -1365,33 -1359,20 +1361,20 @@@ static void qlcnic_83xx_diag_free_res(s
  {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_host_sds_ring *sds_ring;
-       int ring, err;
+       int ring;
  
        clear_bit(__QLCNIC_DEV_UP, &adapter->state);
        if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx->sds_rings[ring];
-                       qlcnic_83xx_disable_intr(adapter, sds_ring);
-                       if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
-                               qlcnic_83xx_enable_mbx_poll(adapter);
+                       if (adapter->flags & QLCNIC_MSIX_ENABLED)
+                               qlcnic_83xx_disable_intr(adapter, sds_ring);
                }
        }
  
        qlcnic_fw_destroy_ctx(adapter);
        qlcnic_detach(adapter);
  
-       if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
-               if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
-                       err = qlcnic_83xx_setup_mbx_intr(adapter);
-                       qlcnic_83xx_disable_mbx_poll(adapter);
-                       if (err) {
-                               dev_err(&adapter->pdev->dev,
-                                       "%s: failed to setup mbx interrupt\n",
-                                       __func__);
-                               goto out;
-                       }
-               }
-       }
        adapter->ahw->diag_test = 0;
        adapter->drv_sds_rings = drv_sds_rings;
  
        if (netif_running(netdev))
                __qlcnic_up(adapter, netdev);
  
-       if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST &&
-           !(adapter->flags & QLCNIC_MSIX_ENABLED))
-               qlcnic_83xx_disable_mbx_poll(adapter);
  out:
        netif_device_attach(netdev);
  }
@@@ -1520,7 -1498,8 +1500,7 @@@ int  qlcnic_83xx_set_led(struct net_dev
        return err;
  }
  
 -void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter,
 -                                     int enable)
 +void qlcnic_83xx_initialize_nic(struct qlcnic_adapter *adapter, int enable)
  {
        struct qlcnic_cmd_args cmd;
        int status;
        if (qlcnic_sriov_vf_check(adapter))
                return;
  
 -      if (enable) {
 +      if (enable)
                status = qlcnic_alloc_mbx_args(&cmd, adapter,
                                               QLCNIC_CMD_INIT_NIC_FUNC);
 -              if (status)
 -                      return;
 -
 -              cmd.req.arg[1] = BIT_0 | BIT_31;
 -      } else {
 +      else
                status = qlcnic_alloc_mbx_args(&cmd, adapter,
                                               QLCNIC_CMD_STOP_NIC_FUNC);
 -              if (status)
 -                      return;
  
 -              cmd.req.arg[1] = BIT_0 | BIT_31;
 -      }
 +      if (status)
 +              return;
 +
 +      cmd.req.arg[1] = QLC_REGISTER_LB_IDC | QLC_INIT_FW_RESOURCES;
 +
 +      if (adapter->dcb)
 +              cmd.req.arg[1] |= QLC_REGISTER_DCB_AEN;
 +
        status = qlcnic_issue_cmd(adapter, &cmd);
        if (status)
                dev_err(&adapter->pdev->dev,
@@@ -1638,7 -1617,7 +1618,7 @@@ int qlcnic_83xx_nic_set_promisc(struct 
  
        cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
        qlcnic_83xx_set_interface_id_promisc(adapter, &temp);
 -      cmd->req.arg[1] = (mode ? 1 : 0) | temp;
 +      cmd->req.arg[1] = mode | temp;
        err = qlcnic_issue_cmd(adapter, cmd);
        if (!err)
                return err;
        return err;
  }
  
 +int qlcnic_get_pci_func_type(struct qlcnic_adapter *adapter, u16 type,
 +                           u16 *nic, u16 *fcoe, u16 *iscsi)
 +{
 +      struct device *dev = &adapter->pdev->dev;
 +      int err = 0;
 +
 +      switch (type) {
 +      case QLCNIC_TYPE_NIC:
 +              (*nic)++;
 +              break;
 +      case QLCNIC_TYPE_FCOE:
 +              (*fcoe)++;
 +              break;
 +      case QLCNIC_TYPE_ISCSI:
 +              (*iscsi)++;
 +              break;
 +      default:
 +              dev_err(dev, "%s: Unknown PCI type[%x]\n",
 +                      __func__, type);
 +              err = -EIO;
 +      }
 +
 +      return err;
 +}
 +
  int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
                             struct qlcnic_pci_info *pci_info)
  {
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct device *dev = &adapter->pdev->dev;
 +      u16 nic = 0, fcoe = 0, iscsi = 0;
        struct qlcnic_cmd_args cmd;
        int i, err = 0, j = 0;
        u32 temp;
  
        err = qlcnic_issue_cmd(adapter, &cmd);
  
 -      ahw->act_pci_func = 0;
 +      ahw->total_nic_func = 0;
        if (err == QLCNIC_RCODE_SUCCESS) {
                ahw->max_pci_func = cmd.rsp.arg[1] & 0xFF;
 -              for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) {
 +              for (i = 2, j = 0; j < ahw->max_vnic_func; j++, pci_info++) {
                        pci_info->id = cmd.rsp.arg[i] & 0xFFFF;
                        pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
                        i++;
 +                      if (!pci_info->active) {
 +                              i += QLC_SKIP_INACTIVE_PCI_REGS;
 +                              continue;
 +                      }
                        pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
 -                      if (pci_info->type == QLCNIC_TYPE_NIC)
 -                              ahw->act_pci_func++;
 +                      err = qlcnic_get_pci_func_type(adapter, pci_info->type,
 +                                                     &nic, &fcoe, &iscsi);
                        temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
                        pci_info->default_port = temp;
                        i++;
                err = -EIO;
        }
  
 +      ahw->total_nic_func = nic;
 +      ahw->total_pci_func = nic + fcoe + iscsi;
 +      if (ahw->total_nic_func == 0 || ahw->total_pci_func == 0) {
 +              dev_err(dev, "%s: Invalid function count: total nic func[%x], total pci func[%x]\n",
 +                      __func__, ahw->total_nic_func, ahw->total_pci_func);
 +              err = -EIO;
 +      }
        qlcnic_free_mbx_args(&cmd);
  
        return err;
@@@ -3792,6 -3734,19 +3772,19 @@@ static void qlcnic_83xx_decode_mbx_rsp(
        return;
  }
  
+ static inline void qlcnic_dump_mailbox_registers(struct qlcnic_adapter *adapter)
+ {
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       u32 offset;
+       offset = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
+       dev_info(&adapter->pdev->dev, "Mbx interrupt mask=0x%x, Mbx interrupt enable=0x%x, Host mbx control=0x%x, Fw mbx control=0x%x",
+                readl(ahw->pci_base0 + offset),
+                QLCRDX(ahw, QLCNIC_MBX_INTR_ENBL),
+                QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL),
+                QLCRDX(ahw, QLCNIC_FW_MBX_CTRL));
+ }
  static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
  {
        struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox,
                                __func__, cmd->cmd_op, cmd->type, ahw->pci_func,
                                ahw->op_mode);
                        clear_bit(QLC_83XX_MBX_READY, &mbx->status);
+                       qlcnic_dump_mailbox_registers(adapter);
+                       qlcnic_83xx_get_mbx_data(adapter, cmd);
                        qlcnic_dump_mbx(adapter, cmd);
                        qlcnic_83xx_idc_request_reset(adapter,
                                                      QLCNIC_FORCE_FW_DUMP_KEY);
@@@ -324,11 -324,6 +324,11 @@@ struct qlc_83xx_idc 
        char            **name;
  };
  
 +enum qlcnic_vlan_operations {
 +      QLC_VLAN_ADD = 0,
 +      QLC_VLAN_DELETE
 +};
 +
  /* Device States */
  enum qlcnic_83xx_states {
        QLC_83XX_IDC_DEV_UNKNOWN,
@@@ -523,11 -518,6 +523,11 @@@ enum qlc_83xx_ext_regs 
        QLC_83XX_ASIC_TEMP,
  };
  
 +/* Initialize/Stop NIC command bit definitions */
 +#define QLC_REGISTER_DCB_AEN          BIT_1
 +#define QLC_REGISTER_LB_IDC           BIT_0
 +#define QLC_INIT_FW_RESOURCES         BIT_31
 +
  /* 83xx funcitons */
  int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *);
  int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
@@@ -552,7 -542,7 +552,7 @@@ int qlcnic_83xx_config_intr_coalesce(st
  void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *, u64 *, u16);
  int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *);
  int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
 -void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *, int);
 +void qlcnic_83xx_initialize_nic(struct qlcnic_adapter *, int);
  
  int qlcnic_83xx_napi_add(struct qlcnic_adapter *, struct net_device *);
  void qlcnic_83xx_napi_del(struct qlcnic_adapter *);
@@@ -672,4 -662,5 +672,5 @@@ pci_ers_result_t qlcnic_83xx_io_error_d
                                               pci_channel_state_t);
  pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *);
  void qlcnic_83xx_io_resume(struct pci_dev *);
+ void qlcnic_83xx_stop_hw(struct qlcnic_adapter *);
  #endif
@@@ -614,7 -614,8 +614,7 @@@ int qlcnic_83xx_idc_reattach_driver(str
        qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox);
        qlcnic_83xx_enable_mbx_interrupt(adapter);
  
 -      /* register for NIC IDC AEN Events */
 -      qlcnic_83xx_register_nic_idc_func(adapter, 1);
 +      qlcnic_83xx_initialize_nic(adapter, 1);
  
        err = qlcnic_sriov_pf_reinit(adapter);
        if (err)
@@@ -739,6 -740,7 +739,7 @@@ static int qlcnic_83xx_idc_unknown_stat
        adapter->ahw->idc.err_code = -EIO;
        dev_err(&adapter->pdev->dev,
                "%s: Device in unknown state\n", __func__);
+       clear_bit(__QLCNIC_RESETTING, &adapter->state);
        return 0;
  }
  
@@@ -817,7 -819,6 +818,6 @@@ static int qlcnic_83xx_idc_ready_state(
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct qlcnic_mailbox *mbx = ahw->mailbox;
        int ret = 0;
-       u32 owner;
        u32 val;
  
        /* Perform NIC configuration based ready state entry actions */
                        set_bit(__QLCNIC_RESETTING, &adapter->state);
                        qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
                }  else {
-                       owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
-                       if (ahw->pci_func == owner)
-                               qlcnic_dump_fw(adapter);
+                       netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                                   __func__);
+                       qlcnic_83xx_idc_enter_failed_state(adapter, 1);
                }
                return -EIO;
        }
@@@ -947,13 -948,26 +947,26 @@@ static int qlcnic_83xx_idc_need_quiesce
        return 0;
  }
  
- static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
+ static void qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter)
  {
-       dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__);
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       u32 val, owner;
+       val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
+               if (ahw->pci_func == owner) {
+                       qlcnic_83xx_stop_hw(adapter);
+                       qlcnic_dump_fw(adapter);
+               }
+       }
+       netdev_warn(adapter->netdev, "%s: Reboot will be required to recover the adapter!!\n",
+                   __func__);
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
-       adapter->ahw->idc.err_code = -EIO;
+       ahw->idc.err_code = -EIO;
  
-       return 0;
+       return;
  }
  
  static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter)
@@@ -1062,12 -1076,6 +1075,6 @@@ void qlcnic_83xx_idc_poll_dev_state(str
        adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state;
        qlcnic_83xx_periodic_tasks(adapter);
  
-       /* Do not reschedule if firmaware is in hanged state and auto
-        * recovery is disabled
-        */
-       if ((adapter->flags & QLCNIC_FW_HANG) && !qlcnic_auto_fw_reset)
-               return;
        /* Re-schedule the function */
        if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status))
                qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
@@@ -1218,10 -1226,10 +1225,10 @@@ void qlcnic_83xx_idc_request_reset(stru
        }
  
        val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
-       if ((val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) ||
-           !qlcnic_auto_fw_reset) {
-               dev_err(&adapter->pdev->dev,
-                       "%s:failed, device in non reset mode\n", __func__);
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                           __func__);
+               qlcnic_83xx_idc_enter_failed_state(adapter, 0);
                qlcnic_83xx_unlock_driver(adapter);
                return;
        }
@@@ -1253,24 -1261,24 +1260,24 @@@ static int qlcnic_83xx_copy_bootloader(
        if (size & 0xF)
                size = (size + 16) & ~0xF;
  
-       p_cache = kzalloc(size, GFP_KERNEL);
+       p_cache = vzalloc(size);
        if (p_cache == NULL)
                return -ENOMEM;
  
        ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache,
                                                size / sizeof(u32));
        if (ret) {
-               kfree(p_cache);
+               vfree(p_cache);
                return ret;
        }
        /* 16 byte write to MS memory */
        ret = qlcnic_83xx_ms_mem_write128(adapter, dest, (u32 *)p_cache,
                                          size / 16);
        if (ret) {
-               kfree(p_cache);
+               vfree(p_cache);
                return ret;
        }
-       kfree(p_cache);
+       vfree(p_cache);
  
        return ret;
  }
@@@ -1938,7 -1946,7 +1945,7 @@@ static void qlcnic_83xx_exec_template_c
        p_dev->ahw->reset.seq_index = index;
  }
  
static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
+ void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev)
  {
        p_dev->ahw->reset.seq_index = 0;
  
@@@ -1993,6 -2001,14 +2000,14 @@@ static int qlcnic_83xx_restart_hw(struc
        val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
        if (!(val & QLC_83XX_IDC_GRACEFULL_RESET))
                qlcnic_dump_fw(adapter);
+       if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) {
+               netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n",
+                           __func__);
+               qlcnic_83xx_idc_enter_failed_state(adapter, 1);
+               return err;
+       }
        qlcnic_83xx_init_hw(adapter);
  
        if (qlcnic_83xx_copy_bootloader(adapter))
@@@ -2072,8 -2088,8 +2087,8 @@@ int qlcnic_83xx_configure_opmode(struc
                ahw->nic_mode = QLCNIC_DEFAULT_MODE;
                adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
                ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
-               adapter->max_sds_rings = ahw->max_rx_ques;
-               adapter->max_tx_rings = ahw->max_tx_ques;
+               adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
+               adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS;
        } else {
                return -EIO;
        }
@@@ -2197,6 -2213,7 +2212,6 @@@ static void qlcnic_83xx_init_rings(stru
  int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
  {
        struct qlcnic_hardware_context *ahw = adapter->ahw;
 -      struct qlcnic_dcb *dcb;
        int err = 0;
  
        ahw->msix_supported = !!qlcnic_use_msi_x;
  
        INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
  
 -      /* register for NIC IDC AEN Events */
 -      qlcnic_83xx_register_nic_idc_func(adapter, 1);
 +      qlcnic_83xx_initialize_nic(adapter, 1);
  
        /* Configure default, SR-IOV or Virtual NIC mode of operation */
        err = qlcnic_83xx_configure_opmode(adapter);
        if (err)
                goto disable_mbx_intr;
  
 -      dcb = adapter->dcb;
 -
 -      if (dcb && qlcnic_dcb_attach(dcb))
 -              qlcnic_clear_dcb_ops(dcb);
 -
        /* Periodically monitor device status */
        qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work);
        return 0;
@@@ -2291,7 -2314,7 +2306,7 @@@ void qlcnic_83xx_aer_stop_poll_work(str
                qlcnic_83xx_disable_vnic_mode(adapter, 1);
  
        qlcnic_83xx_idc_detach_driver(adapter);
 -      qlcnic_83xx_register_nic_idc_func(adapter, 0);
 +      qlcnic_83xx_initialize_nic(adapter, 0);
  
        cancel_delayed_work_sync(&adapter->idc_aen_work);
  }
@@@ -221,7 -221,7 +221,7 @@@ static const u32 ext_diag_registers[] 
        -1
  };
  
 -#define QLCNIC_MGMT_API_VERSION       2
 +#define QLCNIC_MGMT_API_VERSION       3
  #define QLCNIC_ETHTOOL_REGS_VER       4
  
  static inline int qlcnic_get_ring_regs_len(struct qlcnic_adapter *adapter)
@@@ -519,9 -519,6 +519,9 @@@ qlcnic_get_regs(struct net_device *dev
        regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
        regs_buff[1] = QLCNIC_MGMT_API_VERSION;
  
 +      if (adapter->ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
 +              regs_buff[2] = adapter->ahw->max_vnic_func;
 +
        if (qlcnic_82xx_check(adapter))
                i = qlcnic_82xx_get_registers(adapter, regs_buff);
        else
@@@ -670,30 -667,25 +670,25 @@@ qlcnic_set_ringparam(struct net_device 
  static int qlcnic_validate_ring_count(struct qlcnic_adapter *adapter,
                                      u8 rx_ring, u8 tx_ring)
  {
+       if (rx_ring == 0 || tx_ring == 0)
+               return -EINVAL;
        if (rx_ring != 0) {
                if (rx_ring > adapter->max_sds_rings) {
-                       netdev_err(adapter->netdev, "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
+                       netdev_err(adapter->netdev,
+                                  "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
                                   rx_ring, adapter->max_sds_rings);
                        return -EINVAL;
                }
        }
  
         if (tx_ring != 0) {
-               if (qlcnic_82xx_check(adapter) &&
-                   (tx_ring > adapter->max_tx_rings)) {
+               if (tx_ring > adapter->max_tx_rings) {
                        netdev_err(adapter->netdev,
                                   "Invalid ring count, Tx ring count %d should not be greater than max %d driver Tx rings.\n",
                                   tx_ring, adapter->max_tx_rings);
                        return -EINVAL;
                }
-               if (qlcnic_83xx_check(adapter) &&
-                   (tx_ring > QLCNIC_SINGLE_RING)) {
-                       netdev_err(adapter->netdev,
-                                  "Invalid ring count, Tx ring count %d should not be greater than %d driver Tx rings.\n",
-                                  tx_ring, QLCNIC_SINGLE_RING);
-                        return -EINVAL;
-               }
        }
  
        return 0;
@@@ -951,6 -943,7 +946,7 @@@ static int qlcnic_irq_test(struct net_d
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct qlcnic_cmd_args cmd;
        int ret, drv_sds_rings = adapter->drv_sds_rings;
+       int drv_tx_rings = adapter->drv_tx_rings;
  
        if (qlcnic_83xx_check(adapter))
                return qlcnic_83xx_interrupt_test(netdev);
@@@ -983,6 -976,7 +979,7 @@@ free_diag_res
  
  clear_diag_irq:
        adapter->drv_sds_rings = drv_sds_rings;
+       adapter->drv_tx_rings = drv_tx_rings;
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
  
        return ret;
@@@ -687,17 -687,11 +687,11 @@@ void qlcnic_advert_link_change(struct q
        if (adapter->ahw->linkup && !linkup) {
                netdev_info(netdev, "NIC Link is down\n");
                adapter->ahw->linkup = 0;
-               if (netif_running(netdev)) {
-                       netif_carrier_off(netdev);
-                       netif_tx_stop_all_queues(netdev);
-               }
+               netif_carrier_off(netdev);
        } else if (!adapter->ahw->linkup && linkup) {
                netdev_info(netdev, "NIC Link is up\n");
                adapter->ahw->linkup = 1;
-               if (netif_running(netdev)) {
-                       netif_carrier_on(netdev);
-                       netif_wake_queue(netdev);
-               }
+               netif_carrier_on(netdev);
        }
  }
  
@@@ -1466,7 -1460,8 +1460,7 @@@ int qlcnic_82xx_napi_add(struct qlcnic_
        for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
                sds_ring = &recv_ctx->sds_rings[ring];
                if (qlcnic_check_multi_tx(adapter) &&
 -                  !adapter->ahw->diag_test &&
 -                  (adapter->drv_tx_rings > QLCNIC_SINGLE_RING)) {
 +                  !adapter->ahw->diag_test) {
                        netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll,
                                       NAPI_POLL_WEIGHT);
                } else {
@@@ -1539,7 -1534,8 +1533,7 @@@ void qlcnic_82xx_napi_enable(struct qlc
  
        if (qlcnic_check_multi_tx(adapter) &&
            (adapter->flags & QLCNIC_MSIX_ENABLED) &&
 -          !adapter->ahw->diag_test &&
 -          (adapter->drv_tx_rings > QLCNIC_SINGLE_RING)) {
 +          !adapter->ahw->diag_test) {
                for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
                        tx_ring = &adapter->tx_ring[ring];
                        napi_enable(&tx_ring->napi);
@@@ -308,11 -308,11 +308,11 @@@ int qlcnic_read_mac_addr(struct qlcnic_
  
  static void qlcnic_delete_adapter_mac(struct qlcnic_adapter *adapter)
  {
 -      struct qlcnic_mac_list_s *cur;
 +      struct qlcnic_mac_vlan_list *cur;
        struct list_head *head;
  
        list_for_each(head, &adapter->mac_list) {
 -              cur = list_entry(head, struct qlcnic_mac_list_s, list);
 +              cur = list_entry(head, struct qlcnic_mac_vlan_list, list);
                if (!memcmp(adapter->mac_addr, cur->mac_addr, ETH_ALEN)) {
                        qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
                                                  0, QLCNIC_MAC_DEL);
@@@ -646,7 -646,8 +646,7 @@@ int qlcnic_enable_msix(struct qlcnic_ad
                        } else {
                                adapter->ahw->num_msix = num_msix;
                                if (qlcnic_check_multi_tx(adapter) &&
 -                                  !adapter->ahw->diag_test &&
 -                                  (adapter->drv_tx_rings > 1))
 +                                  !adapter->ahw->diag_test)
                                        drv_sds_rings = num_msix - drv_tx_rings;
                                else
                                        drv_sds_rings = num_msix;
@@@ -799,26 -800,25 +799,26 @@@ static void qlcnic_cleanup_pci_map(stru
  
  static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter)
  {
 +      struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct qlcnic_pci_info *pci_info;
        int ret;
  
        if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
 -              switch (adapter->ahw->port_type) {
 +              switch (ahw->port_type) {
                case QLCNIC_GBE:
 -                      adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_GBE_PORTS;
 +                      ahw->total_nic_func = QLCNIC_NIU_MAX_GBE_PORTS;
                        break;
                case QLCNIC_XGBE:
 -                      adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_XG_PORTS;
 +                      ahw->total_nic_func = QLCNIC_NIU_MAX_XG_PORTS;
                        break;
                }
                return 0;
        }
  
 -      if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
 +      if (ahw->op_mode == QLCNIC_MGMT_FUNC)
                return 0;
  
 -      pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
 +      pci_info = kcalloc(ahw->max_vnic_func, sizeof(*pci_info), GFP_KERNEL);
        if (!pci_info)
                return -ENOMEM;
  
@@@ -846,13 -846,12 +846,13 @@@ static bool qlcnic_port_eswitch_cfg_cap
  
  int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
  {
 +      struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct qlcnic_pci_info *pci_info;
        int i, id = 0, ret = 0, j = 0;
        u16 act_pci_func;
        u8 pfn;
  
 -      pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
 +      pci_info = kcalloc(ahw->max_vnic_func, sizeof(*pci_info), GFP_KERNEL);
        if (!pci_info)
                return -ENOMEM;
  
        if (ret)
                goto err_pci_info;
  
 -      act_pci_func = adapter->ahw->act_pci_func;
 +      act_pci_func = ahw->total_nic_func;
  
        adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
                                 act_pci_func, GFP_KERNEL);
                goto err_npars;
        }
  
 -      for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
 +      for (i = 0; i < ahw->max_vnic_func; i++) {
                pfn = pci_info[i].id;
  
 -              if (pfn >= QLCNIC_MAX_PCI_FUNC) {
 +              if (pfn >= ahw->max_vnic_func) {
                        ret = QL_STATUS_INVALID_PARAM;
                        goto err_eswitch;
                }
@@@ -1179,6 -1178,7 +1179,7 @@@ qlcnic_initialize_nic(struct qlcnic_ada
        } else {
                adapter->ahw->nic_mode = QLCNIC_DEFAULT_MODE;
                adapter->max_tx_rings = QLCNIC_MAX_HW_TX_RINGS;
+               adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS;
                adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
        }
  
@@@ -1346,7 -1346,7 +1347,7 @@@ int qlcnic_set_default_offload_settings
        if (adapter->need_fw_reset)
                return 0;
  
 -      for (i = 0; i < adapter->ahw->act_pci_func; i++) {
 +      for (i = 0; i < adapter->ahw->total_nic_func; i++) {
                if (!adapter->npars[i].eswitch_status)
                        continue;
  
@@@ -1409,7 -1409,7 +1410,7 @@@ int qlcnic_reset_npar_config(struct qlc
                        return 0;
  
        /* Set the NPAR config data after FW reset */
 -      for (i = 0; i < adapter->ahw->act_pci_func; i++) {
 +      for (i = 0; i < adapter->ahw->total_nic_func; i++) {
                npar = &adapter->npars[i];
                pci_func = npar->pci_func;
                if (!adapter->npars[i].eswitch_status)
@@@ -1941,7 -1941,6 +1942,6 @@@ int qlcnic_diag_alloc_res(struct net_de
        qlcnic_detach(adapter);
  
        adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
-       adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
        adapter->ahw->diag_test = test;
        adapter->ahw->linkup = 0;
  
@@@ -2038,7 -2037,7 +2038,7 @@@ qlcnic_reset_context(struct qlcnic_adap
  void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
  {
        struct qlcnic_hardware_context *ahw = adapter->ahw;
 -      u16 act_pci_fn = ahw->act_pci_func;
 +      u16 act_pci_fn = ahw->total_nic_func;
        u16 count;
  
        ahw->max_mc_count = QLCNIC_MAX_MC_COUNT;
@@@ -2213,6 -2212,7 +2213,6 @@@ qlcnic_probe(struct pci_dev *pdev, cons
        struct qlcnic_hardware_context *ahw;
        int err, pci_using_dac = -1;
        char board_name[QLCNIC_MAX_BOARD_NAME_LEN + 19]; /* MAC + ": " + name */
 -      struct qlcnic_dcb *dcb;
  
        if (pdev->is_virtfn)
                return -ENODEV;
                goto err_out_free_wq;
  
        adapter->dev_rst_time = jiffies;
 -      adapter->ahw->revision_id = pdev->revision;
 +      ahw->revision_id = pdev->revision;
 +      ahw->max_vnic_func = qlcnic_get_vnic_func_count(adapter);
        if (qlcnic_mac_learn == FDB_MAC_LEARN)
                adapter->fdb_mac_learn = true;
        else if (qlcnic_mac_learn == DRV_MAC_LEARN)
  
                adapter->flags |= QLCNIC_NEED_FLR;
  
 -              dcb = adapter->dcb;
 -
 -              if (dcb && qlcnic_dcb_attach(dcb))
 -                      qlcnic_clear_dcb_ops(dcb);
        } else if (qlcnic_83xx_check(adapter)) {
                qlcnic_83xx_check_vf(adapter, ent);
                adapter->portnum = adapter->ahw->pci_func;
                goto err_out_free_hw;
        }
  
 +      qlcnic_dcb_enable(adapter->dcb);
 +
        if (qlcnic_read_mac_addr(adapter))
                dev_warn(&pdev->dev, "failed to read mac addr\n");
  
@@@ -2499,11 -2500,13 +2499,11 @@@ static void qlcnic_remove(struct pci_de
        qlcnic_cancel_idc_work(adapter);
        ahw = adapter->ahw;
  
 -      qlcnic_dcb_free(adapter->dcb);
 -
        unregister_netdev(netdev);
        qlcnic_sriov_cleanup(adapter);
  
        if (qlcnic_83xx_check(adapter)) {
 -              qlcnic_83xx_register_nic_idc_func(adapter, 0);
 +              qlcnic_83xx_initialize_nic(adapter, 0);
                cancel_delayed_work_sync(&adapter->idc_aen_work);
                qlcnic_83xx_free_mbx_intr(adapter);
                qlcnic_83xx_detach_mailbox_work(adapter);
                kfree(ahw->fw_info);
        }
  
 +      qlcnic_dcb_free(adapter->dcb);
 +
        qlcnic_detach(adapter);
  
        if (adapter->npars != NULL)
@@@ -2641,7 -2642,7 +2641,7 @@@ void qlcnic_alloc_lb_filters_mem(struc
        if (adapter->fhash.fmax && adapter->fhash.fhead)
                return;
  
 -      act_pci_func = adapter->ahw->act_pci_func;
 +      act_pci_func = adapter->ahw->total_nic_func;
        spin_lock_init(&adapter->mac_learn_lock);
        spin_lock_init(&adapter->rx_mac_learn_lock);
  
@@@ -3724,6 -3725,12 +3724,6 @@@ int qlcnic_validate_rings(struct qlcnic
                return -EINVAL;
        }
  
 -      if (ring_cnt < 2) {
 -              netdev_err(netdev,
 -                         "%s rings value should not be lower than 2\n", buf);
 -              return -EINVAL;
 -      }
 -
        if (!is_power_of_2(ring_cnt)) {
                netdev_err(netdev, "%s rings value should be a power of 2\n",
                           buf);
@@@ -3781,7 -3788,8 +3781,7 @@@ int qlcnic_setup_rings(struct qlcnic_ad
        }
  
        if (qlcnic_83xx_check(adapter)) {
 -              /* register for NIC IDC AEN Events */
 -              qlcnic_83xx_register_nic_idc_func(adapter, 1);
 +              qlcnic_83xx_initialize_nic(adapter, 1);
                err = qlcnic_83xx_setup_mbx_intr(adapter);
                qlcnic_83xx_disable_mbx_poll(adapter);
                if (err) {
@@@ -19,7 -19,8 +19,7 @@@
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
 - * along with this program; if not, write to the Free Software
 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 + * along with this program; if not, see <http://www.gnu.org/licenses/>.
   *
   * Arguments:
   *    io      = for the base address
@@@ -81,6 -82,7 +81,7 @@@ static const char version[] 
  #include <linux/mii.h>
  #include <linux/workqueue.h>
  #include <linux/of.h>
+ #include <linux/of_device.h>
  
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
@@@ -2183,6 -2185,15 +2184,15 @@@ static void smc_release_datacs(struct p
        }
  }
  
+ #if IS_BUILTIN(CONFIG_OF)
+ static const struct of_device_id smc91x_match[] = {
+       { .compatible = "smsc,lan91c94", },
+       { .compatible = "smsc,lan91c111", },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, smc91x_match);
+ #endif
  /*
   * smc_init(void)
   *   Input parameters:
  static int smc_drv_probe(struct platform_device *pdev)
  {
        struct smc91x_platdata *pd = dev_get_platdata(&pdev->dev);
+       const struct of_device_id *match = NULL;
        struct smc_local *lp;
        struct net_device *ndev;
        struct resource *res, *ires;
         */
  
        lp = netdev_priv(ndev);
+       lp->cfg.flags = 0;
  
        if (pd) {
                memcpy(&lp->cfg, pd, sizeof(lp->cfg));
                lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
-       } else {
+       }
+ #if IS_BUILTIN(CONFIG_OF)
+       match = of_match_device(of_match_ptr(smc91x_match), &pdev->dev);
+       if (match) {
+               struct device_node *np = pdev->dev.of_node;
+               u32 val;
+               /* Combination of IO widths supported, default to 16-bit */
+               if (!of_property_read_u32(np, "reg-io-width", &val)) {
+                       if (val & 1)
+                               lp->cfg.flags |= SMC91X_USE_8BIT;
+                       if ((val == 0) || (val & 2))
+                               lp->cfg.flags |= SMC91X_USE_16BIT;
+                       if (val & 4)
+                               lp->cfg.flags |= SMC91X_USE_32BIT;
+               } else {
+                       lp->cfg.flags |= SMC91X_USE_16BIT;
+               }
+       }
+ #endif
+       if (!pd && !match) {
                lp->cfg.flags |= (SMC_CAN_USE_8BIT)  ? SMC91X_USE_8BIT  : 0;
                lp->cfg.flags |= (SMC_CAN_USE_16BIT) ? SMC91X_USE_16BIT : 0;
                lp->cfg.flags |= (SMC_CAN_USE_32BIT) ? SMC91X_USE_32BIT : 0;
@@@ -2369,15 -2404,6 +2403,6 @@@ static int smc_drv_resume(struct devic
        return 0;
  }
  
- #ifdef CONFIG_OF
- static const struct of_device_id smc91x_match[] = {
-       { .compatible = "smsc,lan91c94", },
-       { .compatible = "smsc,lan91c111", },
-       {},
- };
- MODULE_DEVICE_TABLE(of, smc91x_match);
- #endif
  static struct dev_pm_ops smc_drv_pm_ops = {
        .suspend        = smc_drv_suspend,
        .resume         = smc_drv_resume,
@@@ -582,7 -582,7 +582,7 @@@ static void cpsw_intr_disable(struct cp
        return;
  }
  
 -void cpsw_tx_handler(void *token, int len, int status)
 +static void cpsw_tx_handler(void *token, int len, int status)
  {
        struct sk_buff          *skb = token;
        struct net_device       *ndev = skb->dev;
        dev_kfree_skb_any(skb);
  }
  
 -void cpsw_rx_handler(void *token, int len, int status)
 +static void cpsw_rx_handler(void *token, int len, int status)
  {
        struct sk_buff          *skb = token;
        struct sk_buff          *new_skb;
@@@ -1151,6 -1151,12 +1151,12 @@@ static int cpsw_ndo_open(struct net_dev
                 * receive descs
                 */
                cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
+               if (cpts_register(&priv->pdev->dev, priv->cpts,
+                                 priv->data.cpts_clock_mult,
+                                 priv->data.cpts_clock_shift))
+                       dev_err(priv->dev, "error registering cpts device\n");
        }
  
        /* Enable Interrupt pacing if configured */
@@@ -1197,6 -1203,7 +1203,7 @@@ static int cpsw_ndo_stop(struct net_dev
        netif_carrier_off(priv->ndev);
  
        if (cpsw_common_res_usage_state(priv) <= 1) {
+               cpts_unregister(priv->cpts);
                cpsw_intr_disable(priv);
                cpdma_ctlr_int_ctrl(priv->dma, false);
                cpdma_ctlr_stop(priv->dma);
@@@ -1322,7 -1329,7 +1329,7 @@@ static void cpsw_hwtstamp_v2(struct cps
        __raw_writel(ETH_P_1588, &priv->regs->ts_ltype);
  }
  
 -static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
 +static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
  {
        struct cpsw_priv *priv = netdev_priv(dev);
        struct cpts *cpts = priv->cpts;
        return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
  }
  
 +static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
 +{
 +      struct cpsw_priv *priv = netdev_priv(dev);
 +      struct cpts *cpts = priv->cpts;
 +      struct hwtstamp_config cfg;
 +
 +      if (priv->version != CPSW_VERSION_1 &&
 +          priv->version != CPSW_VERSION_2)
 +              return -EOPNOTSUPP;
 +
 +      cfg.flags = 0;
 +      cfg.tx_type = cpts->tx_enable ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
 +      cfg.rx_filter = (cpts->rx_enable ?
 +                       HWTSTAMP_FILTER_PTP_V2_EVENT : HWTSTAMP_FILTER_NONE);
 +
 +      return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
 +}
 +
  #endif /*CONFIG_TI_CPTS*/
  
  static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
        switch (cmd) {
  #ifdef CONFIG_TI_CPTS
        case SIOCSHWTSTAMP:
 -              return cpsw_hwtstamp_ioctl(dev, req);
 +              return cpsw_hwtstamp_set(dev, req);
 +      case SIOCGHWTSTAMP:
 +              return cpsw_hwtstamp_get(dev, req);
  #endif
        case SIOCGMIIPHY:
                data->phy_id = priv->slaves[slave_no].phy->addr;
@@@ -2005,9 -1992,15 +2012,15 @@@ static int cpsw_probe(struct platform_d
                goto clean_runtime_disable_ret;
        }
        priv->regs = ss_regs;
-       priv->version = __raw_readl(&priv->regs->id_ver);
        priv->host_port = HOST_PORT_NUM;
  
+       /* Need to enable clocks with runtime PM api to access module
+        * registers
+        */
+       pm_runtime_get_sync(&pdev->dev);
+       priv->version = readl(&priv->regs->id_ver);
+       pm_runtime_put_sync(&pdev->dev);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        priv->wr_regs = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->wr_regs)) {
                          data->cpts_clock_mult, data->cpts_clock_shift))
                dev_err(priv->dev, "error registering cpts device\n");
  
 -      cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
 -                  ss_res->start, ndev->irq);
 +      cpsw_notice(priv, probe, "initialized device (regs %pa, irq %d)\n",
 +                  &ss_res->start, ndev->irq);
  
        if (priv->data.dual_emac) {
                ret = cpsw_probe_dual_emac(pdev, priv);
@@@ -2177,8 -2170,6 +2190,6 @@@ static int cpsw_remove(struct platform_
                unregister_netdev(cpsw_get_slave_ndev(priv, 1));
        unregister_netdev(ndev);
  
-       cpts_unregister(priv->cpts);
        cpsw_ale_destroy(priv->ale);
        cpdma_chan_destroy(priv->txch);
        cpdma_chan_destroy(priv->rxch);
@@@ -11,7 -11,8 +11,7 @@@
   * more details.
   *
   * You should have received a copy of the GNU General Public License along with
 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 - * Place - Suite 330, Boston, MA 02111-1307 USA.
 + * this program; if not, see <http://www.gnu.org/licenses/>.
   *
   * Authors:
   *   Haiyang Zhang <haiyangz@microsoft.com>
@@@ -326,7 -327,6 +326,6 @@@ static int netvsc_change_mtu(struct net
                return -EINVAL;
  
        nvdev->start_remove = true;
-       cancel_delayed_work_sync(&ndevctx->dwork);
        cancel_work_sync(&ndevctx->work);
        netif_tx_disable(ndev);
        rndis_filter_device_remove(hdev);
diff --combined drivers/net/macvtap.c
@@@ -70,11 -70,6 +70,11 @@@ static const struct proto_ops macvtap_s
  #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
  #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
  
 +static struct macvlan_dev *macvtap_get_vlan_rcu(const struct net_device *dev)
 +{
 +      return rcu_dereference(dev->rx_handler_data);
 +}
 +
  /*
   * RCU usage:
   * The macvtap_queue and the macvlan_dev are loosely coupled, the
@@@ -224,7 -219,7 +224,7 @@@ static struct macvtap_queue *macvtap_ge
                goto out;
  
        /* Check if we can use flow to select a queue */
 -      rxq = skb_get_rxhash(skb);
 +      rxq = skb_get_hash(skb);
        if (rxq) {
                tap = rcu_dereference(vlan->taps[rxq % numvtaps]);
                goto out;
@@@ -276,27 -271,24 +276,27 @@@ static void macvtap_del_queues(struct n
                sock_put(&qlist[j]->sk);
  }
  
 -/*
 - * Forward happens for data that gets sent from one macvlan
 - * endpoint to another one in bridge mode. We just take
 - * the skb and put it into the receive queue.
 - */
 -static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
 +static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
  {
 -      struct macvlan_dev *vlan = netdev_priv(dev);
 -      struct macvtap_queue *q = macvtap_get_queue(dev, skb);
 +      struct sk_buff *skb = *pskb;
 +      struct net_device *dev = skb->dev;
 +      struct macvlan_dev *vlan;
 +      struct macvtap_queue *q;
        netdev_features_t features = TAP_FEATURES;
  
 +      vlan = macvtap_get_vlan_rcu(dev);
 +      if (!vlan)
 +              return RX_HANDLER_PASS;
 +
 +      q = macvtap_get_queue(dev, skb);
        if (!q)
 -              goto drop;
 +              return RX_HANDLER_PASS;
  
        if (skb_queue_len(&q->sk.sk_receive_queue) >= dev->tx_queue_len)
                goto drop;
  
 -      skb->dev = dev;
 +      skb_push(skb, ETH_HLEN);
 +
        /* Apply the forward feature mask so that we perform segmentation
         * according to users wishes.  This only works if VNET_HDR is
         * enabled.
  
  wake_up:
        wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND);
 -      return NET_RX_SUCCESS;
 +      return RX_HANDLER_CONSUMED;
  
  drop:
 +      /* Count errors/drops only here, thus don't care about args. */
 +      macvlan_count_rx(vlan, 0, 0, 0);
        kfree_skb(skb);
 -      return NET_RX_DROP;
 -}
 -
 -/*
 - * Receive is for data from the external interface (lowerdev),
 - * in case of macvtap, we can treat that the same way as
 - * forward, which macvlan cannot.
 - */
 -static int macvtap_receive(struct sk_buff *skb)
 -{
 -      skb_push(skb, ETH_HLEN);
 -      return macvtap_forward(skb->dev, skb);
 +      return RX_HANDLER_CONSUMED;
  }
  
  static int macvtap_get_minor(struct macvlan_dev *vlan)
@@@ -384,8 -385,6 +384,8 @@@ static int macvtap_newlink(struct net *
                           struct nlattr *data[])
  {
        struct macvlan_dev *vlan = netdev_priv(dev);
 +      int err;
 +
        INIT_LIST_HEAD(&vlan->queue_list);
  
        /* Since macvlan supports all offloads by default, make
         */
        vlan->tap_features = TUN_OFFLOADS;
  
 +      err = netdev_rx_handler_register(dev, macvtap_handle_frame, vlan);
 +      if (err)
 +              return err;
 +
        /* Don't put anything that may fail after macvlan_common_newlink
         * because we can't undo what it does.
         */
 -      return macvlan_common_newlink(src_net, dev, tb, data,
 -                                    macvtap_receive, macvtap_forward);
 +      return macvlan_common_newlink(src_net, dev, tb, data);
  }
  
  static void macvtap_dellink(struct net_device *dev,
                            struct list_head *head)
  {
 +      netdev_rx_handler_unregister(dev);
        macvtap_del_queues(dev);
        macvlan_dellink(dev, head);
  }
@@@ -593,7 -588,7 +593,7 @@@ static int macvtap_skb_from_vnet_hdr(st
        return 0;
  }
  
 -static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
 +static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
                                   struct virtio_net_hdr *vnet_hdr)
  {
        memset(vnet_hdr, 0, sizeof(*vnet_hdr));
        } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
                vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
        } /* else everything is zero */
 -
 -      return 0;
  }
  
  /* Get packet from user space buffer */
@@@ -730,8 -727,9 +730,8 @@@ static ssize_t macvtap_get_user(struct 
                skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
        }
        if (vlan) {
 -              local_bh_disable();
 -              macvlan_start_xmit(skb, vlan->dev);
 -              local_bh_enable();
 +              skb->dev = vlan->dev;
 +              dev_queue_xmit(skb);
        } else {
                kfree_skb(skb);
        }
@@@ -772,7 -770,7 +772,7 @@@ static ssize_t macvtap_put_user(struct 
        int ret;
        int vnet_hdr_len = 0;
        int vlan_offset = 0;
-       int copied;
+       int copied, total;
  
        if (q->flags & IFF_VNET_HDR) {
                struct virtio_net_hdr vnet_hdr;
                if ((len -= vnet_hdr_len) < 0)
                        return -EINVAL;
  
 -              ret = macvtap_skb_to_vnet_hdr(skb, &vnet_hdr);
 -              if (ret)
 -                      return ret;
 +              macvtap_skb_to_vnet_hdr(skb, &vnet_hdr);
  
                if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr)))
                        return -EFAULT;
        }
-       copied = vnet_hdr_len;
+       total = copied = vnet_hdr_len;
+       total += skb->len;
  
        if (!vlan_tx_tag_present(skb))
                len = min_t(int, skb->len, len);
  
                vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
                len = min_t(int, skb->len + VLAN_HLEN, len);
+               total += VLAN_HLEN;
  
                copy = min_t(int, vlan_offset, len);
                ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
        }
  
        ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
-       copied += len;
  
  done:
-       return ret ? ret : copied;
+       return ret ? ret : total;
  }
  
 -static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb,
 +static ssize_t macvtap_do_read(struct macvtap_queue *q,
                               const struct iovec *iv, unsigned long len,
                               int noblock)
  {
@@@ -874,8 -875,8 +875,8 @@@ static ssize_t macvtap_aio_read(struct 
                goto out;
        }
  
 -      ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK);
 +      ret = macvtap_do_read(q, iv, len, file->f_flags & O_NONBLOCK);
-       ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */
+       ret = min_t(ssize_t, ret, len);
        if (ret > 0)
                iocb->ki_pos = ret;
  out:
@@@ -1108,7 -1109,7 +1109,7 @@@ static int macvtap_recvmsg(struct kioc
        int ret;
        if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
                return -EINVAL;
 -      ret = macvtap_do_read(q, iocb, m->msg_iov, total_len,
 +      ret = macvtap_do_read(q, m->msg_iov, total_len,
                          flags & MSG_DONTWAIT);
        if (ret > total_len) {
                m->msg_flags |= MSG_TRUNC;
diff --combined drivers/net/phy/micrel.c
@@@ -81,14 -81,14 +81,14 @@@ static int ksz_config_flags(struct phy_
  }
  
  static int kszphy_extended_write(struct phy_device *phydev,
 -                                 u32 regnum, u16 val)
 +                              u32 regnum, u16 val)
  {
        phy_write(phydev, MII_KSZPHY_EXTREG, KSZPHY_EXTREG_WRITE | regnum);
        return phy_write(phydev, MII_KSZPHY_EXTREG_WRITE, val);
  }
  
  static int kszphy_extended_read(struct phy_device *phydev,
 -                                 u32 regnum)
 +                              u32 regnum)
  {
        phy_write(phydev, MII_KSZPHY_EXTREG, regnum);
        return phy_read(phydev, MII_KSZPHY_EXTREG_READ);
@@@ -336,6 -336,21 +336,21 @@@ static struct phy_driver ksphy_driver[
        .resume         = genphy_resume,
        .driver         = { .owner = THIS_MODULE,},
  }, {
+       .phy_id         = PHY_ID_KSZ8041RNLI,
+       .phy_id_mask    = 0x00fffff0,
+       .name           = "Micrel KSZ8041RNLI",
+       .features       = PHY_BASIC_FEATURES |
+                         SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+       .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .config_init    = kszphy_config_init,
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = kszphy_ack_interrupt,
+       .config_intr    = kszphy_config_intr,
+       .suspend        = genphy_suspend,
+       .resume         = genphy_resume,
+       .driver         = { .owner = THIS_MODULE,},
+ }, {
        .phy_id         = PHY_ID_KSZ8051,
        .phy_id_mask    = 0x00fffff0,
        .name           = "Micrel KSZ8051",
diff --combined drivers/net/tun.c
@@@ -110,7 -110,7 +110,7 @@@ struct tap_filter 
        unsigned char   addr[FLT_EXACT_COUNT][ETH_ALEN];
  };
  
 -/* DEFAULT_MAX_NUM_RSS_QUEUES were choosed to let the rx/tx queues allocated for
 +/* DEFAULT_MAX_NUM_RSS_QUEUES were chosen to let the rx/tx queues allocated for
   * the netdevice to be fit in one page. So we can make sure the success of
   * memory allocation. TODO: increase the limit. */
  #define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES
  #define TUN_FLOW_EXPIRE (3 * HZ)
  
  /* A tun_file connects an open character device to a tuntap netdevice. It
 - * also contains all socket related strctures (except sock_fprog and tap_filter)
 + * also contains all socket related structures (except sock_fprog and tap_filter)
   * to serve as one transmit queue for tuntap device. The sock_fprog and
   * tap_filter were kept in tun_struct since they were used for filtering for the
   * netdevice not for a specific queue (at least I didn't see the requirement for
@@@ -342,7 -342,7 +342,7 @@@ unlock
  }
  
  /* We try to identify a flow through its rxhash first. The reason that
 - * we do not check rxq no. is becuase some cards(e.g 82599), chooses
 + * we do not check rxq no. is because some cards(e.g 82599), chooses
   * the rxq based on the txq where the last packet of the flow comes. As
   * the userspace application move between processors, we may get a
   * different rxq no. here. If we could not get rxhash, then we would
@@@ -358,7 -358,7 +358,7 @@@ static u16 tun_select_queue(struct net_
        rcu_read_lock();
        numqueues = ACCESS_ONCE(tun->numqueues);
  
 -      txq = skb_get_rxhash(skb);
 +      txq = skb_get_hash(skb);
        if (txq) {
                e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq);
                if (e)
@@@ -531,7 -531,7 +531,7 @@@ static int tun_attach(struct tun_struc
  
        err = 0;
  
 -      /* Re-attach the filter to presist device */
 +      /* Re-attach the filter to persist device */
        if (!skip_filter && (tun->filter_attached == true)) {
                err = sk_attach_filter(&tun->fprog, tfile->socket.sk);
                if (!err)
@@@ -819,9 -819,9 +819,9 @@@ static void tun_poll_controller(struct 
         * Tun only receives frames when:
         * 1) the char device endpoint gets data from user space
         * 2) the tun socket gets a sendmsg call from user space
 -       * Since both of those are syncronous operations, we are guaranteed
 +       * Since both of those are synchronous operations, we are guaranteed
         * never to have pending data when we poll for it
 -       * so theres nothing to do here but return.
 +       * so there is nothing to do here but return.
         * We need this though so netpoll recognizes us as an interface that
         * supports polling, which enables bridge devices in virt setups to
         * still use netconsole
@@@ -1146,7 -1146,7 +1146,7 @@@ static ssize_t tun_get_user(struct tun_
        skb_reset_network_header(skb);
        skb_probe_transport_header(skb, 0);
  
 -      rxhash = skb_get_rxhash(skb);
 +      rxhash = skb_get_hash(skb);
        netif_rx_ni(skb);
  
        tun->dev->stats.rx_packets++;
@@@ -1184,7 -1184,7 +1184,7 @@@ static ssize_t tun_put_user(struct tun_
  {
        struct tun_pi pi = { 0, skb->protocol };
        ssize_t total = 0;
-       int vlan_offset = 0;
+       int vlan_offset = 0, copied;
  
        if (!(tun->flags & TUN_NO_PI)) {
                if ((len -= sizeof(pi)) < 0)
                total += tun->vnet_hdr_sz;
        }
  
+       copied = total;
+       total += skb->len;
        if (!vlan_tx_tag_present(skb)) {
                len = min_t(int, skb->len, len);
        } else {
  
                vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
                len = min_t(int, skb->len + VLAN_HLEN, len);
+               total += VLAN_HLEN;
  
                copy = min_t(int, vlan_offset, len);
-               ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy);
+               ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
                len -= copy;
-               total += copy;
+               copied += copy;
                if (ret || !len)
                        goto done;
  
                copy = min_t(int, sizeof(veth), len);
-               ret = memcpy_toiovecend(iv, (void *)&veth, total, copy);
+               ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy);
                len -= copy;
-               total += copy;
+               copied += copy;
                if (ret || !len)
                        goto done;
        }
  
-       skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len);
-       total += len;
+       skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
  
  done:
        tun->dev->stats.tx_packets++;
  }
  
  static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
 -                         struct kiocb *iocb, const struct iovec *iv,
 -                         ssize_t len, int noblock)
 +                         const struct iovec *iv, ssize_t len, int noblock)
  {
        DECLARE_WAITQUEUE(wait, current);
        struct sk_buff *skb;
@@@ -1352,7 -1355,7 +1354,7 @@@ static ssize_t tun_chr_aio_read(struct 
                goto out;
        }
  
 -      ret = tun_do_read(tun, tfile, iocb, iv, len,
 +      ret = tun_do_read(tun, tfile, iv, len,
                          file->f_flags & O_NONBLOCK);
        ret = min_t(ssize_t, ret, len);
        if (ret > 0)
@@@ -1453,7 -1456,7 +1455,7 @@@ static int tun_recvmsg(struct kiocb *io
                                         SOL_PACKET, TUN_TX_TIMESTAMP);
                goto out;
        }
 -      ret = tun_do_read(tun, tfile, iocb, m->msg_iov, total_len,
 +      ret = tun_do_read(tun, tfile, m->msg_iov, total_len,
                          flags & MSG_DONTWAIT);
        if (ret > total_len) {
                m->msg_flags |= MSG_TRUNC;
diff --combined drivers/net/vxlan.c
@@@ -916,32 -916,17 +916,32 @@@ static bool vxlan_snoop(struct net_devi
  }
  
  /* See if multicast group is already in use by other ID */
 -static bool vxlan_group_used(struct vxlan_net *vn, union vxlan_addr *remote_ip)
 +static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
  {
        struct vxlan_dev *vxlan;
  
 +      /* The vxlan_sock is only used by dev, leaving group has
 +       * no effect on other vxlan devices.
 +       */
 +      if (atomic_read(&dev->vn_sock->refcnt) == 1)
 +              return false;
 +
        list_for_each_entry(vxlan, &vn->vxlan_list, next) {
 -              if (!netif_running(vxlan->dev))
 +              if (!netif_running(vxlan->dev) || vxlan == dev)
                        continue;
  
 -              if (vxlan_addr_equal(&vxlan->default_dst.remote_ip,
 -                                   remote_ip))
 -                      return true;
 +              if (vxlan->vn_sock != dev->vn_sock)
 +                      continue;
 +
 +              if (!vxlan_addr_equal(&vxlan->default_dst.remote_ip,
 +                                    &dev->default_dst.remote_ip))
 +                      continue;
 +
 +              if (vxlan->default_dst.remote_ifindex !=
 +                  dev->default_dst.remote_ifindex)
 +                      continue;
 +
 +              return true;
        }
  
        return false;
@@@ -1405,7 -1390,7 +1405,7 @@@ __be16 vxlan_src_port(__u16 port_min, _
        unsigned int range = (port_max - port_min) + 1;
        u32 hash;
  
 -      hash = skb_get_rxhash(skb);
 +      hash = skb_get_hash(skb);
        if (!hash)
                hash = jhash(skb->data, 2 * ETH_ALEN,
                             (__force u32) skb->protocol);
@@@ -1683,7 -1668,7 +1683,7 @@@ static void vxlan_xmit_one(struct sk_bu
                        netdev_dbg(dev, "circular route to %pI4\n",
                                   &dst->sin.sin_addr.s_addr);
                        dev->stats.collisions++;
-                       goto tx_error;
+                       goto rt_tx_error;
                }
  
                /* Bypass encapsulation if the destination is local */
@@@ -1950,6 -1935,7 +1950,6 @@@ static void vxlan_uninit(struct net_dev
  /* Start ageing timer and join group when device is brought up */
  static int vxlan_open(struct net_device *dev)
  {
 -      struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct vxlan_sock *vs = vxlan->vn_sock;
  
        if (!vs)
                return -ENOTCONN;
  
 -      if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
 -          vxlan_group_used(vn, &vxlan->default_dst.remote_ip)) {
 +      if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
                vxlan_sock_hold(vs);
                dev_hold(dev);
                queue_work(vxlan_wq, &vxlan->igmp_join);
@@@ -1996,7 -1983,7 +1996,7 @@@ static int vxlan_stop(struct net_devic
        struct vxlan_sock *vs = vxlan->vn_sock;
  
        if (vs && vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
 -          ! vxlan_group_used(vn, &vxlan->default_dst.remote_ip)) {
 +          !vxlan_group_used(vn, vxlan)) {
                vxlan_sock_hold(vs);
                dev_hold(dev);
                queue_work(vxlan_wq, &vxlan->igmp_leave);
@@@ -1276,6 -1276,10 +1276,10 @@@ static void ath_tx_fill_desc(struct ath
                                if (!rts_thresh || (len > rts_thresh))
                                        rts = true;
                        }
+                       if (!aggr)
+                               len = fi->framelen;
                        ath_buf_set_rate(sc, bf, &info, len, rts);
                }
  
@@@ -1786,9 -1790,6 +1790,9 @@@ bool ath_drain_all_txq(struct ath_soft
                if (!ATH_TXQ_SETUP(sc, i))
                        continue;
  
 +              if (!sc->tx.txq[i].axq_depth)
 +                      continue;
 +
                if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
                        npend |= BIT(i);
        }
@@@ -2752,8 -2753,6 +2756,8 @@@ void ath_tx_node_cleanup(struct ath_sof
        }
  }
  
 +#ifdef CONFIG_ATH9K_TX99
 +
  int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
                    struct ath_tx_control *txctl)
  {
  
        return 0;
  }
 +
 +#endif /* CONFIG_ATH9K_TX99 */
@@@ -138,26 -138,36 +138,26 @@@ static inline pending_ring_idx_t nr_pen
                vif->pending_prod + vif->pending_cons;
  }
  
 -static int max_required_rx_slots(struct xenvif *vif)
 +bool xenvif_rx_ring_slots_available(struct xenvif *vif, int needed)
  {
 -      int max = DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE);
 +      RING_IDX prod, cons;
  
 -      /* XXX FIXME: RX path dependent on MAX_SKB_FRAGS */
 -      if (vif->can_sg || vif->gso_mask || vif->gso_prefix_mask)
 -              max += MAX_SKB_FRAGS + 1; /* extra_info + frags */
 -
 -      return max;
 -}
 -
 -int xenvif_rx_ring_full(struct xenvif *vif)
 -{
 -      RING_IDX peek   = vif->rx_req_cons_peek;
 -      RING_IDX needed = max_required_rx_slots(vif);
 +      do {
 +              prod = vif->rx.sring->req_prod;
 +              cons = vif->rx.req_cons;
  
 -      return ((vif->rx.sring->req_prod - peek) < needed) ||
 -             ((vif->rx.rsp_prod_pvt + XEN_NETIF_RX_RING_SIZE - peek) < needed);
 -}
 +              if (prod - cons >= needed)
 +                      return true;
  
 -int xenvif_must_stop_queue(struct xenvif *vif)
 -{
 -      if (!xenvif_rx_ring_full(vif))
 -              return 0;
 +              vif->rx.sring->req_event = prod + 1;
  
 -      vif->rx.sring->req_event = vif->rx_req_cons_peek +
 -              max_required_rx_slots(vif);
 -      mb(); /* request notification /then/ check the queue */
 +              /* Make sure event is visible before we check prod
 +               * again.
 +               */
 +              mb();
 +      } while (vif->rx.sring->req_prod != prod);
  
 -      return xenvif_rx_ring_full(vif);
 +      return false;
  }
  
  /*
@@@ -200,6 -210,93 +200,6 @@@ static bool start_new_rx_buffer(int off
        return false;
  }
  
 -struct xenvif_count_slot_state {
 -      unsigned long copy_off;
 -      bool head;
 -};
 -
 -unsigned int xenvif_count_frag_slots(struct xenvif *vif,
 -                                   unsigned long offset, unsigned long size,
 -                                   struct xenvif_count_slot_state *state)
 -{
 -      unsigned count = 0;
 -
 -      offset &= ~PAGE_MASK;
 -
 -      while (size > 0) {
 -              unsigned long bytes;
 -
 -              bytes = PAGE_SIZE - offset;
 -
 -              if (bytes > size)
 -                      bytes = size;
 -
 -              if (start_new_rx_buffer(state->copy_off, bytes, state->head)) {
 -                      count++;
 -                      state->copy_off = 0;
 -              }
 -
 -              if (state->copy_off + bytes > MAX_BUFFER_OFFSET)
 -                      bytes = MAX_BUFFER_OFFSET - state->copy_off;
 -
 -              state->copy_off += bytes;
 -
 -              offset += bytes;
 -              size -= bytes;
 -
 -              if (offset == PAGE_SIZE)
 -                      offset = 0;
 -
 -              state->head = false;
 -      }
 -
 -      return count;
 -}
 -
 -/*
 - * Figure out how many ring slots we're going to need to send @skb to
 - * the guest. This function is essentially a dry run of
 - * xenvif_gop_frag_copy.
 - */
 -unsigned int xenvif_count_skb_slots(struct xenvif *vif, struct sk_buff *skb)
 -{
 -      struct xenvif_count_slot_state state;
 -      unsigned int count;
 -      unsigned char *data;
 -      unsigned i;
 -
 -      state.head = true;
 -      state.copy_off = 0;
 -
 -      /* Slot for the first (partial) page of data. */
 -      count = 1;
 -
 -      /* Need a slot for the GSO prefix for GSO extra data? */
 -      if (skb_shinfo(skb)->gso_size)
 -              count++;
 -
 -      data = skb->data;
 -      while (data < skb_tail_pointer(skb)) {
 -              unsigned long offset = offset_in_page(data);
 -              unsigned long size = PAGE_SIZE - offset;
 -
 -              if (data + size > skb_tail_pointer(skb))
 -                      size = skb_tail_pointer(skb) - data;
 -
 -              count += xenvif_count_frag_slots(vif, offset, size, &state);
 -
 -              data += size;
 -      }
 -
 -      for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 -              unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
 -              unsigned long offset = skb_shinfo(skb)->frags[i].page_offset;
 -
 -              count += xenvif_count_frag_slots(vif, offset, size, &state);
 -      }
 -      return count;
 -}
 -
  struct netrx_pending_operations {
        unsigned copy_prod, copy_cons;
        unsigned meta_prod, meta_cons;
@@@ -355,7 -452,7 +355,7 @@@ static int xenvif_gop_skb(struct sk_buf
        }
  
        /* Set up a GSO prefix descriptor, if necessary */
-       if ((1 << skb_shinfo(skb)->gso_type) & vif->gso_prefix_mask) {
+       if ((1 << gso_type) & vif->gso_prefix_mask) {
                req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
                meta = npo->meta + npo->meta_prod++;
                meta->gso_type = gso_type;
@@@ -460,12 -557,12 +460,12 @@@ struct skb_cb_overlay 
        int meta_slots_used;
  };
  
 -static void xenvif_kick_thread(struct xenvif *vif)
 +void xenvif_kick_thread(struct xenvif *vif)
  {
        wake_up(&vif->wq);
  }
  
 -void xenvif_rx_action(struct xenvif *vif)
 +static void xenvif_rx_action(struct xenvif *vif)
  {
        s8 status;
        u16 flags;
        struct sk_buff *skb;
        LIST_HEAD(notify);
        int ret;
 -      int nr_frags;
 -      int count;
        unsigned long offset;
        struct skb_cb_overlay *sco;
        int need_to_notify = 0;
  
        skb_queue_head_init(&rxq);
  
 -      count = 0;
 -
        while ((skb = skb_dequeue(&vif->rx_queue)) != NULL) {
 -              vif = netdev_priv(skb->dev);
 -              nr_frags = skb_shinfo(skb)->nr_frags;
 +              int max_slots_needed;
 +              int i;
 +
 +              /* We need a cheap worse case estimate for the number of
 +               * slots we'll use.
 +               */
 +
 +              max_slots_needed = DIV_ROUND_UP(offset_in_page(skb->data) +
 +                                              skb_headlen(skb),
 +                                              PAGE_SIZE);
 +              for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 +                      unsigned int size;
 +                      size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
 +                      max_slots_needed += DIV_ROUND_UP(size, PAGE_SIZE);
 +              }
 +              if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 ||
 +                  skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
 +                      max_slots_needed++;
 +
 +              /* If the skb may not fit then bail out now */
 +              if (!xenvif_rx_ring_slots_available(vif, max_slots_needed)) {
 +                      skb_queue_head(&vif->rx_queue, skb);
 +                      need_to_notify = 1;
 +                      break;
 +              }
  
                sco = (struct skb_cb_overlay *)skb->cb;
                sco->meta_slots_used = xenvif_gop_skb(skb, &npo);
 -
 -              count += nr_frags + 1;
 +              BUG_ON(sco->meta_slots_used > max_slots_needed);
  
                __skb_queue_tail(&rxq, skb);
 -
 -              /* Filled the batch queue? */
 -              /* XXX FIXME: RX path dependent on MAX_SKB_FRAGS */
 -              if (count + MAX_SKB_FRAGS >= XEN_NETIF_RX_RING_SIZE)
 -                      break;
        }
  
        BUG_ON(npo.meta_prod > ARRAY_SIZE(vif->meta));
  
        if (!npo.copy_prod)
 -              return;
 +              goto done;
  
        BUG_ON(npo.copy_prod > ARRAY_SIZE(vif->grant_copy_op));
        gnttab_batch_copy(vif->grant_copy_op, npo.copy_prod);
        while ((skb = __skb_dequeue(&rxq)) != NULL) {
                sco = (struct skb_cb_overlay *)skb->cb;
  
 -              vif = netdev_priv(skb->dev);
 -
                if ((1 << vif->meta[npo.meta_cons].gso_type) &
                    vif->gso_prefix_mask) {
                        resp = RING_GET_RESPONSE(&vif->rx,
                if (ret)
                        need_to_notify = 1;
  
 -              xenvif_notify_tx_completion(vif);
 -
                npo.meta_cons += sco->meta_slots_used;
                dev_kfree_skb(skb);
        }
  
 +done:
        if (need_to_notify)
                notify_remote_via_irq(vif->rx_irq);
 -
 -      /* More work to do? */
 -      if (!skb_queue_empty(&vif->rx_queue))
 -              xenvif_kick_thread(vif);
 -}
 -
 -void xenvif_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb)
 -{
 -      skb_queue_tail(&vif->rx_queue, skb);
 -
 -      xenvif_kick_thread(vif);
  }
  
  void xenvif_check_rx_xenvif(struct xenvif *vif)
@@@ -1099,44 -1197,45 +1099,45 @@@ static int checksum_setup_ip(struct xen
  
        err = -EPROTO;
  
+       if (fragment)
+               goto out;
        switch (ip_hdr(skb)->protocol) {
        case IPPROTO_TCP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct tcphdr),
+                                     MAX_IP_HDR_LEN);
+               if (err < 0)
+                       goto out;
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct tcphdr, check)))
                        goto out;
  
-               if (recalculate_partial_csum) {
-                       err = maybe_pull_tail(skb,
-                                             off + sizeof(struct tcphdr),
-                                             MAX_IP_HDR_LEN);
-                       if (err < 0)
-                               goto out;
+               if (recalculate_partial_csum)
                        tcp_hdr(skb)->check =
                                ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
                                                   ip_hdr(skb)->daddr,
                                                   skb->len - off,
                                                   IPPROTO_TCP, 0);
-               }
                break;
        case IPPROTO_UDP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct udphdr),
+                                     MAX_IP_HDR_LEN);
+               if (err < 0)
+                       goto out;
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct udphdr, check)))
                        goto out;
  
-               if (recalculate_partial_csum) {
-                       err = maybe_pull_tail(skb,
-                                             off + sizeof(struct udphdr),
-                                             MAX_IP_HDR_LEN);
-                       if (err < 0)
-                               goto out;
+               if (recalculate_partial_csum)
                        udp_hdr(skb)->check =
                                ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
                                                   ip_hdr(skb)->daddr,
                                                   skb->len - off,
                                                   IPPROTO_UDP, 0);
-               }
                break;
        default:
                goto out;
@@@ -1244,42 -1343,40 +1245,40 @@@ static int checksum_setup_ipv6(struct x
  
        switch (nexthdr) {
        case IPPROTO_TCP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct tcphdr),
+                                     MAX_IPV6_HDR_LEN);
+               if (err < 0)
+                       goto out;
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct tcphdr, check)))
                        goto out;
  
-               if (recalculate_partial_csum) {
-                       err = maybe_pull_tail(skb,
-                                             off + sizeof(struct tcphdr),
-                                             MAX_IPV6_HDR_LEN);
-                       if (err < 0)
-                               goto out;
+               if (recalculate_partial_csum)
                        tcp_hdr(skb)->check =
                                ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
                                                 &ipv6_hdr(skb)->daddr,
                                                 skb->len - off,
                                                 IPPROTO_TCP, 0);
-               }
                break;
        case IPPROTO_UDP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct udphdr),
+                                     MAX_IPV6_HDR_LEN);
+               if (err < 0)
+                       goto out;
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct udphdr, check)))
                        goto out;
  
-               if (recalculate_partial_csum) {
-                       err = maybe_pull_tail(skb,
-                                             off + sizeof(struct udphdr),
-                                             MAX_IPV6_HDR_LEN);
-                       if (err < 0)
-                               goto out;
+               if (recalculate_partial_csum)
                        udp_hdr(skb)->check =
                                ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
                                                 &ipv6_hdr(skb)->daddr,
                                                 skb->len - off,
                                                 IPPROTO_UDP, 0);
-               }
                break;
        default:
                goto out;
@@@ -1351,14 -1448,15 +1350,15 @@@ static bool tx_credit_exceeded(struct x
        return false;
  }
  
- static unsigned xenvif_tx_build_gops(struct xenvif *vif)
+ static unsigned xenvif_tx_build_gops(struct xenvif *vif, int budget)
  {
        struct gnttab_copy *gop = vif->tx_copy_ops, *request_gop;
        struct sk_buff *skb;
        int ret;
  
        while ((nr_pending_reqs(vif) + XEN_NETBK_LEGACY_SLOTS_MAX
-               < MAX_PENDING_REQS)) {
+               < MAX_PENDING_REQS) &&
+              (skb_queue_len(&vif->tx_queue) < budget)) {
                struct xen_netif_tx_request txreq;
                struct xen_netif_tx_request txfrags[XEN_NETBK_LEGACY_SLOTS_MAX];
                struct page *page;
                        continue;
                }
  
-               RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do);
+               work_to_do = RING_HAS_UNCONSUMED_REQUESTS(&vif->tx);
                if (!work_to_do)
                        break;
  
  }
  
  
- static int xenvif_tx_submit(struct xenvif *vif, int budget)
+ static int xenvif_tx_submit(struct xenvif *vif)
  {
        struct gnttab_copy *gop = vif->tx_copy_ops;
        struct sk_buff *skb;
        int work_done = 0;
  
-       while (work_done < budget &&
-              (skb = __skb_dequeue(&vif->tx_queue)) != NULL) {
+       while ((skb = __skb_dequeue(&vif->tx_queue)) != NULL) {
                struct xen_netif_tx_request *txp;
                u16 pending_idx;
                unsigned data_len;
@@@ -1602,14 -1699,14 +1601,14 @@@ int xenvif_tx_action(struct xenvif *vif
        if (unlikely(!tx_work_todo(vif)))
                return 0;
  
-       nr_gops = xenvif_tx_build_gops(vif);
+       nr_gops = xenvif_tx_build_gops(vif, budget);
  
        if (nr_gops == 0)
                return 0;
  
        gnttab_batch_copy(vif->tx_copy_ops, nr_gops);
  
-       work_done = xenvif_tx_submit(vif, nr_gops);
+       work_done = xenvif_tx_submit(vif);
  
        return work_done;
  }
@@@ -1706,7 -1803,7 +1705,7 @@@ static struct xen_netif_rx_response *ma
  
  static inline int rx_work_todo(struct xenvif *vif)
  {
 -      return !skb_queue_empty(&vif->rx_queue);
 +      return !skb_queue_empty(&vif->rx_queue) || vif->rx_event;
  }
  
  static inline int tx_work_todo(struct xenvif *vif)
@@@ -1756,6 -1853,8 +1755,6 @@@ int xenvif_map_frontend_rings(struct xe
        rxs = (struct xen_netif_rx_sring *)addr;
        BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE);
  
 -      vif->rx_req_cons_peek = 0;
 -
        return 0;
  
  err:
        return err;
  }
  
 +void xenvif_stop_queue(struct xenvif *vif)
 +{
 +      if (!vif->can_queue)
 +              return;
 +
 +      netif_stop_queue(vif->dev);
 +}
 +
 +static void xenvif_start_queue(struct xenvif *vif)
 +{
 +      if (xenvif_schedulable(vif))
 +              netif_wake_queue(vif->dev);
 +}
 +
  int xenvif_kthread(void *data)
  {
        struct xenvif *vif = data;
 +      struct sk_buff *skb;
  
        while (!kthread_should_stop()) {
                wait_event_interruptible(vif->wq,
                if (kthread_should_stop())
                        break;
  
 -              if (rx_work_todo(vif))
 +              if (!skb_queue_empty(&vif->rx_queue))
                        xenvif_rx_action(vif);
  
 +              vif->rx_event = false;
 +
 +              if (skb_queue_empty(&vif->rx_queue) &&
 +                  netif_queue_stopped(vif->dev))
 +                      xenvif_start_queue(vif);
 +
                cond_resched();
        }
  
 +      /* Bin any remaining skbs */
 +      while ((skb = skb_dequeue(&vif->rx_queue)) != NULL)
 +              dev_kfree_skb(skb);
 +
        return 0;
  }
  
@@@ -1255,7 -1255,7 +1255,7 @@@ struct net_device 
        unsigned char           perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
        unsigned char           addr_assign_type; /* hw address assignment type */
        unsigned char           addr_len;       /* hardware address length      */
-       unsigned char           neigh_priv_len;
+       unsigned short          neigh_priv_len;
        unsigned short          dev_id;         /* Used to differentiate devices
                                                 * that share the same link
                                                 * layer address
  #if IS_ENABLED(CONFIG_NET_DSA)
        struct dsa_switch_tree  *dsa_ptr;       /* dsa specific data */
  #endif
 +#if IS_ENABLED(CONFIG_TIPC)
 +      struct tipc_bearer __rcu *tipc_ptr;     /* TIPC specific data */
 +#endif
        void                    *atalk_ptr;     /* AppleTalk link       */
        struct in_device __rcu  *ip_ptr;        /* IPv4 specific data   */
        struct dn_dev __rcu     *dn_ptr;        /* DECnet specific data */
@@@ -1676,7 -1673,7 +1676,7 @@@ struct offload_callbacks 
        int                     (*gso_send_check)(struct sk_buff *skb);
        struct sk_buff          **(*gro_receive)(struct sk_buff **head,
                                               struct sk_buff *skb);
 -      int                     (*gro_complete)(struct sk_buff *skb);
 +      int                     (*gro_complete)(struct sk_buff *skb, int nhoff);
  };
  
  struct packet_offload {
@@@ -2371,52 -2368,17 +2371,52 @@@ static inline int netif_copy_real_num_q
  #define DEFAULT_MAX_NUM_RSS_QUEUES    (8)
  int netif_get_num_default_rss_queues(void);
  
 -/* Use this variant when it is known for sure that it
 - * is executing from hardware interrupt context or with hardware interrupts
 - * disabled.
 - */
 -void dev_kfree_skb_irq(struct sk_buff *skb);
 +enum skb_free_reason {
 +      SKB_REASON_CONSUMED,
 +      SKB_REASON_DROPPED,
 +};
  
 -/* Use this variant in places where it could be invoked
 - * from either hardware interrupt or other context, with hardware interrupts
 - * either disabled or enabled.
 +void __dev_kfree_skb_irq(struct sk_buff *skb, enum skb_free_reason reason);
 +void __dev_kfree_skb_any(struct sk_buff *skb, enum skb_free_reason reason);
 +
 +/*
 + * It is not allowed to call kfree_skb() or consume_skb() from hardware
 + * interrupt context or with hardware interrupts being disabled.
 + * (in_irq() || irqs_disabled())
 + *
 + * We provide four helpers that can be used in following contexts :
 + *
 + * dev_kfree_skb_irq(skb) when caller drops a packet from irq context,
 + *  replacing kfree_skb(skb)
 + *
 + * dev_consume_skb_irq(skb) when caller consumes a packet from irq context.
 + *  Typically used in place of consume_skb(skb) in TX completion path
 + *
 + * dev_kfree_skb_any(skb) when caller doesn't know its current irq context,
 + *  replacing kfree_skb(skb)
 + *
 + * dev_consume_skb_any(skb) when caller doesn't know its current irq context,
 + *  and consumed a packet. Used in place of consume_skb(skb)
   */
 -void dev_kfree_skb_any(struct sk_buff *skb);
 +static inline void dev_kfree_skb_irq(struct sk_buff *skb)
 +{
 +      __dev_kfree_skb_irq(skb, SKB_REASON_DROPPED);
 +}
 +
 +static inline void dev_consume_skb_irq(struct sk_buff *skb)
 +{
 +      __dev_kfree_skb_irq(skb, SKB_REASON_CONSUMED);
 +}
 +
 +static inline void dev_kfree_skb_any(struct sk_buff *skb)
 +{
 +      __dev_kfree_skb_any(skb, SKB_REASON_DROPPED);
 +}
 +
 +static inline void dev_consume_skb_any(struct sk_buff *skb)
 +{
 +      __dev_kfree_skb_any(skb, SKB_REASON_CONSUMED);
 +}
  
  int netif_rx(struct sk_buff *skb);
  int netif_rx_ni(struct sk_buff *skb);
@@@ -2810,10 -2772,17 +2810,10 @@@ int register_netdev(struct net_device *
  void unregister_netdev(struct net_device *dev);
  
  /* General hardware address lists handling functions */
 -int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list,
 -                         struct netdev_hw_addr_list *from_list,
 -                         int addr_len, unsigned char addr_type);
 -void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list,
 -                          struct netdev_hw_addr_list *from_list,
 -                          int addr_len, unsigned char addr_type);
  int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
                   struct netdev_hw_addr_list *from_list, int addr_len);
  void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
                      struct netdev_hw_addr_list *from_list, int addr_len);
 -void __hw_addr_flush(struct netdev_hw_addr_list *list);
  void __hw_addr_init(struct netdev_hw_addr_list *list);
  
  /* Functions used for device addresses handling */
@@@ -2821,6 -2790,10 +2821,6 @@@ int dev_addr_add(struct net_device *dev
                 unsigned char addr_type);
  int dev_addr_del(struct net_device *dev, const unsigned char *addr,
                 unsigned char addr_type);
 -int dev_addr_add_multiple(struct net_device *to_dev,
 -                        struct net_device *from_dev, unsigned char addr_type);
 -int dev_addr_del_multiple(struct net_device *to_dev,
 -                        struct net_device *from_dev, unsigned char addr_type);
  void dev_addr_flush(struct net_device *dev);
  int dev_addr_init(struct net_device *dev);
  
@@@ -2896,7 -2869,6 +2896,7 @@@ void *netdev_lower_get_next_private_rcu
             priv = netdev_lower_get_next_private_rcu(dev, &(iter)))
  
  void *netdev_adjacent_get_private(struct list_head *adj_list);
 +void *netdev_lower_get_first_private_rcu(struct net_device *dev);
  struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
  struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
  int netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev);
@@@ -19,8 -19,9 +19,8 @@@
   * See the GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
 - * along with GNU CC; see the file COPYING.  If not, write to
 - * the Free Software Foundation, 59 Temple Place - Suite 330,
 - * Boston, MA 02111-1307, USA.
 + * along with GNU CC; see the file COPYING.  If not, see
 + * <http://www.gnu.org/licenses/>.
   *
   * Please send any bug reports or fixes you make to the
   * email addresses:
@@@ -1360,6 -1361,12 +1360,6 @@@ struct sctp_association 
  
        /* This is all information about our peer.  */
        struct {
 -              /* rwnd
 -               *
 -               * Peer Rwnd   : Current calculated value of the peer's rwnd.
 -               */
 -              __u32 rwnd;
 -
                /* transport_addr_list
                 *
                 * Peer        : A list of SCTP transport addresses that the
                 */
                struct list_head transport_addr_list;
  
 +              /* rwnd
 +               *
 +               * Peer Rwnd   : Current calculated value of the peer's rwnd.
 +               */
 +              __u32 rwnd;
 +
                /* transport_count
                 *
                 * Peer        : A count of the number of peer addresses
                 */
                struct sctp_tsnmap tsn_map;
  
 +              /* This mask is used to disable sending the ASCONF chunk
 +               * with specified parameter to peer.
 +               */
 +              __be16 addip_disabled_mask;
 +
 +              /* These are capabilities which our peer advertised.  */
 +              __u8    ecn_capable:1,      /* Can peer do ECN? */
 +                      ipv4_address:1,     /* Peer understands IPv4 addresses? */
 +                      ipv6_address:1,     /* Peer understands IPv6 addresses? */
 +                      hostname_address:1, /* Peer understands DNS addresses? */
 +                      asconf_capable:1,   /* Does peer support ADDIP? */
 +                      prsctp_capable:1,   /* Can peer do PR-SCTP? */
 +                      auth_capable:1;     /* Is peer doing SCTP-AUTH? */
 +
                /* Ack State   : This flag indicates if the next received
                 *             : packet is to be responded to with a
                 *             : SACK. This is initializedto 0.  When a packet
                __u32   sack_cnt;
                __u32   sack_generation;
  
 -              /* These are capabilities which our peer advertised.  */
 -              __u8    ecn_capable:1,      /* Can peer do ECN? */
 -                      ipv4_address:1,     /* Peer understands IPv4 addresses? */
 -                      ipv6_address:1,     /* Peer understands IPv6 addresses? */
 -                      hostname_address:1, /* Peer understands DNS addresses? */
 -                      asconf_capable:1,   /* Does peer support ADDIP? */
 -                      prsctp_capable:1,   /* Can peer do PR-SCTP? */
 -                      auth_capable:1;     /* Is peer doing SCTP-AUTH? */
 -
                __u32   adaptation_ind;  /* Adaptation Code point. */
  
 -              /* This mask is used to disable sending the ASCONF chunk
 -               * with specified parameter to peer.
 -               */
 -              __be16 addip_disabled_mask;
 -
                struct sctp_inithdr_host i;
 -              int cookie_len;
                void *cookie;
 +              int cookie_len;
  
                /* ADDIP Section 4.2 Upon reception of an ASCONF Chunk.
                 * C1) ... "Peer-Serial-Number'. This value MUST be initialized to the
         */
        sctp_state_t state;
  
 -      /* The cookie life I award for any cookie.  */
 -      ktime_t cookie_life;
 -
        /* Overall     : The overall association error count.
         * Error Count : [Clear this any time I get something.]
         */
        int overall_error_count;
  
 +      /* The cookie life I award for any cookie.  */
 +      ktime_t cookie_life;
 +
        /* These are the association's initial, max, and min RTO values.
         * These values will be initialized by system defaults, but can
         * be modified via the SCTP_RTOINFO socket option.
        /* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */
        __u32 param_flags;
  
 +      __u32 sackfreq;
        /* SACK delay timeout */
        unsigned long sackdelay;
 -      __u32 sackfreq;
 -
  
        unsigned long timeouts[SCTP_NUM_TIMEOUT_TYPES];
        struct timer_list timers[SCTP_NUM_TIMEOUT_TYPES];
        /* Transport to which SHUTDOWN chunk was last sent.  */
        struct sctp_transport *shutdown_last_sent_to;
  
 -      /* How many times have we resent a SHUTDOWN */
 -      int shutdown_retries;
 -
        /* Transport to which INIT chunk was last sent.  */
        struct sctp_transport *init_last_sent_to;
  
 +      /* How many times have we resent a SHUTDOWN */
 +      int shutdown_retries;
 +
        /* Next TSN    : The next TSN number to be assigned to a new
         *             : DATA chunk.  This is sent in the INIT or INIT
         *             : ACK chunk to the peer and incremented each
        /* How many duplicated TSNs have we seen?  */
        int numduptsns;
  
-       /* Number of seconds of idle time before an association is closed.
-        * In the association context, this is really used as a boolean
-        * since the real timeout is stored in the timeouts array
-        */
-       __u32 autoclose;
        /* These are to support
         * "SCTP Extensions for Dynamic Reconfiguration of IP Addresses
         *  and Enforcement of Flow and Message Limits"
         * after reaching 4294967295.
         */
        __u32 addip_serial;
 -      union sctp_addr *asconf_addr_del_pending;
        int src_out_of_asoc_ok;
 +      union sctp_addr *asconf_addr_del_pending;
        struct sctp_transport *new_transport;
  
        /* SCTP AUTH: list of the endpoint shared keys.  These
diff --combined net/core/neighbour.c
@@@ -38,8 -38,6 +38,8 @@@
  #include <linux/random.h>
  #include <linux/string.h>
  #include <linux/log2.h>
 +#include <linux/inetdevice.h>
 +#include <net/addrconf.h>
  
  #define DEBUG
  #define NEIGH_DEBUG 1
@@@ -499,7 -497,7 +499,7 @@@ struct neighbour *__neigh_create(struc
                goto out_neigh_release;
        }
  
 -      n->confirmed = jiffies - (n->parms->base_reachable_time << 1);
 +      n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
  
        write_lock_bh(&tbl->lock);
        nht = rcu_dereference_protected(tbl->nht,
@@@ -778,7 -776,7 +778,7 @@@ static void neigh_periodic_work(struct 
                tbl->last_rand = jiffies;
                for (p = &tbl->parms; p; p = p->next)
                        p->reachable_time =
 -                              neigh_rand_reach_time(p->base_reachable_time);
 +                              neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
        }
  
        for (i = 0 ; i < (1 << nht->hash_shift); i++) {
  
                        if (atomic_read(&n->refcnt) == 1 &&
                            (state == NUD_FAILED ||
 -                           time_after(jiffies, n->used + n->parms->gc_staletime))) {
 +                           time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
                                *np = n->next;
                                n->dead = 1;
                                write_unlock(&n->lock);
@@@ -824,12 -822,12 +824,12 @@@ next_elt
                                                lockdep_is_held(&tbl->lock));
        }
  out:
 -      /* Cycle through all hash buckets every base_reachable_time/2 ticks.
 -       * ARP entry timeouts range from 1/2 base_reachable_time to 3/2
 -       * base_reachable_time.
 +      /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
 +       * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
 +       * BASE_REACHABLE_TIME.
         */
        schedule_delayed_work(&tbl->gc_work,
 -                            tbl->parms.base_reachable_time >> 1);
 +                            NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
        write_unlock_bh(&tbl->lock);
  }
  
@@@ -837,9 -835,8 +837,9 @@@ static __inline__ int neigh_max_probes(
  {
        struct neigh_parms *p = n->parms;
        return (n->nud_state & NUD_PROBE) ?
 -              p->ucast_probes :
 -              p->ucast_probes + p->app_probes + p->mcast_probes;
 +              NEIGH_VAR(p, UCAST_PROBES) :
 +              NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
 +              NEIGH_VAR(p, MCAST_PROBES);
  }
  
  static void neigh_invalidate(struct neighbour *neigh)
@@@ -904,13 -901,12 +904,13 @@@ static void neigh_timer_handler(unsigne
                        neigh_dbg(2, "neigh %p is still alive\n", neigh);
                        next = neigh->confirmed + neigh->parms->reachable_time;
                } else if (time_before_eq(now,
 -                                        neigh->used + neigh->parms->delay_probe_time)) {
 +                                        neigh->used +
 +                                        NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
                        neigh_dbg(2, "neigh %p is delayed\n", neigh);
                        neigh->nud_state = NUD_DELAY;
                        neigh->updated = jiffies;
                        neigh_suspect(neigh);
 -                      next = now + neigh->parms->delay_probe_time;
 +                      next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
                } else {
                        neigh_dbg(2, "neigh %p is suspected\n", neigh);
                        neigh->nud_state = NUD_STALE;
                }
        } else if (state & NUD_DELAY) {
                if (time_before_eq(now,
 -                                 neigh->confirmed + neigh->parms->delay_probe_time)) {
 +                                 neigh->confirmed +
 +                                 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
                        neigh_dbg(2, "neigh %p is now reachable\n", neigh);
                        neigh->nud_state = NUD_REACHABLE;
                        neigh->updated = jiffies;
                        neigh->nud_state = NUD_PROBE;
                        neigh->updated = jiffies;
                        atomic_set(&neigh->probes, 0);
 -                      next = now + neigh->parms->retrans_time;
 +                      next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
                }
        } else {
                /* NUD_PROBE|NUD_INCOMPLETE */
 -              next = now + neigh->parms->retrans_time;
 +              next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
        }
  
        if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
@@@ -978,16 -973,13 +978,16 @@@ int __neigh_event_send(struct neighbou
                goto out_unlock_bh;
  
        if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
 -              if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
 +              if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
 +                  NEIGH_VAR(neigh->parms, APP_PROBES)) {
                        unsigned long next, now = jiffies;
  
 -                      atomic_set(&neigh->probes, neigh->parms->ucast_probes);
 +                      atomic_set(&neigh->probes,
 +                                 NEIGH_VAR(neigh->parms, UCAST_PROBES));
                        neigh->nud_state     = NUD_INCOMPLETE;
                        neigh->updated = now;
 -                      next = now + max(neigh->parms->retrans_time, HZ/2);
 +                      next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
 +                                       HZ/2);
                        neigh_add_timer(neigh, next);
                        immediate_probe = true;
                } else {
                neigh_dbg(2, "neigh %p is delayed\n", neigh);
                neigh->nud_state = NUD_DELAY;
                neigh->updated = jiffies;
 -              neigh_add_timer(neigh,
 -                              jiffies + neigh->parms->delay_probe_time);
 +              neigh_add_timer(neigh, jiffies +
 +                              NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
        }
  
        if (neigh->nud_state == NUD_INCOMPLETE) {
                if (skb) {
                        while (neigh->arp_queue_len_bytes + skb->truesize >
 -                             neigh->parms->queue_len_bytes) {
 +                             NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
                                struct sk_buff *buff;
  
                                buff = __skb_dequeue(&neigh->arp_queue);
@@@ -1169,6 -1161,7 +1169,7 @@@ int neigh_update(struct neighbour *neig
                                                 neigh->parms->reachable_time :
                                                 0)));
                neigh->nud_state = new;
+               notify = 1;
        }
  
        if (lladdr != neigh->ha) {
                neigh_update_hhs(neigh);
                if (!(new & NUD_CONNECTED))
                        neigh->confirmed = jiffies -
 -                                    (neigh->parms->base_reachable_time << 1);
 +                                    (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
                notify = 1;
        }
        if (new == old)
  }
  EXPORT_SYMBOL(neigh_update);
  
 +/* Update the neigh to listen temporarily for probe responses, even if it is
 + * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
 + */
 +void __neigh_set_probe_once(struct neighbour *neigh)
 +{
 +      neigh->updated = jiffies;
 +      if (!(neigh->nud_state & NUD_FAILED))
 +              return;
 +      neigh->nud_state = NUD_PROBE;
 +      atomic_set(&neigh->probes, NEIGH_VAR(neigh->parms, UCAST_PROBES));
 +      neigh_add_timer(neigh,
 +                      jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
 +}
 +EXPORT_SYMBOL(__neigh_set_probe_once);
 +
  struct neighbour *neigh_event_ns(struct neigh_table *tbl,
                                 u8 *lladdr, void *saddr,
                                 struct net_device *dev)
@@@ -1414,10 -1392,9 +1415,10 @@@ void pneigh_enqueue(struct neigh_table 
                    struct sk_buff *skb)
  {
        unsigned long now = jiffies;
 -      unsigned long sched_next = now + (net_random() % p->proxy_delay);
 +      unsigned long sched_next = now + (net_random() %
 +                                        NEIGH_VAR(p, PROXY_DELAY));
  
 -      if (tbl->proxy_queue.qlen > p->proxy_qlen) {
 +      if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
                kfree_skb(skb);
                return;
        }
@@@ -1464,7 -1441,7 +1465,7 @@@ struct neigh_parms *neigh_parms_alloc(s
                p->tbl            = tbl;
                atomic_set(&p->refcnt, 1);
                p->reachable_time =
 -                              neigh_rand_reach_time(p->base_reachable_time);
 +                              neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
                dev_hold(dev);
                p->dev = dev;
                write_pnet(&p->net, hold_net(net));
                p->next         = tbl->parms.next;
                tbl->parms.next = p;
                write_unlock_bh(&tbl->lock);
 +
 +              neigh_parms_data_state_cleanall(p);
        }
        return p;
  }
@@@ -1535,7 -1510,7 +1536,7 @@@ static void neigh_table_init_no_netlink
        write_pnet(&tbl->parms.net, &init_net);
        atomic_set(&tbl->parms.refcnt, 1);
        tbl->parms.reachable_time =
 -                        neigh_rand_reach_time(tbl->parms.base_reachable_time);
 +                        neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
  
        tbl->stats = alloc_percpu(struct neigh_statistics);
        if (!tbl->stats)
@@@ -1803,32 -1778,24 +1804,32 @@@ static int neightbl_fill_parms(struct s
        if ((parms->dev &&
             nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
            nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
 -          nla_put_u32(skb, NDTPA_QUEUE_LENBYTES, parms->queue_len_bytes) ||
 +          nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
 +                      NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
            /* approximative value for deprecated QUEUE_LEN (in packets) */
            nla_put_u32(skb, NDTPA_QUEUE_LEN,
 -                      parms->queue_len_bytes / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
 -          nla_put_u32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen) ||
 -          nla_put_u32(skb, NDTPA_APP_PROBES, parms->app_probes) ||
 -          nla_put_u32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes) ||
 -          nla_put_u32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes) ||
 +                      NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
 +          nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
 +          nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
 +          nla_put_u32(skb, NDTPA_UCAST_PROBES,
 +                      NEIGH_VAR(parms, UCAST_PROBES)) ||
 +          nla_put_u32(skb, NDTPA_MCAST_PROBES,
 +                      NEIGH_VAR(parms, MCAST_PROBES)) ||
            nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) ||
            nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
 -                        parms->base_reachable_time) ||
 -          nla_put_msecs(skb, NDTPA_GC_STALETIME, parms->gc_staletime) ||
 +                        NEIGH_VAR(parms, BASE_REACHABLE_TIME)) ||
 +          nla_put_msecs(skb, NDTPA_GC_STALETIME,
 +                        NEIGH_VAR(parms, GC_STALETIME)) ||
            nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
 -                        parms->delay_probe_time) ||
 -          nla_put_msecs(skb, NDTPA_RETRANS_TIME, parms->retrans_time) ||
 -          nla_put_msecs(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay) ||
 -          nla_put_msecs(skb, NDTPA_PROXY_DELAY, parms->proxy_delay) ||
 -          nla_put_msecs(skb, NDTPA_LOCKTIME, parms->locktime))
 +                        NEIGH_VAR(parms, DELAY_PROBE_TIME)) ||
 +          nla_put_msecs(skb, NDTPA_RETRANS_TIME,
 +                        NEIGH_VAR(parms, RETRANS_TIME)) ||
 +          nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
 +                        NEIGH_VAR(parms, ANYCAST_DELAY)) ||
 +          nla_put_msecs(skb, NDTPA_PROXY_DELAY,
 +                        NEIGH_VAR(parms, PROXY_DELAY)) ||
 +          nla_put_msecs(skb, NDTPA_LOCKTIME,
 +                        NEIGH_VAR(parms, LOCKTIME)))
                goto nla_put_failure;
        return nla_nest_end(skb, nest);
  
@@@ -2044,54 -2011,44 +2045,54 @@@ static int neightbl_set(struct sk_buff 
  
                        switch (i) {
                        case NDTPA_QUEUE_LEN:
 -                              p->queue_len_bytes = nla_get_u32(tbp[i]) *
 -                                                   SKB_TRUESIZE(ETH_FRAME_LEN);
 +                              NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
 +                                            nla_get_u32(tbp[i]) *
 +                                            SKB_TRUESIZE(ETH_FRAME_LEN));
                                break;
                        case NDTPA_QUEUE_LENBYTES:
 -                              p->queue_len_bytes = nla_get_u32(tbp[i]);
 +                              NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
 +                                            nla_get_u32(tbp[i]));
                                break;
                        case NDTPA_PROXY_QLEN:
 -                              p->proxy_qlen = nla_get_u32(tbp[i]);
 +                              NEIGH_VAR_SET(p, PROXY_QLEN,
 +                                            nla_get_u32(tbp[i]));
                                break;
                        case NDTPA_APP_PROBES:
 -                              p->app_probes = nla_get_u32(tbp[i]);
 +                              NEIGH_VAR_SET(p, APP_PROBES,
 +                                            nla_get_u32(tbp[i]));
                                break;
                        case NDTPA_UCAST_PROBES:
 -                              p->ucast_probes = nla_get_u32(tbp[i]);
 +                              NEIGH_VAR_SET(p, UCAST_PROBES,
 +                                            nla_get_u32(tbp[i]));
                                break;
                        case NDTPA_MCAST_PROBES:
 -                              p->mcast_probes = nla_get_u32(tbp[i]);
 +                              NEIGH_VAR_SET(p, MCAST_PROBES,
 +                                            nla_get_u32(tbp[i]));
                                break;
                        case NDTPA_BASE_REACHABLE_TIME:
 -                              p->base_reachable_time = nla_get_msecs(tbp[i]);
 +                              NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
 +                                            nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_GC_STALETIME:
 -                              p->gc_staletime = nla_get_msecs(tbp[i]);
 +                              NEIGH_VAR_SET(p, GC_STALETIME,
 +                                            nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_DELAY_PROBE_TIME:
 -                              p->delay_probe_time = nla_get_msecs(tbp[i]);
 +                              NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
 +                                            nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_RETRANS_TIME:
 -                              p->retrans_time = nla_get_msecs(tbp[i]);
 +                              NEIGH_VAR_SET(p, RETRANS_TIME,
 +                                            nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_ANYCAST_DELAY:
 -                              p->anycast_delay = nla_get_msecs(tbp[i]);
 +                              NEIGH_VAR_SET(p, ANYCAST_DELAY, nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_PROXY_DELAY:
 -                              p->proxy_delay = nla_get_msecs(tbp[i]);
 +                              NEIGH_VAR_SET(p, PROXY_DELAY, nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_LOCKTIME:
 -                              p->locktime = nla_get_msecs(tbp[i]);
 +                              NEIGH_VAR_SET(p, LOCKTIME, nla_get_msecs(tbp[i]));
                                break;
                        }
                }
@@@ -2832,167 -2789,133 +2833,167 @@@ static int proc_unres_qlen(struct ctl_t
        return ret;
  }
  
 -enum {
 -      NEIGH_VAR_MCAST_PROBE,
 -      NEIGH_VAR_UCAST_PROBE,
 -      NEIGH_VAR_APP_PROBE,
 -      NEIGH_VAR_RETRANS_TIME,
 -      NEIGH_VAR_BASE_REACHABLE_TIME,
 -      NEIGH_VAR_DELAY_PROBE_TIME,
 -      NEIGH_VAR_GC_STALETIME,
 -      NEIGH_VAR_QUEUE_LEN,
 -      NEIGH_VAR_QUEUE_LEN_BYTES,
 -      NEIGH_VAR_PROXY_QLEN,
 -      NEIGH_VAR_ANYCAST_DELAY,
 -      NEIGH_VAR_PROXY_DELAY,
 -      NEIGH_VAR_LOCKTIME,
 -      NEIGH_VAR_RETRANS_TIME_MS,
 -      NEIGH_VAR_BASE_REACHABLE_TIME_MS,
 -      NEIGH_VAR_GC_INTERVAL,
 -      NEIGH_VAR_GC_THRESH1,
 -      NEIGH_VAR_GC_THRESH2,
 -      NEIGH_VAR_GC_THRESH3,
 -      NEIGH_VAR_MAX
 -};
 +static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
 +                                                 int family)
 +{
 +      switch (family) {
 +      case AF_INET:
 +              return __in_dev_arp_parms_get_rcu(dev);
 +      case AF_INET6:
 +              return __in6_dev_nd_parms_get_rcu(dev);
 +      }
 +      return NULL;
 +}
 +
 +static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
 +                                int index)
 +{
 +      struct net_device *dev;
 +      int family = neigh_parms_family(p);
 +
 +      rcu_read_lock();
 +      for_each_netdev_rcu(net, dev) {
 +              struct neigh_parms *dst_p =
 +                              neigh_get_dev_parms_rcu(dev, family);
 +
 +              if (dst_p && !test_bit(index, dst_p->data_state))
 +                      dst_p->data[index] = p->data[index];
 +      }
 +      rcu_read_unlock();
 +}
 +
 +static void neigh_proc_update(struct ctl_table *ctl, int write)
 +{
 +      struct net_device *dev = ctl->extra1;
 +      struct neigh_parms *p = ctl->extra2;
 +      struct net *net = neigh_parms_net(p);
 +      int index = (int *) ctl->data - p->data;
 +
 +      if (!write)
 +              return;
 +
 +      set_bit(index, p->data_state);
 +      if (!dev) /* NULL dev means this is default value */
 +              neigh_copy_dflt_parms(net, p, index);
 +}
 +
 +static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
 +                                         void __user *buffer,
 +                                         size_t *lenp, loff_t *ppos)
 +{
 +      struct ctl_table tmp = *ctl;
 +      int ret;
 +
 +      tmp.extra1 = &zero;
 +      tmp.extra2 = &int_max;
 +
 +      ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
 +      neigh_proc_update(ctl, write);
 +      return ret;
 +}
 +
 +int neigh_proc_dointvec(struct ctl_table *ctl, int write,
 +                      void __user *buffer, size_t *lenp, loff_t *ppos)
 +{
 +      int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
 +
 +      neigh_proc_update(ctl, write);
 +      return ret;
 +}
 +EXPORT_SYMBOL(neigh_proc_dointvec);
 +
 +int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
 +                              void __user *buffer,
 +                              size_t *lenp, loff_t *ppos)
 +{
 +      int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
 +
 +      neigh_proc_update(ctl, write);
 +      return ret;
 +}
 +EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
 +
 +static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
 +                                            void __user *buffer,
 +                                            size_t *lenp, loff_t *ppos)
 +{
 +      int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
 +
 +      neigh_proc_update(ctl, write);
 +      return ret;
 +}
 +
 +int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
 +                                 void __user *buffer,
 +                                 size_t *lenp, loff_t *ppos)
 +{
 +      int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
 +
 +      neigh_proc_update(ctl, write);
 +      return ret;
 +}
 +EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
 +
 +static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
 +                                        void __user *buffer,
 +                                        size_t *lenp, loff_t *ppos)
 +{
 +      int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
 +
 +      neigh_proc_update(ctl, write);
 +      return ret;
 +}
 +
 +#define NEIGH_PARMS_DATA_OFFSET(index)        \
 +      (&((struct neigh_parms *) 0)->data[index])
 +
 +#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
 +      [NEIGH_VAR_ ## attr] = { \
 +              .procname       = name, \
 +              .data           = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
 +              .maxlen         = sizeof(int), \
 +              .mode           = mval, \
 +              .proc_handler   = proc, \
 +      }
 +
 +#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
 +      NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
 +
 +#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
 +      NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
 +
 +#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
 +      NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
 +
 +#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
 +      NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
 +
 +#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
 +      NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
 +
 +#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
 +      NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
  
  static struct neigh_sysctl_table {
        struct ctl_table_header *sysctl_header;
        struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
  } neigh_sysctl_template __read_mostly = {
        .neigh_vars = {
 -              [NEIGH_VAR_MCAST_PROBE] = {
 -                      .procname       = "mcast_solicit",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .extra1         = &zero,
 -                      .extra2         = &int_max,
 -                      .proc_handler   = proc_dointvec_minmax,
 -              },
 -              [NEIGH_VAR_UCAST_PROBE] = {
 -                      .procname       = "ucast_solicit",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .extra1         = &zero,
 -                      .extra2         = &int_max,
 -                      .proc_handler   = proc_dointvec_minmax,
 -              },
 -              [NEIGH_VAR_APP_PROBE] = {
 -                      .procname       = "app_solicit",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .extra1         = &zero,
 -                      .extra2         = &int_max,
 -                      .proc_handler   = proc_dointvec_minmax,
 -              },
 -              [NEIGH_VAR_RETRANS_TIME] = {
 -                      .procname       = "retrans_time",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .proc_handler   = proc_dointvec_userhz_jiffies,
 -              },
 -              [NEIGH_VAR_BASE_REACHABLE_TIME] = {
 -                      .procname       = "base_reachable_time",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .proc_handler   = proc_dointvec_jiffies,
 -              },
 -              [NEIGH_VAR_DELAY_PROBE_TIME] = {
 -                      .procname       = "delay_first_probe_time",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .proc_handler   = proc_dointvec_jiffies,
 -              },
 -              [NEIGH_VAR_GC_STALETIME] = {
 -                      .procname       = "gc_stale_time",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .proc_handler   = proc_dointvec_jiffies,
 -              },
 -              [NEIGH_VAR_QUEUE_LEN] = {
 -                      .procname       = "unres_qlen",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .proc_handler   = proc_unres_qlen,
 -              },
 -              [NEIGH_VAR_QUEUE_LEN_BYTES] = {
 -                      .procname       = "unres_qlen_bytes",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .extra1         = &zero,
 -                      .proc_handler   = proc_dointvec_minmax,
 -              },
 -              [NEIGH_VAR_PROXY_QLEN] = {
 -                      .procname       = "proxy_qlen",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .extra1         = &zero,
 -                      .extra2         = &int_max,
 -                      .proc_handler   = proc_dointvec_minmax,
 -              },
 -              [NEIGH_VAR_ANYCAST_DELAY] = {
 -                      .procname       = "anycast_delay",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .proc_handler   = proc_dointvec_userhz_jiffies,
 -              },
 -              [NEIGH_VAR_PROXY_DELAY] = {
 -                      .procname       = "proxy_delay",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .proc_handler   = proc_dointvec_userhz_jiffies,
 -              },
 -              [NEIGH_VAR_LOCKTIME] = {
 -                      .procname       = "locktime",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .proc_handler   = proc_dointvec_userhz_jiffies,
 -              },
 -              [NEIGH_VAR_RETRANS_TIME_MS] = {
 -                      .procname       = "retrans_time_ms",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .proc_handler   = proc_dointvec_ms_jiffies,
 -              },
 -              [NEIGH_VAR_BASE_REACHABLE_TIME_MS] = {
 -                      .procname       = "base_reachable_time_ms",
 -                      .maxlen         = sizeof(int),
 -                      .mode           = 0644,
 -                      .proc_handler   = proc_dointvec_ms_jiffies,
 -              },
 +              NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
 +              NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
 +              NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
 +              NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
 +              NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
 +              NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
 +              NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
 +              NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
 +              NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
 +              NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
 +              NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
 +              NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
 +              NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
 +              NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
 +              NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
                [NEIGH_VAR_GC_INTERVAL] = {
                        .procname       = "gc_interval",
                        .maxlen         = sizeof(int),
  };
  
  int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
 -                        char *p_name, proc_handler *handler)
 +                        proc_handler *handler)
  {
 +      int i;
        struct neigh_sysctl_table *t;
 -      const char *dev_name_source = NULL;
 +      const char *dev_name_source;
        char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
 +      char *p_name;
  
        t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
        if (!t)
                goto err;
  
 -      t->neigh_vars[NEIGH_VAR_MCAST_PROBE].data  = &p->mcast_probes;
 -      t->neigh_vars[NEIGH_VAR_UCAST_PROBE].data  = &p->ucast_probes;
 -      t->neigh_vars[NEIGH_VAR_APP_PROBE].data  = &p->app_probes;
 -      t->neigh_vars[NEIGH_VAR_RETRANS_TIME].data  = &p->retrans_time;
 -      t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].data  = &p->base_reachable_time;
 -      t->neigh_vars[NEIGH_VAR_DELAY_PROBE_TIME].data  = &p->delay_probe_time;
 -      t->neigh_vars[NEIGH_VAR_GC_STALETIME].data  = &p->gc_staletime;
 -      t->neigh_vars[NEIGH_VAR_QUEUE_LEN].data  = &p->queue_len_bytes;
 -      t->neigh_vars[NEIGH_VAR_QUEUE_LEN_BYTES].data  = &p->queue_len_bytes;
 -      t->neigh_vars[NEIGH_VAR_PROXY_QLEN].data  = &p->proxy_qlen;
 -      t->neigh_vars[NEIGH_VAR_ANYCAST_DELAY].data  = &p->anycast_delay;
 -      t->neigh_vars[NEIGH_VAR_PROXY_DELAY].data = &p->proxy_delay;
 -      t->neigh_vars[NEIGH_VAR_LOCKTIME].data = &p->locktime;
 -      t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].data  = &p->retrans_time;
 -      t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].data  = &p->base_reachable_time;
 +      for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) {
 +              t->neigh_vars[i].data += (long) p;
 +              t->neigh_vars[i].extra1 = dev;
 +              t->neigh_vars[i].extra2 = p;
 +      }
  
        if (dev) {
                dev_name_source = dev->name;
                t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = (int *)(p + 1) + 3;
        }
  
 -
        if (handler) {
                /* RetransTime */
                t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
 -              t->neigh_vars[NEIGH_VAR_RETRANS_TIME].extra1 = dev;
                /* ReachableTime */
                t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
 -              t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].extra1 = dev;
                /* RetransTime (in milliseconds)*/
                t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
 -              t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].extra1 = dev;
                /* ReachableTime (in milliseconds) */
                t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
 -              t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].extra1 = dev;
        }
  
        /* Don't export sysctls to unprivileged users */
        if (neigh_parms_net(p)->user_ns != &init_user_ns)
                t->neigh_vars[0].procname = NULL;
  
 +      switch (neigh_parms_family(p)) {
 +      case AF_INET:
 +            p_name = "ipv4";
 +            break;
 +      case AF_INET6:
 +            p_name = "ipv6";
 +            break;
 +      default:
 +            BUG();
 +      }
 +
        snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
                p_name, dev_name_source);
        t->sysctl_header =
diff --combined net/ipv6/route.c
@@@ -66,9 -66,8 +66,9 @@@
  #endif
  
  enum rt6_nud_state {
 -      RT6_NUD_FAIL_HARD = -2,
 -      RT6_NUD_FAIL_SOFT = -1,
 +      RT6_NUD_FAIL_HARD = -3,
 +      RT6_NUD_FAIL_PROBE = -2,
 +      RT6_NUD_FAIL_DO_RR = -1,
        RT6_NUD_SUCCEED = 1
  };
  
@@@ -522,7 -521,7 +522,7 @@@ static void rt6_probe(struct rt6_info *
                work = kmalloc(sizeof(*work), GFP_ATOMIC);
  
                if (neigh && work)
 -                      neigh->updated = jiffies;
 +                      __neigh_set_probe_once(neigh);
  
                if (neigh)
                        write_unlock(&neigh->lock);
@@@ -578,13 -577,11 +578,13 @@@ static inline enum rt6_nud_state rt6_ch
  #ifdef CONFIG_IPV6_ROUTER_PREF
                else if (!(neigh->nud_state & NUD_FAILED))
                        ret = RT6_NUD_SUCCEED;
 +              else
 +                      ret = RT6_NUD_FAIL_PROBE;
  #endif
                read_unlock(&neigh->lock);
        } else {
                ret = IS_ENABLED(CONFIG_IPV6_ROUTER_PREF) ?
 -                    RT6_NUD_SUCCEED : RT6_NUD_FAIL_SOFT;
 +                    RT6_NUD_SUCCEED : RT6_NUD_FAIL_DO_RR;
        }
        rcu_read_unlock_bh();
  
@@@ -621,17 -618,16 +621,17 @@@ static struct rt6_info *find_match(stru
                goto out;
  
        m = rt6_score_route(rt, oif, strict);
 -      if (m == RT6_NUD_FAIL_SOFT) {
 +      if (m == RT6_NUD_FAIL_DO_RR) {
                match_do_rr = true;
                m = 0; /* lowest valid score */
 -      } else if (m < 0) {
 +      } else if (m == RT6_NUD_FAIL_HARD) {
                goto out;
        }
  
        if (strict & RT6_LOOKUP_F_REACHABLE)
                rt6_probe(rt);
  
 +      /* note that m can be RT6_NUD_FAIL_PROBE at this point */
        if (m > *mpri) {
                *do_rr = match_do_rr;
                *mpri = m;
@@@ -2170,12 -2166,10 +2170,10 @@@ struct rt6_info *addrconf_dst_alloc(str
                                    bool anycast)
  {
        struct net *net = dev_net(idev->dev);
-       struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, 0, NULL);
-       if (!rt) {
-               net_warn_ratelimited("Maximum number of routes reached, consider increasing route/max_size\n");
+       struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
+                                           DST_NOCOUNT, NULL);
+       if (!rt)
                return ERR_PTR(-ENOMEM);
-       }
  
        in6_dev_hold(idev);
  
diff --combined net/ipv6/tcp_ipv6.c
@@@ -156,7 -156,6 +156,6 @@@ static int tcp_v6_connect(struct sock *
                        flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                        if (flowlabel == NULL)
                                return -EINVAL;
-                       usin->sin6_addr = flowlabel->dst;
                        fl6_sock_release(flowlabel);
                }
        }
@@@ -1135,7 -1134,7 +1134,7 @@@ static struct sock * tcp_v6_syn_recv_so
                newnp->opt         = NULL;
                newnp->mcast_oif   = inet6_iif(skb);
                newnp->mcast_hops  = ipv6_hdr(skb)->hop_limit;
 -              newnp->rcv_tclass  = ipv6_get_dsfield(ipv6_hdr(skb));
 +              newnp->rcv_flowinfo = ip6_flowinfo(ipv6_hdr(skb));
  
                /*
                 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
        newnp->opt        = NULL;
        newnp->mcast_oif  = inet6_iif(skb);
        newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
 -      newnp->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb));
 +      newnp->rcv_flowinfo = ip6_flowinfo(ipv6_hdr(skb));
  
        /* Clone native IPv6 options from listening socket (if any)
  
@@@ -1425,8 -1424,8 +1424,8 @@@ ipv6_pktoptions
                        np->mcast_oif = inet6_iif(opt_skb);
                if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
                        np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit;
 -              if (np->rxopt.bits.rxtclass)
 -                      np->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(opt_skb));
 +              if (np->rxopt.bits.rxflow || np->rxopt.bits.rxtclass)
 +                      np->rcv_flowinfo = ip6_flowinfo(ipv6_hdr(opt_skb));
                if (ipv6_opt_accepted(sk, opt_skb)) {
                        skb_set_owner_r(opt_skb, sk);
                        opt_skb = xchg(&np->pktoptions, opt_skb);
diff --combined net/sched/sch_htb.c
@@@ -1337,6 -1337,7 +1337,6 @@@ static int htb_change_class(struct Qdis
        struct htb_sched *q = qdisc_priv(sch);
        struct htb_class *cl = (struct htb_class *)*arg, *parent;
        struct nlattr *opt = tca[TCA_OPTIONS];
 -      struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
        struct nlattr *tb[TCA_HTB_MAX + 1];
        struct tc_htb_opt *hopt;
        u64 rate64, ceil64;
                goto failure;
  
        /* Keeping backward compatible with rate_table based iproute2 tc */
 -      if (hopt->rate.linklayer == TC_LINKLAYER_UNAWARE) {
 -              rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
 -              if (rtab)
 -                      qdisc_put_rtab(rtab);
 -      }
 -      if (hopt->ceil.linklayer == TC_LINKLAYER_UNAWARE) {
 -              ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
 -              if (ctab)
 -                      qdisc_put_rtab(ctab);
 -      }
 +      if (hopt->rate.linklayer == TC_LINKLAYER_UNAWARE)
 +              qdisc_put_rtab(qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]));
 +
 +      if (hopt->ceil.linklayer == TC_LINKLAYER_UNAWARE)
 +              qdisc_put_rtab(qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]));
  
        if (!cl) {              /* new class */
                struct Qdisc *new_q;
                sch_tree_lock(sch);
        }
  
+       rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0;
+       ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0;
+       psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64);
+       psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64);
        /* it used to be a nasty bug here, we have to check that node
         * is really leaf before changing cl->un.leaf !
         */
        if (!cl->level) {
-               cl->quantum = hopt->rate.rate / q->rate2quantum;
+               u64 quantum = cl->rate.rate_bytes_ps;
+               do_div(quantum, q->rate2quantum);
+               cl->quantum = min_t(u64, quantum, INT_MAX);
                if (!hopt->quantum && cl->quantum < 1000) {
                        pr_warning(
                               "HTB: quantum of class %X is small. Consider r2q change.\n",
                        cl->prio = TC_HTB_NUMPRIO - 1;
        }
  
-       rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0;
-       ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0;
-       psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64);
-       psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64);
        cl->buffer = PSCHED_TICKS2NS(hopt->buffer);
        cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer);
  
diff --combined net/sctp/associola.c
@@@ -22,8 -22,9 +22,8 @@@
   * See the GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
 - * along with GNU CC; see the file COPYING.  If not, write to
 - * the Free Software Foundation, 59 Temple Place - Suite 330,
 - * Boston, MA 02111-1307, USA.
 + * along with GNU CC; see the file COPYING.  If not, see
 + * <http://www.gnu.org/licenses/>.
   *
   * Please send any bug reports or fixes you make to the
   * email address(es):
@@@ -89,12 -90,14 +89,12 @@@ static struct sctp_association *sctp_as
  
        /* Initialize the object handling fields.  */
        atomic_set(&asoc->base.refcnt, 1);
 -      asoc->base.dead = false;
  
        /* Initialize the bind addr area.  */
        sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port);
  
        asoc->state = SCTP_STATE_CLOSED;
        asoc->cookie_life = ms_to_ktime(sp->assocparams.sasoc_cookie_life);
 -      asoc->frag_point = 0;
        asoc->user_frag = sp->user_frag;
  
        /* Set the association max_retrans and RTO values from the
        asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max);
        asoc->rto_min = msecs_to_jiffies(sp->rtoinfo.srto_min);
  
 -      asoc->overall_error_count = 0;
 -
        /* Initialize the association's heartbeat interval based on the
         * sock configured value.
         */
         */
        asoc->param_flags = sp->param_flags;
  
 -      /* Initialize the maximum mumber of new data packets that can be sent
 +      /* Initialize the maximum number of new data packets that can be sent
         * in a burst.
         */
        asoc->max_burst = sp->max_burst;
  
        /* initialize association timers */
 -      asoc->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
        asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = asoc->rto_initial;
        asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = asoc->rto_initial;
        asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = asoc->rto_initial;
 -      asoc->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
 -      asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
  
        /* sctpimpguide Section 2.12.2
         * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
        asoc->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
                = 5 * asoc->rto_max;
  
 -      asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
        asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
-       asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
-               min_t(unsigned long, sp->autoclose, net->sctp.max_autoclose) * HZ;
+       asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ;
  
        /* Initializes the timers */
        for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
        asoc->max_init_timeo =
                 msecs_to_jiffies(sp->initmsg.sinit_max_init_timeo);
  
 -      /* Allocate storage for the ssnmap after the inbound and outbound
 -       * streams have been negotiated during Init.
 -       */
 -      asoc->ssnmap = NULL;
 -
        /* Set the local window size for receive.
         * This is also the rcvbuf space per association.
         * RFC 6 - A SCTP receiver MUST be able to receive a minimum of
  
        asoc->a_rwnd = asoc->rwnd;
  
 -      asoc->rwnd_over = 0;
 -      asoc->rwnd_press = 0;
 -
        /* Use my own max window until I learn something better.  */
        asoc->peer.rwnd = SCTP_DEFAULT_MAXWINDOW;
  
 -      /* Set the sndbuf size for transmit.  */
 -      asoc->sndbuf_used = 0;
 -
        /* Initialize the receive memory counter */
        atomic_set(&asoc->rmem_alloc, 0);
  
        init_waitqueue_head(&asoc->wait);
  
        asoc->c.my_vtag = sctp_generate_tag(ep);
 -      asoc->peer.i.init_tag = 0;     /* INIT needs a vtag of 0. */
 -      asoc->c.peer_vtag = 0;
 -      asoc->c.my_ttag   = 0;
 -      asoc->c.peer_ttag = 0;
        asoc->c.my_port = ep->base.bind_addr.port;
  
        asoc->c.initial_tsn = sctp_generate_tsn(ep);
        asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
        asoc->highest_sacked = asoc->ctsn_ack_point;
        asoc->last_cwr_tsn = asoc->ctsn_ack_point;
 -      asoc->unack_data = 0;
  
        /* ADDIP Section 4.1 Asconf Chunk Procedures
         *
  
        /* Make an empty list of remote transport addresses.  */
        INIT_LIST_HEAD(&asoc->peer.transport_addr_list);
 -      asoc->peer.transport_count = 0;
  
        /* RFC 2960 5.1 Normal Establishment of an Association
         *
         * already received one packet.]
         */
        asoc->peer.sack_needed = 1;
 -      asoc->peer.sack_cnt = 0;
        asoc->peer.sack_generation = 1;
  
        /* Assume that the peer will tell us if he recognizes ASCONF
         * as part of INIT exchange.
 -       * The sctp_addip_noauth option is there for backward compatibilty
 +       * The sctp_addip_noauth option is there for backward compatibility
         * and will revert old behavior.
         */
 -      asoc->peer.asconf_capable = 0;
        if (net->sctp.addip_noauth)
                asoc->peer.asconf_capable = 1;
 -      asoc->asconf_addr_del_pending = NULL;
 -      asoc->src_out_of_asoc_ok = 0;
 -      asoc->new_transport = NULL;
  
        /* Create an input queue.  */
        sctp_inq_init(&asoc->base.inqueue);
        if (!sctp_ulpq_init(&asoc->ulpq, asoc))
                goto fail_init;
  
 -      memset(&asoc->peer.tsn_map, 0, sizeof(struct sctp_tsnmap));
 -
 -      asoc->need_ecne = 0;
 -
 -      asoc->assoc_id = 0;
 -
        /* Assume that peer would support both address types unless we are
         * told otherwise.
         */
                asoc->peer.ipv6_address = 1;
        INIT_LIST_HEAD(&asoc->asocs);
  
-       asoc->autoclose = sp->autoclose;
        asoc->default_stream = sp->default_stream;
        asoc->default_ppid = sp->default_ppid;
        asoc->default_flags = sp->default_flags;
        asoc->default_timetolive = sp->default_timetolive;
        asoc->default_rcv_context = sp->default_rcv_context;
  
 -      /* SCTP_GET_ASSOC_STATS COUNTERS */
 -      memset(&asoc->stats, 0, sizeof(struct sctp_priv_assoc_stats));
 -
        /* AUTH related initializations */
        INIT_LIST_HEAD(&asoc->endpoint_shared_keys);
        err = sctp_auth_asoc_copy_shkeys(ep, asoc, gfp);
                goto fail_init;
  
        asoc->active_key_id = ep->active_key_id;
 -      asoc->asoc_shared_key = NULL;
  
 -      asoc->default_hmac_id = 0;
        /* Save the hmacs and chunks list into this association */
        if (ep->auth_hmacs_list)
                memcpy(asoc->c.auth_hmacs, ep->auth_hmacs_list,
@@@ -955,13 -994,17 +952,13 @@@ int sctp_cmp_addr_exact(const union sct
   */
  struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc)
  {
 -      struct sctp_chunk *chunk;
 +      if (!asoc->need_ecne)
 +              return NULL;
  
        /* Send ECNE if needed.
         * Not being able to allocate a chunk here is not deadly.
         */
 -      if (asoc->need_ecne)
 -              chunk = sctp_make_ecne(asoc, asoc->last_ecne_tsn);
 -      else
 -              chunk = NULL;
 -
 -      return chunk;
 +      return sctp_make_ecne(asoc, asoc->last_ecne_tsn);
  }
  
  /*
@@@ -1222,7 -1265,7 +1219,7 @@@ void sctp_assoc_update(struct sctp_asso
                }
        }
  
 -      /* SCTP-AUTH: Save the peer parameters from the new assocaitions
 +      /* SCTP-AUTH: Save the peer parameters from the new associations
         * and also move the association shared keys over
         */
        kfree(asoc->peer.peer_random);
@@@ -1350,7 -1393,7 +1347,7 @@@ void sctp_assoc_sync_pmtu(struct sock *
  }
  
  /* Should we send a SACK to update our peer? */
 -static inline int sctp_peer_needs_update(struct sctp_association *asoc)
 +static inline bool sctp_peer_needs_update(struct sctp_association *asoc)
  {
        struct net *net = sock_net(asoc->base.sk);
        switch (asoc->state) {
                    ((asoc->rwnd - asoc->a_rwnd) >= max_t(__u32,
                           (asoc->base.sk->sk_rcvbuf >> net->sctp.rwnd_upd_shift),
                           asoc->pathmtu)))
 -                      return 1;
 +                      return true;
                break;
        default:
                break;
        }
 -      return 0;
 +      return false;
  }
  
  /* Increase asoc's rwnd by len and send any window update SACK if needed. */
@@@ -1447,7 -1490,7 +1444,7 @@@ void sctp_assoc_rwnd_decrease(struct sc
  
        /* If we've reached or overflowed our receive buffer, announce
         * a 0 rwnd if rwnd would still be positive.  Store the
 -       * the pottential pressure overflow so that the window can be restored
 +       * the potential pressure overflow so that the window can be restored
         * back to original value.
         */
        if (rx_count >= asoc->base.sk->sk_rcvbuf)
diff --combined net/sctp/output.c
@@@ -20,8 -20,9 +20,8 @@@
   * See the GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
 - * along with GNU CC; see the file COPYING.  If not, write to
 - * the Free Software Foundation, 59 Temple Place - Suite 330,
 - * Boston, MA 02111-1307, USA.
 + * along with GNU CC; see the file COPYING.  If not, see
 + * <http://www.gnu.org/licenses/>.
   *
   * Please send any bug reports or fixes you make to the
   * email address(es):
@@@ -580,7 -581,8 +580,8 @@@ int sctp_packet_transmit(struct sctp_pa
                unsigned long timeout;
  
                /* Restart the AUTOCLOSE timer when sending data. */
-               if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) {
+               if (sctp_state(asoc, ESTABLISHED) &&
+                   asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                        timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
                        timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
  
diff --combined net/sctp/sm_statefuns.c
@@@ -22,8 -22,9 +22,8 @@@
   * See the GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
 - * along with GNU CC; see the file COPYING.  If not, write to
 - * the Free Software Foundation, 59 Temple Place - Suite 330,
 - * Boston, MA 02111-1307, USA.
 + * along with GNU CC; see the file COPYING.  If not, see
 + * <http://www.gnu.org/licenses/>.
   *
   * Please send any bug reports or fixes you make to the
   * email address(es):
@@@ -819,7 -820,7 +819,7 @@@ sctp_disposition_t sctp_sf_do_5_1D_ce(s
        SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS);
        sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
  
-       if (new_asoc->autoclose)
+       if (new_asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
  
@@@ -907,7 -908,7 +907,7 @@@ sctp_disposition_t sctp_sf_do_5_1E_ca(s
        SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
        SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS);
        sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
  
@@@ -2969,7 -2970,7 +2969,7 @@@ sctp_disposition_t sctp_sf_eat_data_6_2
        if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM)
                force = SCTP_FORCE();
  
-       if (asoc->autoclose) {
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
        }
@@@ -3877,7 -3878,7 +3877,7 @@@ sctp_disposition_t sctp_sf_eat_fwd_tsn(
                                SCTP_CHUNK(chunk));
  
        /* Count this as receiving DATA. */
-       if (asoc->autoclose) {
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
        }
@@@ -5266,7 -5267,7 +5266,7 @@@ sctp_disposition_t sctp_sf_do_9_2_start
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
  
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
  
@@@ -5345,7 -5346,7 +5345,7 @@@ sctp_disposition_t sctp_sf_do_9_2_shutd
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
  
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
  
diff --combined net/sctp/socket.c
@@@ -28,8 -28,9 +28,8 @@@
   * See the GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
 - * along with GNU CC; see the file COPYING.  If not, write to
 - * the Free Software Foundation, 59 Temple Place - Suite 330,
 - * Boston, MA 02111-1307, USA.
 + * along with GNU CC; see the file COPYING.  If not, see
 + * <http://www.gnu.org/licenses/>.
   *
   * Please send any bug reports or fixes you make to the
   * email address(es):
@@@ -2195,6 -2196,7 +2195,7 @@@ static int sctp_setsockopt_autoclose(st
                                     unsigned int optlen)
  {
        struct sctp_sock *sp = sctp_sk(sk);
+       struct net *net = sock_net(sk);
  
        /* Applicable to UDP-style socket only */
        if (sctp_style(sk, TCP))
        if (copy_from_user(&sp->autoclose, optval, optlen))
                return -EFAULT;
  
+       if (sp->autoclose > net->sctp.max_autoclose)
+               sp->autoclose = net->sctp.max_autoclose;
        return 0;
  }
  
@@@ -2810,6 -2815,8 +2814,8 @@@ static int sctp_setsockopt_rtoinfo(stru
  {
        struct sctp_rtoinfo rtoinfo;
        struct sctp_association *asoc;
+       unsigned long rto_min, rto_max;
+       struct sctp_sock *sp = sctp_sk(sk);
  
        if (optlen != sizeof (struct sctp_rtoinfo))
                return -EINVAL;
        if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP))
                return -EINVAL;
  
+       rto_max = rtoinfo.srto_max;
+       rto_min = rtoinfo.srto_min;
+       if (rto_max)
+               rto_max = asoc ? msecs_to_jiffies(rto_max) : rto_max;
+       else
+               rto_max = asoc ? asoc->rto_max : sp->rtoinfo.srto_max;
+       if (rto_min)
+               rto_min = asoc ? msecs_to_jiffies(rto_min) : rto_min;
+       else
+               rto_min = asoc ? asoc->rto_min : sp->rtoinfo.srto_min;
+       if (rto_min > rto_max)
+               return -EINVAL;
        if (asoc) {
                if (rtoinfo.srto_initial != 0)
                        asoc->rto_initial =
                                msecs_to_jiffies(rtoinfo.srto_initial);
-               if (rtoinfo.srto_max != 0)
-                       asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max);
-               if (rtoinfo.srto_min != 0)
-                       asoc->rto_min = msecs_to_jiffies(rtoinfo.srto_min);
+               asoc->rto_max = rto_max;
+               asoc->rto_min = rto_min;
        } else {
                /* If there is no association or the association-id = 0
                 * set the values to the endpoint.
                 */
-               struct sctp_sock *sp = sctp_sk(sk);
                if (rtoinfo.srto_initial != 0)
                        sp->rtoinfo.srto_initial = rtoinfo.srto_initial;
-               if (rtoinfo.srto_max != 0)
-                       sp->rtoinfo.srto_max = rtoinfo.srto_max;
-               if (rtoinfo.srto_min != 0)
-                       sp->rtoinfo.srto_min = rtoinfo.srto_min;
+               sp->rtoinfo.srto_max = rto_max;
+               sp->rtoinfo.srto_min = rto_min;
        }
  
        return 0;
diff --combined net/sctp/sysctl.c
@@@ -19,8 -19,9 +19,8 @@@
   * See the GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
 - * along with GNU CC; see the file COPYING.  If not, write to
 - * the Free Software Foundation, 59 Temple Place - Suite 330,
 - * Boston, MA 02111-1307, USA.
 + * along with GNU CC; see the file COPYING.  If not, see
 + * <http://www.gnu.org/licenses/>.
   *
   * Please send any bug reports or fixes you make to the
   * email address(es):
@@@ -55,11 -56,16 +55,16 @@@ extern long sysctl_sctp_mem[3]
  extern int sysctl_sctp_rmem[3];
  extern int sysctl_sctp_wmem[3];
  
- static int proc_sctp_do_hmac_alg(struct ctl_table *ctl,
-                               int write,
+ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos);
+ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos);
+ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
                                void __user *buffer, size_t *lenp,
                                loff_t *ppos);
  static struct ctl_table sctp_table[] = {
        {
                .procname       = "sctp_mem",
@@@ -101,17 -107,17 +106,17 @@@ static struct ctl_table sctp_net_table[
                .data           = &init_net.sctp.rto_min,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
+               .proc_handler   = proc_sctp_do_rto_min,
                .extra1         = &one,
-               .extra2         = &timer_max
+               .extra2         = &init_net.sctp.rto_max
        },
        {
                .procname       = "rto_max",
                .data           = &init_net.sctp.rto_max,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .proc_handler   = proc_sctp_do_rto_max,
+               .extra1         = &init_net.sctp.rto_min,
                .extra2         = &timer_max
        },
        {
        { /* sentinel */ }
  };
  
- static int proc_sctp_do_hmac_alg(struct ctl_table *ctl,
-                               int write,
+ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
                                void __user *buffer, size_t *lenp,
                                loff_t *ppos)
  {
        return ret;
  }
  
+ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos)
+ {
+       struct net *net = current->nsproxy->net_ns;
+       int new_value;
+       struct ctl_table tbl;
+       unsigned int min = *(unsigned int *) ctl->extra1;
+       unsigned int max = *(unsigned int *) ctl->extra2;
+       int ret;
+       memset(&tbl, 0, sizeof(struct ctl_table));
+       tbl.maxlen = sizeof(unsigned int);
+       if (write)
+               tbl.data = &new_value;
+       else
+               tbl.data = &net->sctp.rto_min;
+       ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
+       if (write) {
+               if (ret || new_value > max || new_value < min)
+                       return -EINVAL;
+               net->sctp.rto_min = new_value;
+       }
+       return ret;
+ }
+ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos)
+ {
+       struct net *net = current->nsproxy->net_ns;
+       int new_value;
+       struct ctl_table tbl;
+       unsigned int min = *(unsigned int *) ctl->extra1;
+       unsigned int max = *(unsigned int *) ctl->extra2;
+       int ret;
+       memset(&tbl, 0, sizeof(struct ctl_table));
+       tbl.maxlen = sizeof(unsigned int);
+       if (write)
+               tbl.data = &new_value;
+       else
+               tbl.data = &net->sctp.rto_max;
+       ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
+       if (write) {
+               if (ret || new_value > max || new_value < min)
+                       return -EINVAL;
+               net->sctp.rto_max = new_value;
+       }
+       return ret;
+ }
  int sctp_sysctl_net_register(struct net *net)
  {
        struct ctl_table *table;
diff --combined net/tipc/core.c
@@@ -82,7 -82,8 +82,7 @@@ struct sk_buff *tipc_buf_acquire(u32 si
  static void tipc_core_stop_net(void)
  {
        tipc_net_stop();
 -      tipc_eth_media_stop();
 -      tipc_ib_media_stop();
 +      tipc_bearer_cleanup();
  }
  
  /**
@@@ -93,7 -94,10 +93,7 @@@ int tipc_core_start_net(unsigned long a
        int res;
  
        tipc_net_start(addr);
 -      res = tipc_eth_media_start();
 -      if (res < 0)
 -              goto err;
 -      res = tipc_ib_media_start();
 +      res = tipc_bearer_setup();
        if (res < 0)
                goto err;
        return res;
@@@ -109,7 -113,6 +109,6 @@@ err
  static void tipc_core_stop(void)
  {
        tipc_netlink_stop();
-       tipc_handler_stop();
        tipc_cfg_stop();
        tipc_subscr_stop();
        tipc_nametbl_stop();
@@@ -142,9 -145,10 +141,10 @@@ static int tipc_core_start(void
                res = tipc_subscr_start();
        if (!res)
                res = tipc_cfg_init();
-       if (res)
+       if (res) {
+               tipc_handler_stop();
                tipc_core_stop();
+       }
        return res;
  }
  
@@@ -174,6 -178,7 +174,7 @@@ static int __init tipc_init(void
  
  static void __exit tipc_exit(void)
  {
+       tipc_handler_stop();
        tipc_core_stop_net();
        tipc_core_stop();
        pr_info("Deactivated\n");
diff --combined net/unix/af_unix.c
@@@ -80,8 -80,6 +80,8 @@@
   *              with BSD names.
   */
  
 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 +
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/signal.h>
@@@ -368,7 -366,7 +368,7 @@@ static void unix_sock_destructor(struc
        WARN_ON(!sk_unhashed(sk));
        WARN_ON(sk->sk_socket);
        if (!sock_flag(sk, SOCK_DEAD)) {
 -              printk(KERN_INFO "Attempt to release alive unix socket: %p\n", sk);
 +              pr_info("Attempt to release alive unix socket: %p\n", sk);
                return;
        }
  
        sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
        local_bh_enable();
  #ifdef UNIX_REFCNT_DEBUG
 -      printk(KERN_DEBUG "UNIX %p is destroyed, %ld are still alive.\n", sk,
 +      pr_debug("UNIX %p is destroyed, %ld are still alive.\n", sk,
                atomic_long_read(&unix_nr_socks));
  #endif
  }
@@@ -532,13 -530,17 +532,17 @@@ static int unix_seqpacket_sendmsg(struc
  static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
                                  struct msghdr *, size_t, int);
  
- static void unix_set_peek_off(struct sock *sk, int val)
+ static int unix_set_peek_off(struct sock *sk, int val)
  {
        struct unix_sock *u = unix_sk(sk);
  
-       mutex_lock(&u->readlock);
+       if (mutex_lock_interruptible(&u->readlock))
+               return -EINTR;
        sk->sk_peek_off = val;
        mutex_unlock(&u->readlock);
+       return 0;
  }
  
  
@@@ -716,7 -718,9 +720,9 @@@ static int unix_autobind(struct socket 
        int err;
        unsigned int retries = 0;
  
-       mutex_lock(&u->readlock);
+       err = mutex_lock_interruptible(&u->readlock);
+       if (err)
+               return err;
  
        err = 0;
        if (u->addr)
@@@ -875,7 -879,9 +881,9 @@@ static int unix_bind(struct socket *soc
                goto out;
        addr_len = err;
  
-       mutex_lock(&u->readlock);
+       err = mutex_lock_interruptible(&u->readlock);
+       if (err)
+               goto out;
  
        err = -EINVAL;
        if (u->addr)
@@@ -2435,7 -2441,8 +2443,7 @@@ static int __init af_unix_init(void
  
        rc = proto_register(&unix_proto, 1);
        if (rc != 0) {
 -              printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
 -                     __func__);
 +              pr_crit("%s: Cannot create unix_sock SLAB cache!\n", __func__);
                goto out;
        }