[linux-next] LinuxNextTracking branch, master, updated. next-20140120

batman at open-mesh.org batman at open-mesh.org
Tue Jan 21 00:18:43 CET 2014


The following commit has been merged in the master branch:
commit 41804420586ab41049a14ab7ef04eaa2280b8647
Merge: 7b1e46c5a265b142dd05ff3463fa3e0a1f4e4172 7d0d46da750a252371cb747b48ddda27d1047881
Author: David S. Miller <davem at davemloft.net>
Date:   Sat Jan 18 00:55:41 2014 -0800

    Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
    
    Conflicts:
    	drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
    	net/ipv4/tcp_metrics.c
    
    Overlapping changes between the "don't create two tcp metrics objects
    with the same key" race fix in net and the addition of the destination
    address in the lookup key in net-next.
    
    Minor overlapping changes in bnx2x driver.
    
    Signed-off-by: David S. Miller <davem at davemloft.net>

diff --combined MAINTAINERS
index b358a3f,6a6e4ac..a723219
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@@ -1435,7 -1435,7 +1435,7 @@@ F:	Documentation/aoe
  F:	drivers/block/aoe/
  
  ATHEROS ATH GENERIC UTILITIES
 -M:	"Luis R. Rodriguez" <mcgrof at qca.qualcomm.com>
 +M:	"Luis R. Rodriguez" <mcgrof at do-not-panic.com>
  L:	linux-wireless at vger.kernel.org
  S:	Supported
  F:	drivers/net/wireless/ath/*
@@@ -1443,7 -1443,7 +1443,7 @@@
  ATHEROS ATH5K WIRELESS DRIVER
  M:	Jiri Slaby <jirislaby at gmail.com>
  M:	Nick Kossifidis <mickflemm at gmail.com>
 -M:	"Luis R. Rodriguez" <mcgrof at qca.qualcomm.com>
 +M:	"Luis R. Rodriguez" <mcgrof at do-not-panic.com>
  L:	linux-wireless at vger.kernel.org
  L:	ath5k-devel at lists.ath5k.org
  W:	http://wireless.kernel.org/en/users/Drivers/ath5k
@@@ -1458,6 -1458,17 +1458,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 at qca.qualcomm.com>
 -M:	Jouni Malinen <jouni at qca.qualcomm.com>
 -M:	Vasanthakumar Thiagarajan <vthiagar at qca.qualcomm.com>
 -M:	Senthil Balasubramanian <senthilb at qca.qualcomm.com>
 -L:	linux-wireless at vger.kernel.org
 -L:	ath9k-devel at 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 at qca.qualcomm.com>
  L:	linux-wireless at vger.kernel.org
@@@ -2013,7 -2024,6 +2013,7 @@@ L:	linux-can at vger.kernel.or
  W:	http://gitorious.org/linux-can
  T:	git git://gitorious.org/linux-can/linux-can-next.git
  S:	Maintained
 +F:	Documentation/networking/can.txt
  F:	net/can/
  F:	include/linux/can/core.h
  F:	include/uapi/linux/can.h
@@@ -4464,7 -4474,7 +4464,7 @@@ M:	Deepak Saxena <dsaxena at plexity.net
  S:	Maintained
  F:	drivers/char/hw_random/ixp4xx-rng.c
  
 -INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf/i40e)
 +INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf/i40e/i40evf)
  M:	Jeff Kirsher <jeffrey.t.kirsher at intel.com>
  M:	Jesse Brandeburg <jesse.brandeburg at intel.com>
  M:	Bruce Allan <bruce.w.allan at intel.com>
@@@ -4473,7 -4483,6 +4473,7 @@@ M:	Don Skidmore <donald.c.skidmore at inte
  M:	Greg Rose <gregory.v.rose at intel.com>
  M:	Alex Duyck <alexander.h.duyck at intel.com>
  M:	John Ronciak <john.ronciak at intel.com>
 +M:	Mitch Williams <mitch.a.williams at intel.com>
  L:	e1000-devel at lists.sourceforge.net
  W:	http://www.intel.com/support/feedback.htm
  W:	http://e1000.sourceforge.net/
@@@ -4489,7 -4498,6 +4489,7 @@@ F:	Documentation/networking/ixgb.tx
  F:	Documentation/networking/ixgbe.txt
  F:	Documentation/networking/ixgbevf.txt
  F:	Documentation/networking/i40e.txt
 +F:	Documentation/networking/i40evf.txt
  F:	drivers/net/ethernet/intel/
  
  INTEL-MID GPIO DRIVER
@@@ -6980,14 -6988,6 +6980,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 at qca.qualcomm.com>
 +L:	linux-wireless at vger.kernel.org
 +L:	ath9k-devel at 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 at qca.qualcomm.com>
  L:	ath10k at lists.infradead.org
@@@ -8628,11 -8628,12 +8628,11 @@@ S:	Maintaine
  F:	sound/soc/codecs/twl4030*
  
  TI WILINK WIRELESS DRIVERS
 -M:	Luciano Coelho <luca at coelho.fi>
  L:	linux-wireless at 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
  
@@@ -9230,6 -9231,7 +9230,7 @@@ F:	include/media/videobuf2-
  
  VIRTIO CONSOLE DRIVER
  M:	Amit Shah <amit.shah at redhat.com>
+ L:	virtio-dev at lists.oasis-open.org
  L:	virtualization at lists.linux-foundation.org
  S:	Maintained
  F:	drivers/char/virtio_console.c
@@@ -9239,6 -9241,7 +9240,7 @@@ F:	include/uapi/linux/virtio_console.
  VIRTIO CORE, NET AND BLOCK DRIVERS
  M:	Rusty Russell <rusty at rustcorp.com.au>
  M:	"Michael S. Tsirkin" <mst at redhat.com>
+ L:	virtio-dev at lists.oasis-open.org
  L:	virtualization at lists.linux-foundation.org
  S:	Maintained
  F:	drivers/virtio/
@@@ -9251,6 -9254,7 +9253,7 @@@ F:	include/uapi/linux/virtio_*.
  VIRTIO HOST (VHOST)
  M:	"Michael S. Tsirkin" <mst at redhat.com>
  L:	kvm at vger.kernel.org
+ L:	virtio-dev at lists.oasis-open.org
  L:	virtualization at lists.linux-foundation.org
  L:	netdev at vger.kernel.org
  S:	Maintained
diff --combined drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index cf17b66,0067b97..e118a3e
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@@ -27,7 -27,6 +27,7 @@@
  #include <linux/slab.h>
  #include <linux/interrupt.h>
  #include <linux/pci.h>
 +#include <linux/aer.h>
  #include <linux/init.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
@@@ -94,8 -93,8 +94,8 @@@ MODULE_FIRMWARE(FW_FILE_NAME_E1)
  MODULE_FIRMWARE(FW_FILE_NAME_E1H);
  MODULE_FIRMWARE(FW_FILE_NAME_E2);
  
 -int num_queues;
 -module_param(num_queues, int, 0);
 +int bnx2x_num_queues;
 +module_param_named(num_queues, bnx2x_num_queues, int, 0);
  MODULE_PARM_DESC(num_queues,
  		 " Set number of queues (default is as a number of CPUs)");
  
@@@ -103,7 -102,7 +103,7 @@@ static int disable_tpa
  module_param(disable_tpa, int, 0);
  MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature");
  
 -int int_mode;
 +static int int_mode;
  module_param(int_mode, int, 0);
  MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X "
  				"(1 INT#x; 2 MSI)");
@@@ -279,12 -278,6 +279,12 @@@ MODULE_DEVICE_TABLE(pci, bnx2x_pci_tbl)
  #define BNX2X_PREV_WAIT_NEEDED 1
  static DEFINE_SEMAPHORE(bnx2x_prev_sem);
  static LIST_HEAD(bnx2x_prev_list);
 +
 +/* Forward declaration */
 +static struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev);
 +static u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp);
 +static int bnx2x_set_storm_rx_mode(struct bnx2x *bp);
 +
  /****************************************************************************
  * General service functions
  ****************************************************************************/
@@@ -3007,9 -3000,6 +3007,9 @@@ static unsigned long bnx2x_get_common_f
  	if (zero_stats)
  		__set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags);
  
 +	if (bp->flags & TX_SWITCHING)
 +		__set_bit(BNX2X_Q_FLG_TX_SWITCH, &flags);
 +
  	__set_bit(BNX2X_Q_FLG_PCSUM_ON_PKT, &flags);
  	__set_bit(BNX2X_Q_FLG_TUN_INC_INNER_IP_ID, &flags);
  
@@@ -3307,10 -3297,6 +3307,10 @@@ static void bnx2x_drv_info_ether_stat(s
  
  	ether_stat->txq_size = bp->tx_ring_size;
  	ether_stat->rxq_size = bp->rx_ring_size;
 +
 +#ifdef CONFIG_BNX2X_SRIOV
 +	ether_stat->vf_cnt = IS_SRIOV(bp) ? bp->vfdb->sriov.nr_virtfn : 0;
 +#endif
  }
  
  static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp)
@@@ -5866,11 -5852,11 +5866,11 @@@ static void bnx2x_init_eq_ring(struct b
  }
  
  /* called with netif_addr_lock_bh() */
 -int bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
 -			unsigned long rx_mode_flags,
 -			unsigned long rx_accept_flags,
 -			unsigned long tx_accept_flags,
 -			unsigned long ramrod_flags)
 +static int bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
 +			       unsigned long rx_mode_flags,
 +			       unsigned long rx_accept_flags,
 +			       unsigned long tx_accept_flags,
 +			       unsigned long ramrod_flags)
  {
  	struct bnx2x_rx_mode_ramrod_params ramrod_param;
  	int rc;
@@@ -5978,7 -5964,7 +5978,7 @@@ static int bnx2x_fill_accept_flags(stru
  }
  
  /* called with netif_addr_lock_bh() */
 -int bnx2x_set_storm_rx_mode(struct bnx2x *bp)
 +static int bnx2x_set_storm_rx_mode(struct bnx2x *bp)
  {
  	unsigned long rx_mode_flags = 0, ramrod_flags = 0;
  	unsigned long rx_accept_flags = 0, tx_accept_flags = 0;
@@@ -6174,47 -6160,6 +6174,47 @@@ static void bnx2x_init_tx_rings(struct 
  			bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[cos]);
  }
  
 +static void bnx2x_init_fcoe_fp(struct bnx2x *bp)
 +{
 +	struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
 +	unsigned long q_type = 0;
 +
 +	bnx2x_fcoe(bp, rx_queue) = BNX2X_NUM_ETH_QUEUES(bp);
 +	bnx2x_fcoe(bp, cl_id) = bnx2x_cnic_eth_cl_id(bp,
 +						     BNX2X_FCOE_ETH_CL_ID_IDX);
 +	bnx2x_fcoe(bp, cid) = BNX2X_FCOE_ETH_CID(bp);
 +	bnx2x_fcoe(bp, fw_sb_id) = DEF_SB_ID;
 +	bnx2x_fcoe(bp, igu_sb_id) = bp->igu_dsb_id;
 +	bnx2x_fcoe(bp, rx_cons_sb) = BNX2X_FCOE_L2_RX_INDEX;
 +	bnx2x_init_txdata(bp, bnx2x_fcoe(bp, txdata_ptr[0]),
 +			  fp->cid, FCOE_TXQ_IDX(bp), BNX2X_FCOE_L2_TX_INDEX,
 +			  fp);
 +
 +	DP(NETIF_MSG_IFUP, "created fcoe tx data (fp index %d)\n", fp->index);
 +
 +	/* qZone id equals to FW (per path) client id */
 +	bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp);
 +	/* init shortcut */
 +	bnx2x_fcoe(bp, ustorm_rx_prods_offset) =
 +		bnx2x_rx_ustorm_prods_offset(fp);
 +
 +	/* Configure Queue State object */
 +	__set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
 +	__set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
 +
 +	/* No multi-CoS for FCoE L2 client */
 +	BUG_ON(fp->max_cos != 1);
 +
 +	bnx2x_init_queue_obj(bp, &bnx2x_sp_obj(bp, fp).q_obj, fp->cl_id,
 +			     &fp->cid, 1, BP_FUNC(bp), bnx2x_sp(bp, q_rdata),
 +			     bnx2x_sp_mapping(bp, q_rdata), q_type);
 +
 +	DP(NETIF_MSG_IFUP,
 +	   "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d fw_sb %d igu_sb %d\n",
 +	   fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
 +	   fp->igu_sb_id);
 +}
 +
  void bnx2x_nic_init_cnic(struct bnx2x *bp)
  {
  	if (!NO_FCOE(bp))
@@@ -8787,16 -8732,16 +8787,16 @@@ u32 bnx2x_send_unload_req(struct bnx2x 
  		int path = BP_PATH(bp);
  
  		DP(NETIF_MSG_IFDOWN, "NO MCP - load counts[%d]      %d, %d, %d\n",
 -		   path, load_count[path][0], load_count[path][1],
 -		   load_count[path][2]);
 -		load_count[path][0]--;
 -		load_count[path][1 + port]--;
 +		   path, bnx2x_load_count[path][0], bnx2x_load_count[path][1],
 +		   bnx2x_load_count[path][2]);
 +		bnx2x_load_count[path][0]--;
 +		bnx2x_load_count[path][1 + port]--;
  		DP(NETIF_MSG_IFDOWN, "NO MCP - new load counts[%d]  %d, %d, %d\n",
 -		   path, load_count[path][0], load_count[path][1],
 -		   load_count[path][2]);
 -		if (load_count[path][0] == 0)
 +		   path, bnx2x_load_count[path][0], bnx2x_load_count[path][1],
 +		   bnx2x_load_count[path][2]);
 +		if (bnx2x_load_count[path][0] == 0)
  			reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON;
 -		else if (load_count[path][1 + port] == 0)
 +		else if (bnx2x_load_count[path][1 + port] == 0)
  			reset_code = FW_MSG_CODE_DRV_UNLOAD_PORT;
  		else
  			reset_code = FW_MSG_CODE_DRV_UNLOAD_FUNCTION;
@@@ -9822,7 -9767,7 +9822,7 @@@ period_task_exit
   * Init service functions
   */
  
 -u32 bnx2x_get_pretend_reg(struct bnx2x *bp)
 +static u32 bnx2x_get_pretend_reg(struct bnx2x *bp)
  {
  	u32 base = PXP2_REG_PGL_PRETEND_FUNC_F0;
  	u32 stride = PXP2_REG_PGL_PRETEND_FUNC_F1 - base;
@@@ -9909,64 -9854,6 +9909,64 @@@ static void bnx2x_prev_unload_close_mac
  #define BNX2X_PREV_UNDI_BD(val)		((val) >> 16 & 0xffff)
  #define BNX2X_PREV_UNDI_PROD(rcq, bd)	((bd) << 16 | (rcq))
  
 +#define BCM_5710_UNDI_FW_MF_MAJOR	(0x07)
 +#define BCM_5710_UNDI_FW_MF_MINOR	(0x08)
 +#define BCM_5710_UNDI_FW_MF_VERS	(0x05)
 +#define BNX2X_PREV_UNDI_MF_PORT(p)	(0x1a150c + ((p) << 4))
 +#define BNX2X_PREV_UNDI_MF_FUNC(f)	(0x1a184c + ((f) << 4))
 +static bool bnx2x_prev_unload_undi_fw_supports_mf(struct bnx2x *bp)
 +{
 +	u8 major, minor, version;
 +	u32 fw;
 +
 +	/* Must check that FW is loaded */
 +	if (!(REG_RD(bp, MISC_REG_RESET_REG_1) &
 +	     MISC_REGISTERS_RESET_REG_1_RST_XSEM)) {
 +		BNX2X_DEV_INFO("XSEM is reset - UNDI MF FW is not loaded\n");
 +		return false;
 +	}
 +
 +	/* Read Currently loaded FW version */
 +	fw = REG_RD(bp, XSEM_REG_PRAM);
 +	major = fw & 0xff;
 +	minor = (fw >> 0x8) & 0xff;
 +	version = (fw >> 0x10) & 0xff;
 +	BNX2X_DEV_INFO("Loaded FW: 0x%08x: Major 0x%02x Minor 0x%02x Version 0x%02x\n",
 +		       fw, major, minor, version);
 +
 +	if (major > BCM_5710_UNDI_FW_MF_MAJOR)
 +		return true;
 +
 +	if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
 +	    (minor > BCM_5710_UNDI_FW_MF_MINOR))
 +		return true;
 +
 +	if ((major == BCM_5710_UNDI_FW_MF_MAJOR) &&
 +	    (minor == BCM_5710_UNDI_FW_MF_MINOR) &&
 +	    (version >= BCM_5710_UNDI_FW_MF_VERS))
 +		return true;
 +
 +	return false;
 +}
 +
 +static void bnx2x_prev_unload_undi_mf(struct bnx2x *bp)
 +{
 +	int i;
 +
 +	/* Due to legacy (FW) code, the first function on each engine has a
 +	 * different offset macro from the rest of the functions.
 +	 * Setting this for all 8 functions is harmless regardless of whether
 +	 * this is actually a multi-function device.
 +	 */
 +	for (i = 0; i < 2; i++)
 +		REG_WR(bp, BNX2X_PREV_UNDI_MF_PORT(i), 1);
 +
 +	for (i = 2; i < 8; i++)
 +		REG_WR(bp, BNX2X_PREV_UNDI_MF_FUNC(i - 2), 1);
 +
 +	BNX2X_DEV_INFO("UNDI FW (MF) set to discard\n");
 +}
 +
  static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, u8 inc)
  {
  	u16 rcq, bd;
@@@ -10167,7 -10054,7 +10167,7 @@@ static int bnx2x_prev_unload_uncommon(s
  	 * the one required, then FLR will be sufficient to clean any residue
  	 * left by previous driver
  	 */
 -	rc = bnx2x_nic_load_analyze_req(bp, FW_MSG_CODE_DRV_LOAD_FUNCTION);
 +	rc = bnx2x_compare_fw_ver(bp, FW_MSG_CODE_DRV_LOAD_FUNCTION, false);
  
  	if (!rc) {
  		/* fw version is good */
@@@ -10255,17 -10142,10 +10255,17 @@@ static int bnx2x_prev_unload_common(str
  			else
  				timer_count--;
  
 -			/* If UNDI resides in memory, manually increment it */
 -			if (prev_undi)
 +			/* New UNDI FW supports MF and contains better
 +			 * cleaning methods - might be redundant but harmless.
 +			 */
 +			if (bnx2x_prev_unload_undi_fw_supports_mf(bp)) {
 +				bnx2x_prev_unload_undi_mf(bp);
 +			} else if (prev_undi) {
 +				/* If UNDI resides in memory,
 +				 * manually increment it
 +				 */
  				bnx2x_prev_unload_undi_inc(bp, BP_PORT(bp), 1);
 -
 +			}
  			udelay(10);
  		}
  
@@@ -10385,8 -10265,8 +10385,8 @@@ static int bnx2x_prev_unload(struct bnx
  	} while (--time_counter);
  
  	if (!time_counter || rc) {
 -		BNX2X_ERR("Failed unloading previous driver, aborting\n");
 -		rc = -EBUSY;
 +		BNX2X_DEV_INFO("Unloading previous driver did not occur, Possibly due to MF UNDI\n");
 +		rc = -EPROBE_DEFER;
  	}
  
  	/* Mark function if its port was used to boot from SAN */
@@@ -11756,11 -11636,7 +11756,11 @@@ static int bnx2x_init_bp(struct bnx2x *
  							DRV_MSG_SEQ_NUMBER_MASK;
  		BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
  
 -		bnx2x_prev_unload(bp);
 +		rc = bnx2x_prev_unload(bp);
 +		if (rc) {
 +			bnx2x_free_mem_bp(bp);
 +			return rc;
 +		}
  	}
  
  	if (CHIP_REV_IS_FPGA(bp))
@@@ -12055,7 -11931,7 +12055,7 @@@ static int bnx2x_set_mc_list(struct bnx
  }
  
  /* If bp->state is OPEN, should be called with netif_addr_lock_bh() */
 -void bnx2x_set_rx_mode(struct net_device *dev)
 +static void bnx2x_set_rx_mode(struct net_device *dev)
  {
  	struct bnx2x *bp = netdev_priv(dev);
  
@@@ -12280,14 -12156,6 +12280,14 @@@ static int bnx2x_set_coherency_mask(str
  	return 0;
  }
  
 +static void bnx2x_disable_pcie_error_reporting(struct bnx2x *bp)
 +{
 +	if (bp->flags & AER_ENABLED) {
 +		pci_disable_pcie_error_reporting(bp->pdev);
 +		bp->flags &= ~AER_ENABLED;
 +	}
 +}
 +
  static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
  			  struct net_device *dev, unsigned long board_type)
  {
@@@ -12394,14 -12262,6 +12394,14 @@@
  	/* clean indirect addresses */
  	pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS,
  			       PCICFG_VENDOR_ID_OFFSET);
 +
 +	/* AER (Advanced Error reporting) configuration */
 +	rc = pci_enable_pcie_error_reporting(pdev);
 +	if (!rc)
 +		bp->flags |= AER_ENABLED;
 +	else
 +		BNX2X_DEV_INFO("Failed To configure PCIe AER [%d]\n", rc);
 +
  	/*
  	 * Clean the following indirect addresses for all functions since it
  	 * is not used by the driver.
@@@ -12833,6 -12693,8 +12833,6 @@@ static int set_is_vf(int chip_id
  	}
  }
  
 -struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev);
 -
  static int bnx2x_init_one(struct pci_dev *pdev,
  				    const struct pci_device_id *ent)
  {
@@@ -13007,8 -12869,6 +13007,8 @@@
  	return 0;
  
  init_one_exit:
 +	bnx2x_disable_pcie_error_reporting(bp);
 +
  	if (bp->regview)
  		iounmap(bp->regview);
  
@@@ -13082,27 -12942,26 +13082,27 @@@ static void __bnx2x_remove(struct pci_d
  		pci_set_power_state(pdev, PCI_D3hot);
  	}
  
 +	bnx2x_disable_pcie_error_reporting(bp);
+ 	if (remove_netdev) {
+ 		if (bp->regview)
+ 			iounmap(bp->regview);
  
- 	if (bp->regview)
- 		iounmap(bp->regview);
- 
- 	/* for vf doorbells are part of the regview and were unmapped along with
- 	 * it. FW is only loaded by PF.
- 	 */
- 	if (IS_PF(bp)) {
- 		if (bp->doorbells)
- 			iounmap(bp->doorbells);
+ 		/* For vfs, doorbells are part of the regview and were unmapped
+ 		 * along with it. FW is only loaded by PF.
+ 		 */
+ 		if (IS_PF(bp)) {
+ 			if (bp->doorbells)
+ 				iounmap(bp->doorbells);
  
- 		bnx2x_release_firmware(bp);
- 	}
- 	bnx2x_free_mem_bp(bp);
+ 			bnx2x_release_firmware(bp);
+ 		}
+ 		bnx2x_free_mem_bp(bp);
  
- 	if (remove_netdev)
  		free_netdev(dev);
  
- 	if (atomic_read(&pdev->enable_cnt) == 1)
- 		pci_release_regions(pdev);
+ 		if (atomic_read(&pdev->enable_cnt) == 1)
+ 			pci_release_regions(pdev);
+ 	}
  
  	pci_disable_device(pdev);
  }
@@@ -13261,14 -13120,6 +13261,14 @@@ static pci_ers_result_t bnx2x_io_slot_r
  
  	rtnl_unlock();
  
 +	/* If AER, perform cleanup of the PCIe registers */
 +	if (bp->flags & AER_ENABLED) {
 +		if (pci_cleanup_aer_uncorrect_error_status(pdev))
 +			BNX2X_ERR("pci_cleanup_aer_uncorrect_error_status failed\n");
 +		else
 +			DP(NETIF_MSG_HW, "pci_cleanup_aer_uncorrect_error_status succeeded\n");
 +	}
 +
  	return PCI_ERS_RESULT_RECOVERED;
  }
  
@@@ -13907,7 -13758,7 +13907,7 @@@ static int bnx2x_unregister_cnic(struc
  	return 0;
  }
  
 -struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
 +static struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
  {
  	struct bnx2x *bp = netdev_priv(dev);
  	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
@@@ -13957,7 -13808,7 +13957,7 @@@
  	return cp;
  }
  
 -u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp)
 +static u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp)
  {
  	struct bnx2x *bp = fp->bp;
  	u32 offset = BAR_USTRORM_INTMEM;
diff --combined drivers/net/ethernet/emulex/benet/be_main.c
index 6d22d6f,a37039d..4dc9639
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@@ -121,6 -121,12 +121,6 @@@ static const char * const ue_status_hi_
  	"Unknown"
  };
  
 -/* Is BE in a multi-channel mode */
 -static inline bool be_is_mc(struct be_adapter *adapter) {
 -	return (adapter->function_mode & FLEX10_MODE ||
 -		adapter->function_mode & VNIC_MODE ||
 -		adapter->function_mode & UMC_ENABLED);
 -}
  
  static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q)
  {
@@@ -252,12 -258,6 +252,12 @@@ static int be_mac_addr_set(struct net_d
  	if (!is_valid_ether_addr(addr->sa_data))
  		return -EADDRNOTAVAIL;
  
 +	/* Proceed further only if, User provided MAC is different
 +	 * from active MAC
 +	 */
 +	if (ether_addr_equal(addr->sa_data, netdev->dev_addr))
 +		return 0;
 +
  	/* The PMAC_ADD cmd may fail if the VF doesn't have FILTMGMT
  	 * privilege or if PF did not provision the new MAC address.
  	 * On BE3, this cmd will always fail if the VF doesn't have the
@@@ -280,15 -280,14 +280,15 @@@
  	/* Decide if the new MAC is successfully activated only after
  	 * querying the FW
  	 */
 -	status = be_cmd_get_active_mac(adapter, curr_pmac_id, mac);
 +	status = be_cmd_get_active_mac(adapter, curr_pmac_id, mac,
 +				       adapter->if_handle, true, 0);
  	if (status)
  		goto err;
  
  	/* The MAC change did not happen, either due to lack of privilege
  	 * or PF didn't pre-provision.
  	 */
 -	if (memcmp(addr->sa_data, mac, ETH_ALEN)) {
 +	if (!ether_addr_equal(addr->sa_data, mac)) {
  		status = -EPERM;
  		goto err;
  	}
@@@ -1443,12 -1442,12 +1443,12 @@@ static inline bool csum_passed(struct b
  				(rxcp->ip_csum || rxcp->ipv6);
  }
  
 -static struct be_rx_page_info *get_rx_page_info(struct be_rx_obj *rxo,
 -						u16 frag_idx)
 +static struct be_rx_page_info *get_rx_page_info(struct be_rx_obj *rxo)
  {
  	struct be_adapter *adapter = rxo->adapter;
  	struct be_rx_page_info *rx_page_info;
  	struct be_queue_info *rxq = &rxo->q;
 +	u16 frag_idx = rxq->tail;
  
  	rx_page_info = &rxo->page_info_tbl[frag_idx];
  	BUG_ON(!rx_page_info->page);
@@@ -1460,7 -1459,6 +1460,7 @@@
  		rx_page_info->last_page_user = false;
  	}
  
 +	queue_tail_inc(rxq);
  	atomic_dec(&rxq->used);
  	return rx_page_info;
  }
@@@ -1469,13 -1467,15 +1469,13 @@@
  static void be_rx_compl_discard(struct be_rx_obj *rxo,
  				struct be_rx_compl_info *rxcp)
  {
 -	struct be_queue_info *rxq = &rxo->q;
  	struct be_rx_page_info *page_info;
  	u16 i, num_rcvd = rxcp->num_rcvd;
  
  	for (i = 0; i < num_rcvd; i++) {
 -		page_info = get_rx_page_info(rxo, rxcp->rxq_idx);
 +		page_info = get_rx_page_info(rxo);
  		put_page(page_info->page);
  		memset(page_info, 0, sizeof(*page_info));
 -		index_inc(&rxcp->rxq_idx, rxq->len);
  	}
  }
  
@@@ -1486,12 -1486,13 +1486,12 @@@
  static void skb_fill_rx_data(struct be_rx_obj *rxo, struct sk_buff *skb,
  			     struct be_rx_compl_info *rxcp)
  {
 -	struct be_queue_info *rxq = &rxo->q;
  	struct be_rx_page_info *page_info;
  	u16 i, j;
  	u16 hdr_len, curr_frag_len, remaining;
  	u8 *start;
  
 -	page_info = get_rx_page_info(rxo, rxcp->rxq_idx);
 +	page_info = get_rx_page_info(rxo);
  	start = page_address(page_info->page) + page_info->page_offset;
  	prefetch(start);
  
@@@ -1525,9 -1526,10 +1525,9 @@@
  	}
  
  	/* More frags present for this completion */
 -	index_inc(&rxcp->rxq_idx, rxq->len);
  	remaining = rxcp->pkt_size - curr_frag_len;
  	for (i = 1, j = 0; i < rxcp->num_rcvd; i++) {
 -		page_info = get_rx_page_info(rxo, rxcp->rxq_idx);
 +		page_info = get_rx_page_info(rxo);
  		curr_frag_len = min(remaining, rx_frag_size);
  
  		/* Coalesce all frags from the same physical page in one slot */
@@@ -1548,6 -1550,7 +1548,6 @@@
  		skb->data_len += curr_frag_len;
  		skb->truesize += rx_frag_size;
  		remaining -= curr_frag_len;
 -		index_inc(&rxcp->rxq_idx, rxq->len);
  		page_info->page = NULL;
  	}
  	BUG_ON(j > MAX_SKB_FRAGS);
@@@ -1578,7 -1581,7 +1578,7 @@@ static void be_rx_compl_process(struct 
  	skb->protocol = eth_type_trans(skb, netdev);
  	skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]);
  	if (netdev->features & NETIF_F_RXHASH)
 -		skb->rxhash = rxcp->rss_hash;
 +		skb_set_hash(skb, rxcp->rss_hash, PKT_HASH_TYPE_L3);
  	skb_mark_napi_id(skb, napi);
  
  	if (rxcp->vlanf)
@@@ -1595,6 -1598,7 +1595,6 @@@ static void be_rx_compl_process_gro(str
  	struct be_adapter *adapter = rxo->adapter;
  	struct be_rx_page_info *page_info;
  	struct sk_buff *skb = NULL;
 -	struct be_queue_info *rxq = &rxo->q;
  	u16 remaining, curr_frag_len;
  	u16 i, j;
  
@@@ -1606,7 -1610,7 +1606,7 @@@
  
  	remaining = rxcp->pkt_size;
  	for (i = 0, j = -1; i < rxcp->num_rcvd; i++) {
 -		page_info = get_rx_page_info(rxo, rxcp->rxq_idx);
 +		page_info = get_rx_page_info(rxo);
  
  		curr_frag_len = min(remaining, rx_frag_size);
  
@@@ -1624,6 -1628,7 +1624,6 @@@
  		skb_frag_size_add(&skb_shinfo(skb)->frags[j], curr_frag_len);
  		skb->truesize += rx_frag_size;
  		remaining -= curr_frag_len;
 -		index_inc(&rxcp->rxq_idx, rxq->len);
  		memset(page_info, 0, sizeof(*page_info));
  	}
  	BUG_ON(j > MAX_SKB_FRAGS);
@@@ -1634,7 -1639,7 +1634,7 @@@
  	skb->ip_summed = CHECKSUM_UNNECESSARY;
  	skb_record_rx_queue(skb, rxo - &adapter->rx_obj[0]);
  	if (adapter->netdev->features & NETIF_F_RXHASH)
 -		skb->rxhash = rxcp->rss_hash;
 +		skb_set_hash(skb, rxcp->rss_hash, PKT_HASH_TYPE_L3);
  	skb_mark_napi_id(skb, napi);
  
  	if (rxcp->vlanf)
@@@ -1658,6 -1663,8 +1658,6 @@@ static void be_parse_rx_compl_v1(struc
  		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, l4_cksm, compl);
  	rxcp->ipv6 =
  		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, ip_version, compl);
 -	rxcp->rxq_idx =
 -		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, fragndx, compl);
  	rxcp->num_rcvd =
  		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, numfrags, compl);
  	rxcp->pkt_type =
@@@ -1688,6 -1695,8 +1688,6 @@@ static void be_parse_rx_compl_v0(struc
  		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, l4_cksm, compl);
  	rxcp->ipv6 =
  		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, ip_version, compl);
 -	rxcp->rxq_idx =
 -		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, fragndx, compl);
  	rxcp->num_rcvd =
  		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, numfrags, compl);
  	rxcp->pkt_type =
@@@ -1767,6 -1776,7 +1767,7 @@@ static void be_post_rx_frags(struct be_
  	struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL;
  	struct be_queue_info *rxq = &rxo->q;
  	struct page *pagep = NULL;
+ 	struct device *dev = &adapter->pdev->dev;
  	struct be_eth_rx_d *rxd;
  	u64 page_dmaaddr = 0, frag_dmaaddr;
  	u32 posted, page_offset = 0;
@@@ -1779,9 -1789,15 +1780,15 @@@
  				rx_stats(rxo)->rx_post_fail++;
  				break;
  			}
- 			page_dmaaddr = dma_map_page(&adapter->pdev->dev, pagep,
- 						    0, adapter->big_page_size,
+ 			page_dmaaddr = dma_map_page(dev, pagep, 0,
+ 						    adapter->big_page_size,
  						    DMA_FROM_DEVICE);
+ 			if (dma_mapping_error(dev, page_dmaaddr)) {
+ 				put_page(pagep);
+ 				pagep = NULL;
+ 				rx_stats(rxo)->rx_post_fail++;
+ 				break;
+ 			}
  			page_info->page_offset = 0;
  		} else {
  			get_page(pagep);
@@@ -1905,6 -1921,7 +1912,6 @@@ static void be_rx_cq_clean(struct be_rx
  	struct be_rx_compl_info *rxcp;
  	struct be_adapter *adapter = rxo->adapter;
  	int flush_wait = 0;
 -	u16 tail;
  
  	/* Consume pending rx completions.
  	 * Wait for the flush completion (identified by zero num_rcvd)
@@@ -1937,8 -1954,9 +1944,8 @@@
  	be_cq_notify(adapter, rx_cq->id, false, 0);
  
  	/* Then free posted rx buffers that were not used */
 -	tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len;
 -	for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) {
 -		page_info = get_rx_page_info(rxo, tail);
 +	while (atomic_read(&rxq->used) > 0) {
 +		page_info = get_rx_page_info(rxo);
  		put_page(page_info->page);
  		memset(page_info, 0, sizeof(*page_info));
  	}
@@@ -2873,11 -2891,14 +2880,11 @@@ static int be_vfs_mac_query(struct be_a
  	int status, vf;
  	u8 mac[ETH_ALEN];
  	struct be_vf_cfg *vf_cfg;
 -	bool active = false;
  
  	for_all_vfs(adapter, vf_cfg, vf) {
 -		be_cmd_get_mac_from_list(adapter, mac, &active,
 -					 &vf_cfg->pmac_id, 0);
 -
 -		status = be_cmd_mac_addr_query(adapter, mac, false,
 -					       vf_cfg->if_handle, 0);
 +		status = be_cmd_get_active_mac(adapter, vf_cfg->pmac_id,
 +					       mac, vf_cfg->if_handle,
 +					       false, vf+1);
  		if (status)
  			return status;
  		memcpy(vf_cfg->mac_addr, mac, ETH_ALEN);
@@@ -3219,7 -3240,6 +3226,7 @@@ static int be_get_resources(struct be_a
  /* Routine to query per function resource limits */
  static int be_get_config(struct be_adapter *adapter)
  {
 +	u16 profile_id;
  	int status;
  
  	status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
@@@ -3229,13 -3249,6 +3236,13 @@@
  	if (status)
  		return status;
  
 +	 if (be_physfn(adapter)) {
 +		status = be_cmd_get_active_profile(adapter, &profile_id);
 +		if (!status)
 +			dev_info(&adapter->pdev->dev,
 +				 "Using profile 0x%x\n", profile_id);
 +	}
 +
  	status = be_get_resources(adapter);
  	if (status)
  		return status;
@@@ -3390,6 -3403,11 +3397,6 @@@ static int be_setup(struct be_adapter *
  		goto err;
  
  	be_cmd_get_fn_privileges(adapter, &adapter->cmd_privileges, 0);
 -	/* In UMC mode FW does not return right privileges.
 -	 * Override with correct privilege equivalent to PF.
 -	 */
 -	if (be_is_mc(adapter))
 -		adapter->cmd_privileges = MAX_PRIVILEGES;
  
  	status = be_mac_setup(adapter);
  	if (status)
@@@ -3408,8 -3426,6 +3415,8 @@@
  
  	be_set_rx_mode(adapter->netdev);
  
 +	be_cmd_get_acpi_wol_cap(adapter);
 +
  	be_cmd_get_flow_control(adapter, &tx_fc, &rx_fc);
  
  	if (rx_fc != adapter->rx_fc || tx_fc != adapter->tx_fc)
@@@ -4279,22 -4295,74 +4286,22 @@@ static void be_remove(struct pci_dev *p
  	free_netdev(adapter->netdev);
  }
  
 -bool be_is_wol_supported(struct be_adapter *adapter)
 -{
 -	return ((adapter->wol_cap & BE_WOL_CAP) &&
 -		!be_is_wol_excluded(adapter)) ? true : false;
 -}
 -
 -u32 be_get_fw_log_level(struct be_adapter *adapter)
 -{
 -	struct be_dma_mem extfat_cmd;
 -	struct be_fat_conf_params *cfgs;
 -	int status;
 -	u32 level = 0;
 -	int j;
 -
 -	if (lancer_chip(adapter))
 -		return 0;
 -
 -	memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
 -	extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
 -	extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
 -					     &extfat_cmd.dma);
 -
 -	if (!extfat_cmd.va) {
 -		dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
 -			__func__);
 -		goto err;
 -	}
 -
 -	status = be_cmd_get_ext_fat_capabilites(adapter, &extfat_cmd);
 -	if (!status) {
 -		cfgs = (struct be_fat_conf_params *)(extfat_cmd.va +
 -						sizeof(struct be_cmd_resp_hdr));
 -		for (j = 0; j < le32_to_cpu(cfgs->module[0].num_modes); j++) {
 -			if (cfgs->module[0].trace_lvl[j].mode == MODE_UART)
 -				level = cfgs->module[0].trace_lvl[j].dbg_lvl;
 -		}
 -	}
 -	pci_free_consistent(adapter->pdev, extfat_cmd.size, extfat_cmd.va,
 -			    extfat_cmd.dma);
 -err:
 -	return level;
 -}
 -
  static int be_get_initial_config(struct be_adapter *adapter)
  {
 -	int status;
 -	u32 level;
 +	int status, level;
  
  	status = be_cmd_get_cntl_attributes(adapter);
  	if (status)
  		return status;
  
  	/* Must be a power of 2 or else MODULO will BUG_ON */
  	adapter->be_get_temp_freq = 64;
  
 -	level = be_get_fw_log_level(adapter);
 -	adapter->msg_enable = level <= FW_LOG_LEVEL_DEFAULT ? NETIF_MSG_HW : 0;
 +	if (BEx_chip(adapter)) {
 +		level = be_cmd_get_fw_log_level(adapter);
 +		adapter->msg_enable =
 +			level <= FW_LOG_LEVEL_DEFAULT ? NETIF_MSG_HW : 0;
 +	}
  
  	adapter->cfg_num_qs = netif_get_num_default_rss_queues();
  	return 0;
@@@ -4557,7 -4625,7 +4564,7 @@@ static int be_suspend(struct pci_dev *p
  	struct be_adapter *adapter = pci_get_drvdata(pdev);
  	struct net_device *netdev =  adapter->netdev;
  
 -	if (adapter->wol)
 +	if (adapter->wol_en)
  		be_setup_wol(adapter, true);
  
  	be_intr_set(adapter, false);
@@@ -4613,7 -4681,7 +4620,7 @@@ static int be_resume(struct pci_dev *pd
  			      msecs_to_jiffies(1000));
  	netif_device_attach(netdev);
  
 -	if (adapter->wol)
 +	if (adapter->wol_en)
  		be_setup_wol(adapter, false);
  
  	return 0;
diff --combined drivers/net/ethernet/intel/e1000e/netdev.c
index d6570b2,6d14eea..6d91933
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@@ -5790,7 -5790,7 +5790,7 @@@ static int e1000_mii_ioctl(struct net_d
   * specified. Matching the kind of event packet is not supported, with the
   * exception of "all V2 events regardless of level 2 or 4".
   **/
 -static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr)
 +static int e1000e_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr)
  {
  	struct e1000_adapter *adapter = netdev_priv(netdev);
  	struct hwtstamp_config config;
@@@ -5825,14 -5825,6 +5825,14 @@@
  			    sizeof(config)) ? -EFAULT : 0;
  }
  
 +static int e1000e_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr)
 +{
 +	struct e1000_adapter *adapter = netdev_priv(netdev);
 +
 +	return copy_to_user(ifr->ifr_data, &adapter->hwtstamp_config,
 +			    sizeof(adapter->hwtstamp_config)) ? -EFAULT : 0;
 +}
 +
  static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
  {
  	switch (cmd) {
@@@ -5841,9 -5833,7 +5841,9 @@@
  	case SIOCSMIIREG:
  		return e1000_mii_ioctl(netdev, ifr, cmd);
  	case SIOCSHWTSTAMP:
 -		return e1000e_hwtstamp_ioctl(netdev, ifr);
 +		return e1000e_hwtstamp_set(netdev, ifr);
 +	case SIOCGHWTSTAMP:
 +		return e1000e_hwtstamp_get(netdev, ifr);
  	default:
  		return -EOPNOTSUPP;
  	}
@@@ -6184,7 -6174,7 +6184,7 @@@ static int __e1000_resume(struct pci_de
  	return 0;
  }
  
- #ifdef CONFIG_PM
+ #ifdef CONFIG_PM_SLEEP
  static int e1000_suspend(struct device *dev)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
@@@ -6203,7 -6193,7 +6203,7 @@@ static int e1000_resume(struct device *
  
  	return __e1000_resume(pdev);
  }
- #endif /* CONFIG_PM */
+ #endif /* CONFIG_PM_SLEEP */
  
  #ifdef CONFIG_PM_RUNTIME
  static int e1000_runtime_suspend(struct device *dev)
@@@ -7025,13 -7015,11 +7025,11 @@@ static DEFINE_PCI_DEVICE_TABLE(e1000_pc
  };
  MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
  
- #ifdef CONFIG_PM
  static const struct dev_pm_ops e1000_pm_ops = {
  	SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume)
  	SET_RUNTIME_PM_OPS(e1000_runtime_suspend, e1000_runtime_resume,
  			   e1000_idle)
  };
- #endif
  
  /* PCI Device API Driver */
  static struct pci_driver e1000_driver = {
@@@ -7039,11 -7027,9 +7037,9 @@@
  	.id_table = e1000_pci_tbl,
  	.probe    = e1000_probe,
  	.remove   = e1000_remove,
  	.driver   = {
  		.pm = &e1000_pm_ops,
  	},
- #endif
  	.shutdown = e1000_shutdown,
  	.err_handler = &e1000_err_handler
  };
diff --combined drivers/net/ethernet/qlogic/qlge/qlge_main.c
index 394c0a5,f705aee..ce2cfdd
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@@ -6,6 -6,7 +6,6 @@@
   *                      Ron Mercer <ron.mercer at qlogic.com>
   */
  #include <linux/kernel.h>
 -#include <linux/init.h>
  #include <linux/bitops.h>
  #include <linux/types.h>
  #include <linux/module.h>
@@@ -4764,6 -4765,8 +4764,8 @@@ static int qlge_probe(struct pci_dev *p
  			    NETIF_F_RXCSUM;
  	ndev->features = ndev->hw_features;
  	ndev->vlan_features = ndev->hw_features;
+ 	/* vlan gets same features (except vlan filter) */
+ 	ndev->vlan_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
  
  	if (test_bit(QL_DMA64, &qdev->flags))
  		ndev->features |= NETIF_F_HIGHDMA;
diff --combined drivers/net/usb/dm9601.c
index 15e3f8e,e802198..6e9c344
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@@ -13,6 -13,7 +13,6 @@@
  #include <linux/module.h>
  #include <linux/sched.h>
  #include <linux/stddef.h>
 -#include <linux/init.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/ethtool.h>
@@@ -613,6 -614,18 +613,18 @@@ static const struct usb_device_id produ
  	 USB_DEVICE(0x0a46, 0x9621),	/* DM9621A USB to Fast Ethernet Adapter */
  	 .driver_info = (unsigned long)&dm9601_info,
  	},
+ 	{
+ 	 USB_DEVICE(0x0a46, 0x9622),	/* DM9622 USB to Fast Ethernet Adapter */
+ 	 .driver_info = (unsigned long)&dm9601_info,
+ 	},
+ 	{
+ 	 USB_DEVICE(0x0a46, 0x0269),	/* DM962OA USB to Fast Ethernet Adapter */
+ 	 .driver_info = (unsigned long)&dm9601_info,
+ 	},
+ 	{
+ 	 USB_DEVICE(0x0a46, 0x1269),	/* DM9621A USB to Fast Ethernet Adapter */
+ 	 .driver_info = (unsigned long)&dm9601_info,
+ 	},
  	{},			// END
  };
  
diff --combined include/net/if_inet6.h
index b58c36c,65bb130..9650a3f
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@@ -50,8 -50,8 +50,8 @@@ struct inet6_ifaddr 
  
  	int			state;
  
 +	__u32			flags;
  	__u8			dad_probes;
 -	__u8			flags;
  
  	__u16			scope;
  
@@@ -165,7 -165,6 +165,6 @@@ struct inet6_dev 
  	struct net_device	*dev;
  
  	struct list_head	addr_list;
- 	int			valid_ll_addr_cnt;
  
  	struct ifmcaddr6	*mc_list;
  	struct ifmcaddr6	*mc_tomb;
diff --combined net/batman-adv/main.c
index e56b4d6,faba0f6..66ae135
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@@ -1,4 -1,4 +1,4 @@@
 -/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors:
 +/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
   *
   * Marek Lindner, Simon Wunderlich
   *
@@@ -12,7 -12,9 +12,7 @@@
   * 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., 51 Franklin Street, Fifth Floor, Boston, MA
 - * 02110-1301, USA
 + * along with this program; if not, see <http://www.gnu.org/licenses/>.
   */
  
  #include <linux/crc32c.h>
@@@ -275,7 -277,7 +275,7 @@@ int batadv_max_header_len(void
  			   sizeof(struct batadv_coded_packet));
  #endif
  
- 	return header_len;
+ 	return header_len + ETH_HLEN;
  }
  
  /**
@@@ -419,23 -421,13 +419,23 @@@ static void batadv_recv_handler_init(vo
  	for (i = BATADV_UNICAST_MIN; i <= BATADV_UNICAST_MAX; i++)
  		batadv_rx_handler[i] = batadv_recv_unhandled_unicast_packet;
  
 -	/* compile time checks for struct member offsets */
 -	BUILD_BUG_ON(offsetof(struct batadv_unicast_4addr_packet, src) != 10);
 -	BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
 -	BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
 -	BUILD_BUG_ON(offsetof(struct batadv_frag_packet, dest) != 4);
 -	BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4);
 -	BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4);
 +	/* compile time checks for sizes */
 +	BUILD_BUG_ON(sizeof(struct batadv_bla_claim_dst) != 6);
 +	BUILD_BUG_ON(sizeof(struct batadv_ogm_packet) != 24);
 +	BUILD_BUG_ON(sizeof(struct batadv_icmp_header) != 20);
 +	BUILD_BUG_ON(sizeof(struct batadv_icmp_packet) != 20);
 +	BUILD_BUG_ON(sizeof(struct batadv_icmp_packet_rr) != 116);
 +	BUILD_BUG_ON(sizeof(struct batadv_unicast_packet) != 10);
 +	BUILD_BUG_ON(sizeof(struct batadv_unicast_4addr_packet) != 18);
 +	BUILD_BUG_ON(sizeof(struct batadv_frag_packet) != 20);
 +	BUILD_BUG_ON(sizeof(struct batadv_bcast_packet) != 14);
 +	BUILD_BUG_ON(sizeof(struct batadv_coded_packet) != 46);
 +	BUILD_BUG_ON(sizeof(struct batadv_unicast_tvlv_packet) != 20);
 +	BUILD_BUG_ON(sizeof(struct batadv_tvlv_hdr) != 4);
 +	BUILD_BUG_ON(sizeof(struct batadv_tvlv_gateway_data) != 8);
 +	BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_vlan_data) != 8);
 +	BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_change) != 12);
 +	BUILD_BUG_ON(sizeof(struct batadv_tvlv_roam_adv) != 8);
  
  	/* broadcast packet */
  	batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
@@@ -1181,32 -1173,6 +1181,32 @@@ unsigned short batadv_get_vid(struct sk
  	return vid;
  }
  
 +/**
 + * batadv_vlan_ap_isola_get - return the AP isolation status for the given vlan
 + * @bat_priv: the bat priv with all the soft interface information
 + * @vid: the VLAN identifier for which the AP isolation attributed as to be
 + *  looked up
 + *
 + * Returns true if AP isolation is on for the VLAN idenfied by vid, false
 + * otherwise
 + */
 +bool batadv_vlan_ap_isola_get(struct batadv_priv *bat_priv, unsigned short vid)
 +{
 +	bool ap_isolation_enabled = false;
 +	struct batadv_softif_vlan *vlan;
 +
 +	/* if the AP isolation is requested on a VLAN, then check for its
 +	 * setting in the proper VLAN private data structure
 +	 */
 +	vlan = batadv_softif_vlan_get(bat_priv, vid);
 +	if (vlan) {
 +		ap_isolation_enabled = atomic_read(&vlan->ap_isolation);
 +		batadv_softif_vlan_free_ref(vlan);
 +	}
 +
 +	return ap_isolation_enabled;
 +}
 +
  static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
  {
  	struct batadv_algo_ops *bat_algo_ops;
diff --combined net/ipv4/ipmr.c
index 421a249,1672409..b9b3472
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@@ -157,9 -157,12 +157,12 @@@ static struct mr_table *ipmr_get_table(
  static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
  			   struct mr_table **mrt)
  {
- 	struct ipmr_result res;
- 	struct fib_lookup_arg arg = { .result = &res, };
  	int err;
+ 	struct ipmr_result res;
+ 	struct fib_lookup_arg arg = {
+ 		.result = &res,
+ 		.flags = FIB_LOOKUP_NOREF,
+ 	};
  
  	err = fib_rules_lookup(net->ipv4.mr_rules_ops,
  			       flowi4_to_flowi(flp4), 0, &arg);
@@@ -425,7 -428,6 +428,7 @@@ struct net_device *ipmr_new_tunnel(stru
  				goto failure;
  
  			ipv4_devconf_setall(in_dev);
 +			neigh_parms_data_state_setall(in_dev->arp_parms);
  			IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
  
  			if (dev_open(dev))
@@@ -518,7 -520,6 +521,7 @@@ static struct net_device *ipmr_reg_vif(
  	}
  
  	ipv4_devconf_setall(in_dev);
 +	neigh_parms_data_state_setall(in_dev->arp_parms);
  	IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
  	rcu_read_unlock();
  
diff --combined net/ipv4/tcp_metrics.c
index 699a42f,098b3a2..fa95094
--- a/net/ipv4/tcp_metrics.c
+++ b/net/ipv4/tcp_metrics.c
@@@ -22,6 -22,9 +22,10 @@@
  
  int sysctl_tcp_nometrics_save __read_mostly;
  
 -static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *addr,
++static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *saddr,
++						   const struct inetpeer_addr *daddr,
+ 						   struct net *net, unsigned int hash);
+ 
  struct tcp_fastopen_metrics {
  	u16	mss;
  	u16	syn_loss:10;		/* Recurring Fast Open SYN losses */
@@@ -31,8 -34,7 +35,8 @@@
  
  struct tcp_metrics_block {
  	struct tcp_metrics_block __rcu	*tcpm_next;
 -	struct inetpeer_addr		tcpm_addr;
 +	struct inetpeer_addr		tcpm_saddr;
 +	struct inetpeer_addr		tcpm_daddr;
  	unsigned long			tcpm_stamp;
  	u32				tcpm_ts;
  	u32				tcpm_ts_stamp;
@@@ -131,17 -133,41 +135,42 @@@ static void tcpm_suck_dst(struct tcp_me
  	}
  }
  
+ #define TCP_METRICS_TIMEOUT		(60 * 60 * HZ)
+ 
+ static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst)
+ {
+ 	if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT)))
+ 		tcpm_suck_dst(tm, dst, false);
+ }
+ 
+ #define TCP_METRICS_RECLAIM_DEPTH	5
+ #define TCP_METRICS_RECLAIM_PTR		(struct tcp_metrics_block *) 0x1UL
+ 
  static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
 -					  struct inetpeer_addr *addr,
 +					  struct inetpeer_addr *saddr,
 +					  struct inetpeer_addr *daddr,
- 					  unsigned int hash,
- 					  bool reclaim)
+ 					  unsigned int hash)
  {
  	struct tcp_metrics_block *tm;
  	struct net *net;
+ 	bool reclaim = false;
  
  	spin_lock_bh(&tcp_metrics_lock);
  	net = dev_net(dst->dev);
+ 
+ 	/* While waiting for the spin-lock the cache might have been populated
+ 	 * with this entry and so we have to check again.
+ 	 */
 -	tm = __tcp_get_metrics(addr, net, hash);
++	tm = __tcp_get_metrics(saddr, daddr, net, hash);
+ 	if (tm == TCP_METRICS_RECLAIM_PTR) {
+ 		reclaim = true;
+ 		tm = NULL;
+ 	}
+ 	if (tm) {
+ 		tcpm_check_stamp(tm, dst);
+ 		goto out_unlock;
+ 	}
+ 
  	if (unlikely(reclaim)) {
  		struct tcp_metrics_block *oldest;
  
@@@ -157,8 -183,7 +186,8 @@@
  		if (!tm)
  			goto out_unlock;
  	}
 -	tm->tcpm_addr = *addr;
 +	tm->tcpm_saddr = *saddr;
 +	tm->tcpm_daddr = *daddr;
  
  	tcpm_suck_dst(tm, dst, true);
  
@@@ -172,17 -197,6 +201,6 @@@ out_unlock
  	return tm;
  }
  
- #define TCP_METRICS_TIMEOUT		(60 * 60 * HZ)
- 
- static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst)
- {
- 	if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT)))
- 		tcpm_suck_dst(tm, dst, false);
- }
- 
- #define TCP_METRICS_RECLAIM_DEPTH	5
- #define TCP_METRICS_RECLAIM_PTR		(struct tcp_metrics_block *) 0x1UL
- 
  static struct tcp_metrics_block *tcp_get_encode(struct tcp_metrics_block *tm, int depth)
  {
  	if (tm)
@@@ -192,8 -206,7 +210,8 @@@
  	return NULL;
  }
  
 -static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *addr,
 +static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *saddr,
 +						   const struct inetpeer_addr *daddr,
  						   struct net *net, unsigned int hash)
  {
  	struct tcp_metrics_block *tm;
@@@ -201,8 -214,7 +219,8 @@@
  
  	for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
  	     tm = rcu_dereference(tm->tcpm_next)) {
 -		if (addr_same(&tm->tcpm_addr, addr))
 +		if (addr_same(&tm->tcpm_saddr, saddr) &&
 +		    addr_same(&tm->tcpm_daddr, daddr))
  			break;
  		depth++;
  	}
@@@ -213,22 -225,19 +231,22 @@@ static struct tcp_metrics_block *__tcp_
  						       struct dst_entry *dst)
  {
  	struct tcp_metrics_block *tm;
 -	struct inetpeer_addr addr;
 +	struct inetpeer_addr saddr, daddr;
  	unsigned int hash;
  	struct net *net;
  
 -	addr.family = req->rsk_ops->family;
 -	switch (addr.family) {
 +	saddr.family = req->rsk_ops->family;
 +	daddr.family = req->rsk_ops->family;
 +	switch (daddr.family) {
  	case AF_INET:
 -		addr.addr.a4 = inet_rsk(req)->ir_rmt_addr;
 -		hash = (__force unsigned int) addr.addr.a4;
 +		saddr.addr.a4 = inet_rsk(req)->ir_loc_addr;
 +		daddr.addr.a4 = inet_rsk(req)->ir_rmt_addr;
 +		hash = (__force unsigned int) daddr.addr.a4;
  		break;
  #if IS_ENABLED(CONFIG_IPV6)
  	case AF_INET6:
 -		*(struct in6_addr *)addr.addr.a6 = inet_rsk(req)->ir_v6_rmt_addr;
 +		*(struct in6_addr *)saddr.addr.a6 = inet_rsk(req)->ir_v6_loc_addr;
 +		*(struct in6_addr *)daddr.addr.a6 = inet_rsk(req)->ir_v6_rmt_addr;
  		hash = ipv6_addr_hash(&inet_rsk(req)->ir_v6_rmt_addr);
  		break;
  #endif
@@@ -241,8 -250,7 +259,8 @@@
  
  	for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
  	     tm = rcu_dereference(tm->tcpm_next)) {
 -		if (addr_same(&tm->tcpm_addr, &addr))
 +		if (addr_same(&tm->tcpm_saddr, &saddr) &&
 +		    addr_same(&tm->tcpm_daddr, &daddr))
  			break;
  	}
  	tcpm_check_stamp(tm, dst);
@@@ -252,22 -260,19 +270,22 @@@
  static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock *tw)
  {
  	struct tcp_metrics_block *tm;
 -	struct inetpeer_addr addr;
 +	struct inetpeer_addr saddr, daddr;
  	unsigned int hash;
  	struct net *net;
  
 -	addr.family = tw->tw_family;
 -	switch (addr.family) {
 +	saddr.family = tw->tw_family;
 +	daddr.family = tw->tw_family;
 +	switch (daddr.family) {
  	case AF_INET:
 -		addr.addr.a4 = tw->tw_daddr;
 -		hash = (__force unsigned int) addr.addr.a4;
 +		saddr.addr.a4 = tw->tw_rcv_saddr;
 +		daddr.addr.a4 = tw->tw_daddr;
 +		hash = (__force unsigned int) daddr.addr.a4;
  		break;
  #if IS_ENABLED(CONFIG_IPV6)
  	case AF_INET6:
 -		*(struct in6_addr *)addr.addr.a6 = tw->tw_v6_daddr;
 +		*(struct in6_addr *)saddr.addr.a6 = tw->tw_v6_rcv_saddr;
 +		*(struct in6_addr *)daddr.addr.a6 = tw->tw_v6_daddr;
  		hash = ipv6_addr_hash(&tw->tw_v6_daddr);
  		break;
  #endif
@@@ -280,8 -285,7 +298,8 @@@
  
  	for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
  	     tm = rcu_dereference(tm->tcpm_next)) {
 -		if (addr_same(&tm->tcpm_addr, &addr))
 +		if (addr_same(&tm->tcpm_saddr, &saddr) &&
 +		    addr_same(&tm->tcpm_daddr, &daddr))
  			break;
  	}
  	return tm;
@@@ -292,23 -296,19 +310,22 @@@ static struct tcp_metrics_block *tcp_ge
  						 bool create)
  {
  	struct tcp_metrics_block *tm;
 -	struct inetpeer_addr addr;
 +	struct inetpeer_addr saddr, daddr;
  	unsigned int hash;
  	struct net *net;
- 	bool reclaim;
  
 -	addr.family = sk->sk_family;
 -	switch (addr.family) {
 +	saddr.family = sk->sk_family;
 +	daddr.family = sk->sk_family;
 +	switch (daddr.family) {
  	case AF_INET:
 -		addr.addr.a4 = inet_sk(sk)->inet_daddr;
 -		hash = (__force unsigned int) addr.addr.a4;
 +		saddr.addr.a4 = inet_sk(sk)->inet_saddr;
 +		daddr.addr.a4 = inet_sk(sk)->inet_daddr;
 +		hash = (__force unsigned int) daddr.addr.a4;
  		break;
  #if IS_ENABLED(CONFIG_IPV6)
  	case AF_INET6:
 -		*(struct in6_addr *)addr.addr.a6 = sk->sk_v6_daddr;
 +		*(struct in6_addr *)saddr.addr.a6 = sk->sk_v6_rcv_saddr;
 +		*(struct in6_addr *)daddr.addr.a6 = sk->sk_v6_daddr;
  		hash = ipv6_addr_hash(&sk->sk_v6_daddr);
  		break;
  #endif
@@@ -319,14 -319,11 +336,11 @@@
  	net = dev_net(dst->dev);
  	hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
  
 -	tm = __tcp_get_metrics(&addr, net, hash);
 +	tm = __tcp_get_metrics(&saddr, &daddr, net, hash);
- 	reclaim = false;
- 	if (tm == TCP_METRICS_RECLAIM_PTR) {
- 		reclaim = true;
+ 	if (tm == TCP_METRICS_RECLAIM_PTR)
  		tm = NULL;
- 	}
  	if (!tm && create)
- 		tm = tcpm_new(dst, &saddr, &daddr, hash, reclaim);
 -		tm = tcpm_new(dst, &addr, hash);
++		tm = tcpm_new(dst, &saddr, &daddr, hash);
  	else
  		tcpm_check_stamp(tm, dst);
  
@@@ -740,21 -737,15 +754,21 @@@ static int tcp_metrics_fill_info(struc
  	struct nlattr *nest;
  	int i;
  
 -	switch (tm->tcpm_addr.family) {
 +	switch (tm->tcpm_daddr.family) {
  	case AF_INET:
  		if (nla_put_be32(msg, TCP_METRICS_ATTR_ADDR_IPV4,
 -				tm->tcpm_addr.addr.a4) < 0)
 +				tm->tcpm_daddr.addr.a4) < 0)
 +			goto nla_put_failure;
 +		if (nla_put_be32(msg, TCP_METRICS_ATTR_SADDR_IPV4,
 +				tm->tcpm_saddr.addr.a4) < 0)
  			goto nla_put_failure;
  		break;
  	case AF_INET6:
  		if (nla_put(msg, TCP_METRICS_ATTR_ADDR_IPV6, 16,
 -			    tm->tcpm_addr.addr.a6) < 0)
 +			    tm->tcpm_daddr.addr.a6) < 0)
 +			goto nla_put_failure;
 +		if (nla_put(msg, TCP_METRICS_ATTR_SADDR_IPV6, 16,
 +			    tm->tcpm_saddr.addr.a6) < 0)
  			goto nla_put_failure;
  		break;
  	default:
@@@ -877,66 -868,44 +891,66 @@@ done
  	return skb->len;
  }
  
 -static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
 -			 unsigned int *hash, int optional)
 +static int __parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
 +			   unsigned int *hash, int optional, int v4, int v6)
  {
  	struct nlattr *a;
  
 -	a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV4];
 +	a = info->attrs[v4];
  	if (a) {
  		addr->family = AF_INET;
  		addr->addr.a4 = nla_get_be32(a);
 -		*hash = (__force unsigned int) addr->addr.a4;
 +		if (hash)
 +			*hash = (__force unsigned int) addr->addr.a4;
  		return 0;
  	}
 -	a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6];
 +	a = info->attrs[v6];
  	if (a) {
  		if (nla_len(a) != sizeof(struct in6_addr))
  			return -EINVAL;
  		addr->family = AF_INET6;
  		memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6));
 -		*hash = ipv6_addr_hash((struct in6_addr *) addr->addr.a6);
 +		if (hash)
 +			*hash = ipv6_addr_hash((struct in6_addr *) addr->addr.a6);
  		return 0;
  	}
  	return optional ? 1 : -EAFNOSUPPORT;
  }
  
 +static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
 +			 unsigned int *hash, int optional)
 +{
 +	return __parse_nl_addr(info, addr, hash, optional,
 +			       TCP_METRICS_ATTR_ADDR_IPV4,
 +			       TCP_METRICS_ATTR_ADDR_IPV6);
 +}
 +
 +static int parse_nl_saddr(struct genl_info *info, struct inetpeer_addr *addr)
 +{
 +	return __parse_nl_addr(info, addr, NULL, 0,
 +			       TCP_METRICS_ATTR_SADDR_IPV4,
 +			       TCP_METRICS_ATTR_SADDR_IPV6);
 +}
 +
  static int tcp_metrics_nl_cmd_get(struct sk_buff *skb, struct genl_info *info)
  {
  	struct tcp_metrics_block *tm;
 -	struct inetpeer_addr addr;
 +	struct inetpeer_addr saddr, daddr;
  	unsigned int hash;
  	struct sk_buff *msg;
  	struct net *net = genl_info_net(info);
  	void *reply;
  	int ret;
 +	bool src = true;
  
 -	ret = parse_nl_addr(info, &addr, &hash, 0);
 +	ret = parse_nl_addr(info, &daddr, &hash, 0);
  	if (ret < 0)
  		return ret;
  
 +	ret = parse_nl_saddr(info, &saddr);
 +	if (ret < 0)
 +		src = false;
 +
  	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  	if (!msg)
  		return -ENOMEM;
@@@ -951,8 -920,7 +965,8 @@@
  	rcu_read_lock();
  	for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
  	     tm = rcu_dereference(tm->tcpm_next)) {
 -		if (addr_same(&tm->tcpm_addr, &addr)) {
 +		if (addr_same(&tm->tcpm_daddr, &daddr) &&
 +		    (!src || addr_same(&tm->tcpm_saddr, &saddr))) {
  			ret = tcp_metrics_fill_info(msg, tm);
  			break;
  		}
@@@ -1005,44 -973,34 +1019,44 @@@ static int tcp_metrics_flush_all(struc
  static int tcp_metrics_nl_cmd_del(struct sk_buff *skb, struct genl_info *info)
  {
  	struct tcpm_hash_bucket *hb;
 -	struct tcp_metrics_block *tm;
 +	struct tcp_metrics_block *tm, *tmlist = NULL;
  	struct tcp_metrics_block __rcu **pp;
 -	struct inetpeer_addr addr;
 +	struct inetpeer_addr saddr, daddr;
  	unsigned int hash;
  	struct net *net = genl_info_net(info);
  	int ret;
 +	bool src = true;
  
 -	ret = parse_nl_addr(info, &addr, &hash, 1);
 +	ret = parse_nl_addr(info, &daddr, &hash, 1);
  	if (ret < 0)
  		return ret;
  	if (ret > 0)
  		return tcp_metrics_flush_all(net);
 +	ret = parse_nl_saddr(info, &saddr);
 +	if (ret < 0)
 +		src = false;
  
  	hash = hash_32(hash, net->ipv4.tcp_metrics_hash_log);
  	hb = net->ipv4.tcp_metrics_hash + hash;
  	pp = &hb->chain;
  	spin_lock_bh(&tcp_metrics_lock);
 -	for (tm = deref_locked_genl(*pp); tm;
 -	     pp = &tm->tcpm_next, tm = deref_locked_genl(*pp)) {
 -		if (addr_same(&tm->tcpm_addr, &addr)) {
 +	for (tm = deref_locked_genl(*pp); tm; tm = deref_locked_genl(*pp)) {
 +		if (addr_same(&tm->tcpm_daddr, &daddr) &&
 +		    (!src || addr_same(&tm->tcpm_saddr, &saddr))) {
  			*pp = tm->tcpm_next;
 -			break;
 +			tm->tcpm_next = tmlist;
 +			tmlist = tm;
 +		} else {
 +			pp = &tm->tcpm_next;
  		}
  	}
  	spin_unlock_bh(&tcp_metrics_lock);
 -	if (!tm)
 +	if (!tmlist)
  		return -ESRCH;
 -	kfree_rcu(tm, rcu_head);
 +	for (tm = tmlist; tm; tm = tmlist) {
 +		tmlist = tm->tcpm_next;
 +		kfree_rcu(tm, rcu_head);
 +	}
  	return 0;
  }
  
diff --combined net/ipv6/addrconf.c
index 6913a82,4b6b720..f91e107
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@@ -442,8 -442,6 +442,8 @@@ static int inet6_netconf_msgsize_devcon
  	if (type == -1 || type == NETCONFA_MC_FORWARDING)
  		size += nla_total_size(4);
  #endif
 +	if (type == -1 || type == NETCONFA_PROXY_NEIGH)
 +		size += nla_total_size(4);
  
  	return size;
  }
@@@ -477,10 -475,6 +477,10 @@@ static int inet6_netconf_fill_devconf(s
  			devconf->mc_forwarding) < 0)
  		goto nla_put_failure;
  #endif
 +	if ((type == -1 || type == NETCONFA_PROXY_NEIGH) &&
 +	    nla_put_s32(skb, NETCONFA_PROXY_NEIGH, devconf->proxy_ndp) < 0)
 +		goto nla_put_failure;
 +
  	return nlmsg_end(skb, nlh);
  
  nla_put_failure:
@@@ -515,7 -509,6 +515,7 @@@ errout
  static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
  	[NETCONFA_IFINDEX]	= { .len = sizeof(int) },
  	[NETCONFA_FORWARDING]	= { .len = sizeof(int) },
 +	[NETCONFA_PROXY_NEIGH]	= { .len = sizeof(int) },
  };
  
  static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
@@@ -841,8 -834,6 +841,8 @@@ ipv6_add_addr(struct inet6_dev *idev, c
  		goto out;
  	}
  
 +	neigh_parms_data_state_setall(idev->nd_parms);
 +
  	ifa->addr = *addr;
  	if (peer_addr)
  		ifa->peer_addr = *peer_addr;
@@@ -900,95 -891,15 +900,95 @@@ out
  	goto out2;
  }
  
 +enum cleanup_prefix_rt_t {
 +	CLEANUP_PREFIX_RT_NOP,    /* no cleanup action for prefix route */
 +	CLEANUP_PREFIX_RT_DEL,    /* delete the prefix route */
 +	CLEANUP_PREFIX_RT_EXPIRE, /* update the lifetime of the prefix route */
 +};
 +
 +/*
 + * Check, whether the prefix for ifp would still need a prefix route
 + * after deleting ifp. The function returns one of the CLEANUP_PREFIX_RT_*
 + * constants.
 + *
 + * 1) we don't purge prefix if address was not permanent.
 + *    prefix is managed by its own lifetime.
 + * 2) we also don't purge, if the address was IFA_F_NOPREFIXROUTE.
 + * 3) if there are no addresses, delete prefix.
 + * 4) if there are still other permanent address(es),
 + *    corresponding prefix is still permanent.
 + * 5) if there are still other addresses with IFA_F_NOPREFIXROUTE,
 + *    don't purge the prefix, assume user space is managing it.
 + * 6) otherwise, update prefix lifetime to the
 + *    longest valid lifetime among the corresponding
 + *    addresses on the device.
 + *    Note: subsequent RA will update lifetime.
 + **/
 +static enum cleanup_prefix_rt_t
 +check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires)
 +{
 +	struct inet6_ifaddr *ifa;
 +	struct inet6_dev *idev = ifp->idev;
 +	unsigned long lifetime;
 +	enum cleanup_prefix_rt_t action = CLEANUP_PREFIX_RT_DEL;
 +
 +	*expires = jiffies;
 +
 +	list_for_each_entry(ifa, &idev->addr_list, if_list) {
 +		if (ifa == ifp)
 +			continue;
 +		if (!ipv6_prefix_equal(&ifa->addr, &ifp->addr,
 +				       ifp->prefix_len))
 +			continue;
 +		if (ifa->flags & (IFA_F_PERMANENT | IFA_F_NOPREFIXROUTE))
 +			return CLEANUP_PREFIX_RT_NOP;
 +
 +		action = CLEANUP_PREFIX_RT_EXPIRE;
 +
 +		spin_lock(&ifa->lock);
 +
 +		lifetime = addrconf_timeout_fixup(ifa->valid_lft, HZ);
 +		/*
 +		 * Note: Because this address is
 +		 * not permanent, lifetime <
 +		 * LONG_MAX / HZ here.
 +		 */
 +		if (time_before(*expires, ifa->tstamp + lifetime * HZ))
 +			*expires = ifa->tstamp + lifetime * HZ;
 +		spin_unlock(&ifa->lock);
 +	}
 +
 +	return action;
 +}
 +
 +static void
 +cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires, bool del_rt)
 +{
 +	struct rt6_info *rt;
 +
 +	rt = addrconf_get_prefix_route(&ifp->addr,
 +				       ifp->prefix_len,
 +				       ifp->idev->dev,
 +				       0, RTF_GATEWAY | RTF_DEFAULT);
 +	if (rt) {
 +		if (del_rt)
 +			ip6_del_rt(rt);
 +		else {
 +			if (!(rt->rt6i_flags & RTF_EXPIRES))
 +				rt6_set_expires(rt, expires);
 +			ip6_rt_put(rt);
 +		}
 +	}
 +}
 +
 +
  /* This function wants to get referenced ifp and releases it before return */
  
  static void ipv6_del_addr(struct inet6_ifaddr *ifp)
  {
 -	struct inet6_ifaddr *ifa, *ifn;
 -	struct inet6_dev *idev = ifp->idev;
  	int state;
 -	int deleted = 0, onlink = 0;
 -	unsigned long expires = jiffies;
 +	enum cleanup_prefix_rt_t action = CLEANUP_PREFIX_RT_NOP;
 +	unsigned long expires;
  
  	spin_lock_bh(&ifp->state_lock);
  	state = ifp->state;
@@@ -1002,7 -913,7 +1002,7 @@@
  	hlist_del_init_rcu(&ifp->addr_lst);
  	spin_unlock_bh(&addrconf_hash_lock);
  
 -	write_lock_bh(&idev->lock);
 +	write_lock_bh(&ifp->idev->lock);
  
  	if (ifp->flags&IFA_F_TEMPORARY) {
  		list_del(&ifp->tmp_list);
@@@ -1013,13 -924,45 +1013,13 @@@
  		__in6_ifa_put(ifp);
  	}
  
 -	list_for_each_entry_safe(ifa, ifn, &idev->addr_list, if_list) {
 -		if (ifa == ifp) {
 -			list_del_init(&ifp->if_list);
 -			__in6_ifa_put(ifp);
 +	if (ifp->flags & IFA_F_PERMANENT && !(ifp->flags & IFA_F_NOPREFIXROUTE))
 +		action = check_cleanup_prefix_route(ifp, &expires);
  
 -			if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0)
 -				break;
 -			deleted = 1;
 -			continue;
 -		} else if (ifp->flags & IFA_F_PERMANENT) {
 -			if (ipv6_prefix_equal(&ifa->addr, &ifp->addr,
 -					      ifp->prefix_len)) {
 -				if (ifa->flags & IFA_F_PERMANENT) {
 -					onlink = 1;
 -					if (deleted)
 -						break;
 -				} else {
 -					unsigned long lifetime;
 -
 -					if (!onlink)
 -						onlink = -1;
 -
 -					spin_lock(&ifa->lock);
 -
 -					lifetime = addrconf_timeout_fixup(ifa->valid_lft, HZ);
 -					/*
 -					 * Note: Because this address is
 -					 * not permanent, lifetime <
 -					 * LONG_MAX / HZ here.
 -					 */
 -					if (time_before(expires,
 -							ifa->tstamp + lifetime * HZ))
 -						expires = ifa->tstamp + lifetime * HZ;
 -					spin_unlock(&ifa->lock);
 -				}
 -			}
 -		}
 -	}
 -	write_unlock_bh(&idev->lock);
 +	list_del_init(&ifp->if_list);
 +	__in6_ifa_put(ifp);
 +
 +	write_unlock_bh(&ifp->idev->lock);
  
  	addrconf_del_dad_timer(ifp);
  
@@@ -1027,9 -970,41 +1027,9 @@@
  
  	inet6addr_notifier_call_chain(NETDEV_DOWN, ifp);
  
 -	/*
 -	 * Purge or update corresponding prefix
 -	 *
 -	 * 1) we don't purge prefix here if address was not permanent.
 -	 *    prefix is managed by its own lifetime.
 -	 * 2) if there're no addresses, delete prefix.
 -	 * 3) if there're still other permanent address(es),
 -	 *    corresponding prefix is still permanent.
 -	 * 4) otherwise, update prefix lifetime to the
 -	 *    longest valid lifetime among the corresponding
 -	 *    addresses on the device.
 -	 *    Note: subsequent RA will update lifetime.
 -	 *
 -	 * --yoshfuji
 -	 */
 -	if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) {
 -		struct in6_addr prefix;
 -		struct rt6_info *rt;
 -
 -		ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
 -
 -		rt = addrconf_get_prefix_route(&prefix,
 -					       ifp->prefix_len,
 -					       ifp->idev->dev,
 -					       0, RTF_GATEWAY | RTF_DEFAULT);
 -
 -		if (rt) {
 -			if (onlink == 0) {
 -				ip6_del_rt(rt);
 -				rt = NULL;
 -			} else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
 -				rt6_set_expires(rt, expires);
 -			}
 -		}
 -		ip6_rt_put(rt);
 +	if (action != CLEANUP_PREFIX_RT_NOP) {
 +		cleanup_prefix_route(ifp, expires,
 +			action == CLEANUP_PREFIX_RT_DEL);
  	}
  
  	/* clean up prefsrc entries */
@@@ -1049,7 -1024,7 +1049,7 @@@ static int ipv6_create_tempaddr(struct 
  	u32 addr_flags;
  	unsigned long now = jiffies;
  
 -	write_lock(&idev->lock);
 +	write_lock_bh(&idev->lock);
  	if (ift) {
  		spin_lock_bh(&ift->lock);
  		memcpy(&addr.s6_addr[8], &ift->addr.s6_addr[8], 8);
@@@ -1061,7 -1036,7 +1061,7 @@@
  retry:
  	in6_dev_hold(idev);
  	if (idev->cnf.use_tempaddr <= 0) {
 -		write_unlock(&idev->lock);
 +		write_unlock_bh(&idev->lock);
  		pr_info("%s: use_tempaddr is disabled\n", __func__);
  		in6_dev_put(idev);
  		ret = -1;
@@@ -1071,7 -1046,7 +1071,7 @@@
  	if (ifp->regen_count++ >= idev->cnf.regen_max_retry) {
  		idev->cnf.use_tempaddr = -1;	/*XXX*/
  		spin_unlock_bh(&ifp->lock);
 -		write_unlock(&idev->lock);
 +		write_unlock_bh(&idev->lock);
  		pr_warn("%s: regeneration time exceeded - disabled temporary address support\n",
  			__func__);
  		in6_dev_put(idev);
@@@ -1096,8 -1071,8 +1096,8 @@@
  
  	regen_advance = idev->cnf.regen_max_retry *
  	                idev->cnf.dad_transmits *
 -	                idev->nd_parms->retrans_time / HZ;
 -	write_unlock(&idev->lock);
 +	                NEIGH_VAR(idev->nd_parms, RETRANS_TIME) / HZ;
 +	write_unlock_bh(&idev->lock);
  
  	/* A temporary address is created only if this calculated Preferred
  	 * Lifetime is greater than REGEN_ADVANCE time units.  In particular,
@@@ -1124,7 -1099,7 +1124,7 @@@
  		in6_dev_put(idev);
  		pr_info("%s: retry temporary address regeneration\n", __func__);
  		tmpaddr = &addr;
 -		write_lock(&idev->lock);
 +		write_lock_bh(&idev->lock);
  		goto retry;
  	}
  
@@@ -1225,7 -1200,7 +1225,7 @@@ static int ipv6_get_saddr_eval(struct n
  		 *       |             d is scope of the destination.
  		 *  B-d  |  \
  		 *       |   \      <- smaller scope is better if
 -		 *  B-15 |    \        if scope is enough for destinaion.
 +		 *  B-15 |    \        if scope is enough for destination.
  		 *       |             ret = B - scope (-1 <= scope >= d <= 15).
  		 * d-C-1 | /
  		 *       |/         <- greater is better
@@@ -1432,7 -1407,7 +1432,7 @@@ try_nextdev
  EXPORT_SYMBOL(ipv6_dev_get_saddr);
  
  int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
 -		      unsigned char banned_flags)
 +		      u32 banned_flags)
  {
  	struct inet6_ifaddr *ifp;
  	int err = -EADDRNOTAVAIL;
@@@ -1449,7 -1424,7 +1449,7 @@@
  }
  
  int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
 -		    unsigned char banned_flags)
 +		    u32 banned_flags)
  {
  	struct inet6_dev *idev;
  	int err = -EADDRNOTAVAIL;
@@@ -1841,7 -1816,6 +1841,7 @@@ static int ipv6_generate_eui64(u8 *eui
  		return addrconf_ifid_sit(eui, dev);
  	case ARPHRD_IPGRE:
  		return addrconf_ifid_gre(eui, dev);
 +	case ARPHRD_6LOWPAN:
  	case ARPHRD_IEEE802154:
  		return addrconf_ifid_eui64(eui, dev);
  	case ARPHRD_IEEE1394:
@@@ -1914,8 -1888,7 +1914,8 @@@ static void ipv6_regen_rndid(unsigned l
  
  	expires = jiffies +
  		idev->cnf.temp_prefered_lft * HZ -
 -		idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time -
 +		idev->cnf.regen_max_retry * idev->cnf.dad_transmits *
 +		NEIGH_VAR(idev->nd_parms, RETRANS_TIME) -
  		idev->cnf.max_desync_factor * HZ;
  	if (time_before(expires, jiffies)) {
  		pr_warn("%s: too short regeneration interval; timer disabled for %s\n",
@@@ -2043,73 -2016,6 +2043,73 @@@ static struct inet6_dev *addrconf_add_d
  	return idev;
  }
  
 +static void manage_tempaddrs(struct inet6_dev *idev,
 +			     struct inet6_ifaddr *ifp,
 +			     __u32 valid_lft, __u32 prefered_lft,
 +			     bool create, unsigned long now)
 +{
 +	u32 flags;
 +	struct inet6_ifaddr *ift;
 +
 +	read_lock_bh(&idev->lock);
 +	/* update all temporary addresses in the list */
 +	list_for_each_entry(ift, &idev->tempaddr_list, tmp_list) {
 +		int age, max_valid, max_prefered;
 +
 +		if (ifp != ift->ifpub)
 +			continue;
 +
 +		/* RFC 4941 section 3.3:
 +		 * If a received option will extend the lifetime of a public
 +		 * address, the lifetimes of temporary addresses should
 +		 * be extended, subject to the overall constraint that no
 +		 * temporary addresses should ever remain "valid" or "preferred"
 +		 * for a time longer than (TEMP_VALID_LIFETIME) or
 +		 * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR), respectively.
 +		 */
 +		age = (now - ift->cstamp) / HZ;
 +		max_valid = idev->cnf.temp_valid_lft - age;
 +		if (max_valid < 0)
 +			max_valid = 0;
 +
 +		max_prefered = idev->cnf.temp_prefered_lft -
 +			       idev->cnf.max_desync_factor - age;
 +		if (max_prefered < 0)
 +			max_prefered = 0;
 +
 +		if (valid_lft > max_valid)
 +			valid_lft = max_valid;
 +
 +		if (prefered_lft > max_prefered)
 +			prefered_lft = max_prefered;
 +
 +		spin_lock(&ift->lock);
 +		flags = ift->flags;
 +		ift->valid_lft = valid_lft;
 +		ift->prefered_lft = prefered_lft;
 +		ift->tstamp = now;
 +		if (prefered_lft > 0)
 +			ift->flags &= ~IFA_F_DEPRECATED;
 +
 +		spin_unlock(&ift->lock);
 +		if (!(flags&IFA_F_TENTATIVE))
 +			ipv6_ifa_notify(0, ift);
 +	}
 +
 +	if ((create || list_empty(&idev->tempaddr_list)) &&
 +	    idev->cnf.use_tempaddr > 0) {
 +		/* When a new public address is created as described
 +		 * in [ADDRCONF], also create a new temporary address.
 +		 * Also create a temporary address if it's enabled but
 +		 * no temporary address currently exists.
 +		 */
 +		read_unlock_bh(&idev->lock);
 +		ipv6_create_tempaddr(ifp, NULL);
 +	} else {
 +		read_unlock_bh(&idev->lock);
 +	}
 +}
 +
  void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
  {
  	struct prefix_info *pinfo;
@@@ -2264,7 -2170,6 +2264,7 @@@ ok
  				return;
  			}
  
 +			ifp->flags |= IFA_F_MANAGETEMPADDR;
  			update_lft = 0;
  			create = 1;
  			ifp->cstamp = jiffies;
@@@ -2273,8 -2178,9 +2273,8 @@@
  		}
  
  		if (ifp) {
 -			int flags;
 +			u32 flags;
  			unsigned long now;
 -			struct inet6_ifaddr *ift;
  			u32 stored_lft;
  
  			/* update lifetime (RFC2462 5.5.3 e) */
@@@ -2315,8 -2221,70 +2315,8 @@@
  			} else
  				spin_unlock(&ifp->lock);
  
 -			read_lock_bh(&in6_dev->lock);
 -			/* update all temporary addresses in the list */
 -			list_for_each_entry(ift, &in6_dev->tempaddr_list,
 -					    tmp_list) {
 -				int age, max_valid, max_prefered;
 -
 -				if (ifp != ift->ifpub)
 -					continue;
 -
 -				/*
 -				 * RFC 4941 section 3.3:
 -				 * If a received option will extend the lifetime
 -				 * of a public address, the lifetimes of
 -				 * temporary addresses should be extended,
 -				 * subject to the overall constraint that no
 -				 * temporary addresses should ever remain
 -				 * "valid" or "preferred" for a time longer than
 -				 * (TEMP_VALID_LIFETIME) or
 -				 * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR),
 -				 * respectively.
 -				 */
 -				age = (now - ift->cstamp) / HZ;
 -				max_valid = in6_dev->cnf.temp_valid_lft - age;
 -				if (max_valid < 0)
 -					max_valid = 0;
 -
 -				max_prefered = in6_dev->cnf.temp_prefered_lft -
 -					       in6_dev->cnf.max_desync_factor -
 -					       age;
 -				if (max_prefered < 0)
 -					max_prefered = 0;
 -
 -				if (valid_lft > max_valid)
 -					valid_lft = max_valid;
 -
 -				if (prefered_lft > max_prefered)
 -					prefered_lft = max_prefered;
 -
 -				spin_lock(&ift->lock);
 -				flags = ift->flags;
 -				ift->valid_lft = valid_lft;
 -				ift->prefered_lft = prefered_lft;
 -				ift->tstamp = now;
 -				if (prefered_lft > 0)
 -					ift->flags &= ~IFA_F_DEPRECATED;
 -
 -				spin_unlock(&ift->lock);
 -				if (!(flags&IFA_F_TENTATIVE))
 -					ipv6_ifa_notify(0, ift);
 -			}
 -
 -			if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) {
 -				/*
 -				 * When a new public address is created as
 -				 * described in [ADDRCONF], also create a new
 -				 * temporary address. Also create a temporary
 -				 * address if it's enabled but no temporary
 -				 * address currently exists.
 -				 */
 -				read_unlock_bh(&in6_dev->lock);
 -				ipv6_create_tempaddr(ifp, NULL);
 -			} else {
 -				read_unlock_bh(&in6_dev->lock);
 -			}
 +			manage_tempaddrs(in6_dev, ifp, valid_lft, prefered_lft,
 +					 create, now);
  
  			in6_ifa_put(ifp);
  			addrconf_verify(0);
@@@ -2395,11 -2363,10 +2395,11 @@@ err_exit
  /*
   *	Manual configuration of address on an interface
   */
 -static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx,
 +static int inet6_addr_add(struct net *net, int ifindex,
 +			  const struct in6_addr *pfx,
  			  const struct in6_addr *peer_pfx,
 -			  unsigned int plen, __u8 ifa_flags, __u32 prefered_lft,
 -			  __u32 valid_lft)
 +			  unsigned int plen, __u32 ifa_flags,
 +			  __u32 prefered_lft, __u32 valid_lft)
  {
  	struct inet6_ifaddr *ifp;
  	struct inet6_dev *idev;
@@@ -2418,9 -2385,6 +2418,9 @@@
  	if (!valid_lft || prefered_lft > valid_lft)
  		return -EINVAL;
  
 +	if (ifa_flags & IFA_F_MANAGETEMPADDR && plen != 64)
 +		return -EINVAL;
 +
  	dev = __dev_get_by_index(net, ifindex);
  	if (!dev)
  		return -ENODEV;
@@@ -2453,20 -2417,14 +2453,20 @@@
  			    valid_lft, prefered_lft);
  
  	if (!IS_ERR(ifp)) {
 -		addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
 -				      expires, flags);
 +		if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) {
 +			addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
 +					      expires, flags);
 +		}
 +
  		/*
  		 * Note that section 3.1 of RFC 4429 indicates
  		 * that the Optimistic flag should not be set for
  		 * manually configured addresses
  		 */
  		addrconf_dad_start(ifp);
 +		if (ifa_flags & IFA_F_MANAGETEMPADDR)
 +			manage_tempaddrs(idev, ifp, valid_lft, prefered_lft,
 +					 true, jiffies);
  		in6_ifa_put(ifp);
  		addrconf_verify(0);
  		return 0;
@@@ -2702,8 -2660,7 +2702,8 @@@ static void addrconf_dev_config(struct 
  	    (dev->type != ARPHRD_INFINIBAND) &&
  	    (dev->type != ARPHRD_IEEE802154) &&
  	    (dev->type != ARPHRD_IEEE1394) &&
 -	    (dev->type != ARPHRD_TUNNEL6)) {
 +	    (dev->type != ARPHRD_TUNNEL6) &&
 +	    (dev->type != ARPHRD_6LOWPAN)) {
  		/* Alas, we support only Ethernet autoconfiguration. */
  		return;
  	}
@@@ -2900,7 -2857,7 +2900,7 @@@ static int addrconf_notify(struct notif
  		}
  
  		/*
 -		 * MTU falled under IPV6_MIN_MTU.
 +		 * if MTU under IPV6_MIN_MTU.
  		 * Stop IPv6 on this interface.
  		 */
  
@@@ -3126,7 -3083,7 +3126,7 @@@ static void addrconf_dad_kick(struct in
  	if (ifp->flags & IFA_F_OPTIMISTIC)
  		rand_num = 0;
  	else
 -		rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1);
 +		rand_num = prandom_u32() % (idev->cnf.rtr_solicit_delay ? : 1);
  
  	ifp->dad_probes = idev->cnf.dad_transmits;
  	addrconf_mod_dad_timer(ifp, rand_num);
@@@ -3139,7 -3096,7 +3139,7 @@@ static void addrconf_dad_start(struct i
  
  	addrconf_join_solict(dev, &ifp->addr);
  
 -	net_srandom(ifp->addr.s6_addr32[3]);
 +	prandom_seed((__force u32) ifp->addr.s6_addr32[3]);
  
  	read_lock_bh(&idev->lock);
  	spin_lock(&ifp->lock);
@@@ -3221,8 -3178,7 +3221,8 @@@ static void addrconf_dad_timer(unsigne
  	}
  
  	ifp->dad_probes--;
 -	addrconf_mod_dad_timer(ifp, ifp->idev->nd_parms->retrans_time);
 +	addrconf_mod_dad_timer(ifp,
 +			       NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME));
  	spin_unlock(&ifp->lock);
  	write_unlock(&idev->lock);
  
@@@ -3233,6 -3189,22 +3233,22 @@@ out
  	in6_ifa_put(ifp);
  }
  
+ /* ifp->idev must be at least read locked */
+ static bool ipv6_lonely_lladdr(struct inet6_ifaddr *ifp)
+ {
+ 	struct inet6_ifaddr *ifpiter;
+ 	struct inet6_dev *idev = ifp->idev;
+ 
+ 	list_for_each_entry(ifpiter, &idev->addr_list, if_list) {
+ 		if (ifp != ifpiter && ifpiter->scope == IFA_LINK &&
+ 		    (ifpiter->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|
+ 				       IFA_F_OPTIMISTIC|IFA_F_DADFAILED)) ==
+ 		    IFA_F_PERMANENT)
+ 			return false;
+ 	}
+ 	return true;
+ }
+ 
  static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
  {
  	struct net_device *dev = ifp->idev->dev;
@@@ -3252,14 -3224,11 +3268,11 @@@
  	 */
  
  	read_lock_bh(&ifp->idev->lock);
- 	spin_lock(&ifp->lock);
- 	send_mld = ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL &&
- 		   ifp->idev->valid_ll_addr_cnt == 1;
+ 	send_mld = ifp->scope == IFA_LINK && ipv6_lonely_lladdr(ifp);
  	send_rs = send_mld &&
  		  ipv6_accept_ra(ifp->idev) &&
  		  ifp->idev->cnf.rtr_solicits > 0 &&
  		  (dev->flags&IFF_LOOPBACK) == 0;
- 	spin_unlock(&ifp->lock);
  	read_unlock_bh(&ifp->idev->lock);
  
  	/* While dad is in progress mld report's source address is in6_addrany.
@@@ -3402,7 -3371,7 +3415,7 @@@ static int if6_seq_show(struct seq_fil
  		   ifp->idev->dev->ifindex,
  		   ifp->prefix_len,
  		   ifp->scope,
 -		   ifp->flags,
 +		   (u8) ifp->flags,
  		   ifp->idev->dev->name);
  	return 0;
  }
@@@ -3549,7 -3518,7 +3562,7 @@@ restart
  				   !(ifp->flags&IFA_F_TENTATIVE)) {
  				unsigned long regen_advance = ifp->idev->cnf.regen_max_retry *
  					ifp->idev->cnf.dad_transmits *
 -					ifp->idev->nd_parms->retrans_time / HZ;
 +					NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME) / HZ;
  
  				if (age >= ifp->prefered_lft - regen_advance) {
  					struct inet6_ifaddr *ifpub = ifp->ifpub;
@@@ -3624,7 -3593,6 +3637,7 @@@ static const struct nla_policy ifa_ipv6
  	[IFA_ADDRESS]		= { .len = sizeof(struct in6_addr) },
  	[IFA_LOCAL]		= { .len = sizeof(struct in6_addr) },
  	[IFA_CACHEINFO]		= { .len = sizeof(struct ifa_cacheinfo) },
 +	[IFA_FLAGS]		= { .len = sizeof(u32) },
  };
  
  static int
@@@ -3648,22 -3616,16 +3661,22 @@@ inet6_rtm_deladdr(struct sk_buff *skb, 
  	return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen);
  }
  
 -static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
 +static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags,
  			     u32 prefered_lft, u32 valid_lft)
  {
  	u32 flags;
  	clock_t expires;
  	unsigned long timeout;
 +	bool was_managetempaddr;
 +	bool had_prefixroute;
  
  	if (!valid_lft || (prefered_lft > valid_lft))
  		return -EINVAL;
  
 +	if (ifa_flags & IFA_F_MANAGETEMPADDR &&
 +	    (ifp->flags & IFA_F_TEMPORARY || ifp->prefix_len != 64))
 +		return -EINVAL;
 +
  	timeout = addrconf_timeout_fixup(valid_lft, HZ);
  	if (addrconf_finite_timeout(timeout)) {
  		expires = jiffies_to_clock_t(timeout * HZ);
@@@ -3683,13 -3645,7 +3696,13 @@@
  	}
  
  	spin_lock_bh(&ifp->lock);
 -	ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags;
 +	was_managetempaddr = ifp->flags & IFA_F_MANAGETEMPADDR;
 +	had_prefixroute = ifp->flags & IFA_F_PERMANENT &&
 +			  !(ifp->flags & IFA_F_NOPREFIXROUTE);
 +	ifp->flags &= ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD |
 +			IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR |
 +			IFA_F_NOPREFIXROUTE);
 +	ifp->flags |= ifa_flags;
  	ifp->tstamp = jiffies;
  	ifp->valid_lft = valid_lft;
  	ifp->prefered_lft = prefered_lft;
@@@ -3698,30 -3654,8 +3711,30 @@@
  	if (!(ifp->flags&IFA_F_TENTATIVE))
  		ipv6_ifa_notify(0, ifp);
  
 -	addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev,
 -			      expires, flags);
 +	if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) {
 +		addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev,
 +				      expires, flags);
 +	} else if (had_prefixroute) {
 +		enum cleanup_prefix_rt_t action;
 +		unsigned long rt_expires;
 +
 +		write_lock_bh(&ifp->idev->lock);
 +		action = check_cleanup_prefix_route(ifp, &rt_expires);
 +		write_unlock_bh(&ifp->idev->lock);
 +
 +		if (action != CLEANUP_PREFIX_RT_NOP) {
 +			cleanup_prefix_route(ifp, rt_expires,
 +				action == CLEANUP_PREFIX_RT_DEL);
 +		}
 +	}
 +
 +	if (was_managetempaddr || ifp->flags & IFA_F_MANAGETEMPADDR) {
 +		if (was_managetempaddr && !(ifp->flags & IFA_F_MANAGETEMPADDR))
 +			valid_lft = prefered_lft = 0;
 +		manage_tempaddrs(ifp->idev, ifp, valid_lft, prefered_lft,
 +				 !was_managetempaddr, jiffies);
 +	}
 +
  	addrconf_verify(0);
  
  	return 0;
@@@ -3737,7 -3671,7 +3750,7 @@@ inet6_rtm_newaddr(struct sk_buff *skb, 
  	struct inet6_ifaddr *ifa;
  	struct net_device *dev;
  	u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
 -	u8 ifa_flags;
 +	u32 ifa_flags;
  	int err;
  
  	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
@@@ -3764,17 -3698,14 +3777,17 @@@
  	if (dev == NULL)
  		return -ENODEV;
  
 +	ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifm->ifa_flags;
 +
  	/* We ignore other flags so far. */
 -	ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS);
 +	ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR |
 +		     IFA_F_NOPREFIXROUTE;
  
  	ifa = ipv6_get_ifaddr(net, pfx, dev, 1);
  	if (ifa == NULL) {
  		/*
  		 * It would be best to check for !NLM_F_CREATE here but
 -		 * userspace alreay relies on not having to provide this.
 +		 * userspace already relies on not having to provide this.
  		 */
  		return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx,
  				      ifm->ifa_prefixlen, ifa_flags,
@@@ -3792,7 -3723,7 +3805,7 @@@
  	return err;
  }
  
 -static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags,
 +static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u32 flags,
  			  u8 scope, int ifindex)
  {
  	struct ifaddrmsg *ifm;
@@@ -3835,8 -3766,7 +3848,8 @@@ static inline int inet6_ifaddr_msgsize(
  	return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
  	       + nla_total_size(16) /* IFA_LOCAL */
  	       + nla_total_size(16) /* IFA_ADDRESS */
 -	       + nla_total_size(sizeof(struct ifa_cacheinfo));
 +	       + nla_total_size(sizeof(struct ifa_cacheinfo))
 +	       + nla_total_size(4)  /* IFA_FLAGS */;
  }
  
  static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
@@@ -3885,9 -3815,6 +3898,9 @@@
  	if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
  		goto error;
  
 +	if (nla_put_u32(skb, IFA_FLAGS, ifa->flags) < 0)
 +		goto error;
 +
  	return nlmsg_end(skb, nlh);
  
  error:
@@@ -4291,7 -4218,7 +4304,7 @@@ static int inet6_fill_ifla6_attrs(struc
  	ci.max_reasm_len = IPV6_MAXPLEN;
  	ci.tstamp = cstamp_delta(idev->tstamp);
  	ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time);
 -	ci.retrans_time = jiffies_to_msecs(idev->nd_parms->retrans_time);
 +	ci.retrans_time = jiffies_to_msecs(NEIGH_VAR(idev->nd_parms, RETRANS_TIME));
  	if (nla_put(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci))
  		goto nla_put_failure;
  	nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
@@@ -4598,19 -4525,6 +4611,6 @@@ errout
  		rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err);
  }
  
- static void update_valid_ll_addr_cnt(struct inet6_ifaddr *ifp, int count)
- {
- 	write_lock_bh(&ifp->idev->lock);
- 	spin_lock(&ifp->lock);
- 	if (((ifp->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|
- 			    IFA_F_DADFAILED)) == IFA_F_PERMANENT) &&
- 	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL))
- 		ifp->idev->valid_ll_addr_cnt += count;
- 	WARN_ON(ifp->idev->valid_ll_addr_cnt < 0);
- 	spin_unlock(&ifp->lock);
- 	write_unlock_bh(&ifp->idev->lock);
- }
- 
  static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
  {
  	struct net *net = dev_net(ifp->idev->dev);
@@@ -4619,8 -4533,6 +4619,6 @@@
  
  	switch (event) {
  	case RTM_NEWADDR:
- 		update_valid_ll_addr_cnt(ifp, 1);
- 
  		/*
  		 * If the address was optimistic
  		 * we inserted the route at the start of
@@@ -4636,8 -4548,6 +4634,6 @@@
  					      ifp->idev->dev, 0, 0);
  		break;
  	case RTM_DELADDR:
- 		update_valid_ll_addr_cnt(ifp, -1);
- 
  		if (ifp->idev->cnf.forwarding)
  			addrconf_leave_anycast(ifp);
  		addrconf_leave_solict(ifp->idev, &ifp->addr);
@@@ -4784,46 -4694,6 +4780,46 @@@ int addrconf_sysctl_disable(struct ctl_
  	return ret;
  }
  
 +static
 +int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
 +			      void __user *buffer, size_t *lenp, loff_t *ppos)
 +{
 +	int *valp = ctl->data;
 +	int ret;
 +	int old, new;
 +
 +	old = *valp;
 +	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
 +	new = *valp;
 +
 +	if (write && old != new) {
 +		struct net *net = ctl->extra2;
 +
 +		if (!rtnl_trylock())
 +			return restart_syscall();
 +
 +		if (valp == &net->ipv6.devconf_dflt->proxy_ndp)
 +			inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
 +						     NETCONFA_IFINDEX_DEFAULT,
 +						     net->ipv6.devconf_dflt);
 +		else if (valp == &net->ipv6.devconf_all->proxy_ndp)
 +			inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
 +						     NETCONFA_IFINDEX_ALL,
 +						     net->ipv6.devconf_all);
 +		else {
 +			struct inet6_dev *idev = ctl->extra1;
 +
 +			inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
 +						     idev->dev->ifindex,
 +						     &idev->cnf);
 +		}
 +		rtnl_unlock();
 +	}
 +
 +	return ret;
 +}
 +
 +
  static struct addrconf_sysctl_table
  {
  	struct ctl_table_header *sysctl_header;
@@@ -5010,7 -4880,7 +5006,7 @@@
  			.data		= &ipv6_devconf.proxy_ndp,
  			.maxlen		= sizeof(int),
  			.mode		= 0644,
 -			.proc_handler	= proc_dointvec,
 +			.proc_handler	= addrconf_sysctl_proxy_ndp,
  		},
  		{
  			.procname	= "accept_source_route",
@@@ -5126,7 -4996,7 +5122,7 @@@ static void __addrconf_sysctl_unregiste
  
  static void addrconf_sysctl_register(struct inet6_dev *idev)
  {
 -	neigh_sysctl_register(idev->dev, idev->nd_parms, "ipv6",
 +	neigh_sysctl_register(idev->dev, idev->nd_parms,
  			      &ndisc_ifinfo_sysctl_change);
  	__addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
  					idev, &idev->cnf);
@@@ -5259,7 -5129,9 +5255,7 @@@ int __init addrconf_init(void
  
  	addrconf_verify(0);
  
 -	err = rtnl_af_register(&inet6_ops);
 -	if (err < 0)
 -		goto errout_af;
 +	rtnl_af_register(&inet6_ops);
  
  	err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo,
  			      NULL);
@@@ -5283,6 -5155,7 +5279,6 @@@
  	return 0;
  errout:
  	rtnl_af_unregister(&inet6_ops);
 -errout_af:
  	unregister_netdevice_notifier(&ipv6_dev_notf);
  errlo:
  	unregister_pernet_subsys(&addrconf_ops);

-- 
LinuxNextTracking


More information about the linux-merge mailing list