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

batman at open-mesh.org batman at open-mesh.org
Fri Feb 21 00:20:51 CET 2014


The following commit has been merged in the master branch:
commit 1e8d6421cff2c24fe0b345711e7a21af02e8bcf5
Merge: f7b12606b5de323a2bb5ca1696558efde8f25441 960dfc4eb23a28495276b02604d7458e0e1a1ed8
Author: David S. Miller <davem at davemloft.net>
Date:   Wed Feb 19 01:24:22 2014 -0500

    Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
    
    Conflicts:
    	drivers/net/bonding/bond_3ad.h
    	drivers/net/bonding/bond_main.c
    
    Two minor conflicts in bonding, both of which were overlapping
    changes.
    
    Signed-off-by: David S. Miller <davem at davemloft.net>

diff --combined MAINTAINERS
index 5a7b3ec,0dba50b..db8bb0d
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@@ -1845,12 -1845,6 +1845,12 @@@ L:	netdev at vger.kernel.or
  S:	Supported
  F:	drivers/net/ethernet/broadcom/b44.*
  
 +BROADCOM GENET ETHERNET DRIVER
 +M:	Florian Fainelli <f.fainelli at gmail.com>
 +L:	netdev at vger.kernel.org
 +S:	Supported
 +F:	drivers/net/ethernet/broadcom/genet/
 +
  BROADCOM BNX2 GIGABIT ETHERNET DRIVER
  M:	Michael Chan <mchan at broadcom.com>
  L:	netdev at vger.kernel.org
@@@ -2373,7 -2367,7 +2373,7 @@@ F:	include/linux/cpufreq.
  
  CPU FREQUENCY DRIVERS - ARM BIG LITTLE
  M:	Viresh Kumar <viresh.kumar at linaro.org>
- M:	Sudeep KarkadaNagesha <sudeep.karkadanagesha at arm.com>
+ M:	Sudeep Holla <sudeep.holla at arm.com>
  L:	cpufreq at vger.kernel.org
  L:	linux-pm at vger.kernel.org
  W:	http://www.arm.com/products/processors/technologies/biglittleprocessing.php
@@@ -2863,7 -2857,7 +2863,7 @@@ M:	Jani Nikula <jani.nikula at linux.intel
  L:	intel-gfx at lists.freedesktop.org
  L:	dri-devel at lists.freedesktop.org
  Q:	http://patchwork.freedesktop.org/project/intel-gfx/
- T:	git git://people.freedesktop.org/~danvet/drm-intel
+ T:	git git://anongit.freedesktop.org/drm-intel
  S:	Supported
  F:	drivers/gpu/drm/i915/
  F:	include/drm/i915*
@@@ -3330,6 -3324,17 +3330,17 @@@ S:	Maintaine
  F:	include/linux/netfilter_bridge/
  F:	net/bridge/
  
+ ETHERNET PHY LIBRARY
+ M:	Florian Fainelli <f.fainelli at gmail.com>
+ L:	netdev at vger.kernel.org
+ S:	Maintained
+ F:	include/linux/phy.h
+ F:	include/linux/phy_fixed.h
+ F:	drivers/net/phy/
+ F:	Documentation/networking/phy.txt
+ F:	drivers/of/of_mdio.c
+ F:	drivers/of/of_net.c
+ 
  EXT2 FILE SYSTEM
  M:	Jan Kara <jack at suse.cz>
  L:	linux-ext4 at vger.kernel.org
diff --combined drivers/net/bonding/bond_3ad.c
index e9edd84,6d20fbd..e362ff7
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@@ -768,11 -768,11 +768,11 @@@ static int ad_lacpdu_send(struct port *
  
  	lacpdu_header = (struct lacpdu_header *)skb_put(skb, length);
  
 -	memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
 +	ether_addr_copy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr);
  	/* Note: source address is set to be the member's PERMANENT address,
  	 * because we use it to identify loopback lacpdus in receive.
  	 */
 -	memcpy(lacpdu_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
 +	ether_addr_copy(lacpdu_header->hdr.h_source, slave->perm_hwaddr);
  	lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU;
  
  	lacpdu_header->lacpdu = port->lacpdu;
@@@ -810,11 -810,11 +810,11 @@@ static int ad_marker_send(struct port *
  
  	marker_header = (struct bond_marker_header *)skb_put(skb, length);
  
 -	memcpy(marker_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
 +	ether_addr_copy(marker_header->hdr.h_dest, lacpdu_mcast_addr);
  	/* Note: source address is set to be the member's PERMANENT address,
  	 * because we use it to identify loopback MARKERs in receive.
  	 */
 -	memcpy(marker_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
 +	ether_addr_copy(marker_header->hdr.h_source, slave->perm_hwaddr);
  	marker_header->hdr.h_proto = PKT_TYPE_LACPDU;
  
  	marker_header->marker = *marker;
@@@ -1079,8 -1079,7 +1079,8 @@@ static void ad_rx_machine(struct lacpd
  			/* detect loopback situation */
  			if (MAC_ADDRESS_EQUAL(&(lacpdu->actor_system),
  					      &(port->actor_system))) {
 -				pr_err("%s: An illegal loopback occurred on adapter (%s).\nCheck the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
 +				pr_err("%s: An illegal loopback occurred on adapter (%s)\n"
 +				       "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
  				       port->slave->bond->dev->name,
  				       port->slave->dev->name);
  				return;
@@@ -1797,8 -1796,6 +1797,6 @@@ void bond_3ad_initiate_agg_selection(st
  	BOND_AD_INFO(bond).agg_select_timer = timeout;
  }
  
- static u16 aggregator_identifier;
- 
  /**
   * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
   * @bond: bonding struct to work on
@@@ -1812,7 -1809,7 +1810,7 @@@ void bond_3ad_initialize(struct bondin
  	if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr),
  				bond->dev->dev_addr)) {
  
- 		aggregator_identifier = 0;
+ 		BOND_AD_INFO(bond).aggregator_identifier = 0;
  
  		BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
  		BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
@@@ -1881,7 -1878,7 +1879,7 @@@ void bond_3ad_bind_slave(struct slave *
  		ad_initialize_agg(aggregator);
  
  		aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr);
- 		aggregator->aggregator_identifier = (++aggregator_identifier);
+ 		aggregator->aggregator_identifier = ++BOND_AD_INFO(bond).aggregator_identifier;
  		aggregator->slave = slave;
  		aggregator->is_active = 0;
  		aggregator->num_of_ports = 0;
@@@ -1951,7 -1948,7 +1949,7 @@@ void bond_3ad_unbind_slave(struct slav
  			 * new aggregator
  			 */
  			if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
 -				pr_debug("Some port(s) related to LAG %d - replaceing with LAG %d\n",
 +				pr_debug("Some port(s) related to LAG %d - replacing with LAG %d\n",
  					 aggregator->aggregator_identifier,
  					 new_aggregator->aggregator_identifier);
  
@@@ -2301,9 -2298,9 +2299,9 @@@ void bond_3ad_handle_link_change(struc
  		port->actor_oper_port_key = (port->actor_admin_port_key &=
  					     ~AD_SPEED_KEY_BITS);
  	}
 -	pr_debug("Port %d changed link status to %s",
 -		port->actor_port_number,
 -		(link == BOND_LINK_UP) ? "UP" : "DOWN");
 +	pr_debug("Port %d changed link status to %s\n",
 +		 port->actor_port_number,
 +		 link == BOND_LINK_UP ? "UP" : "DOWN");
  	/* there is no need to reselect a new aggregator, just signal the
  	 * state machines to reinitialize
  	 */
diff --combined drivers/net/bonding/bond_3ad.h
index 3b97fe48,f4dd959..bb03b1d
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@@ -28,7 -28,7 +28,7 @@@
  #include <linux/netdevice.h>
  #include <linux/if_ether.h>
  
 -// General definitions
 +/* General definitions */
  #define PKT_TYPE_LACPDU         cpu_to_be16(ETH_P_SLOW)
  #define AD_TIMER_INTERVAL       100 /*msec*/
  
@@@ -47,54 -47,54 +47,54 @@@ enum 
  	BOND_AD_COUNT = 2,
  };
  
 -// rx machine states(43.4.11 in the 802.3ad standard)
 +/* rx machine states(43.4.11 in the 802.3ad standard) */
  typedef enum {
  	AD_RX_DUMMY,
 -	AD_RX_INITIALIZE,     // rx Machine
 -	AD_RX_PORT_DISABLED,  // rx Machine
 -	AD_RX_LACP_DISABLED,  // rx Machine
 -	AD_RX_EXPIRED,	      // rx Machine
 -	AD_RX_DEFAULTED,      // rx Machine
 -	AD_RX_CURRENT	      // rx Machine
 +	AD_RX_INITIALIZE,	/* rx Machine */
 +	AD_RX_PORT_DISABLED,	/* rx Machine */
 +	AD_RX_LACP_DISABLED,	/* rx Machine */
 +	AD_RX_EXPIRED,		/* rx Machine */
 +	AD_RX_DEFAULTED,	/* rx Machine */
 +	AD_RX_CURRENT		/* rx Machine */
  } rx_states_t;
  
 -// periodic machine states(43.4.12 in the 802.3ad standard)
 +/* periodic machine states(43.4.12 in the 802.3ad standard) */
  typedef enum {
  	AD_PERIODIC_DUMMY,
 -	AD_NO_PERIODIC,	       // periodic machine
 -	AD_FAST_PERIODIC,      // periodic machine
 -	AD_SLOW_PERIODIC,      // periodic machine
 -	AD_PERIODIC_TX	   // periodic machine
 +	AD_NO_PERIODIC,		/* periodic machine */
 +	AD_FAST_PERIODIC,	/* periodic machine */
 +	AD_SLOW_PERIODIC,	/* periodic machine */
 +	AD_PERIODIC_TX		/* periodic machine */
  } periodic_states_t;
  
 -// mux machine states(43.4.13 in the 802.3ad standard)
 +/* mux machine states(43.4.13 in the 802.3ad standard) */
  typedef enum {
  	AD_MUX_DUMMY,
 -	AD_MUX_DETACHED,       // mux machine
 -	AD_MUX_WAITING,	       // mux machine
 -	AD_MUX_ATTACHED,       // mux machine
 -	AD_MUX_COLLECTING_DISTRIBUTING // mux machine
 +	AD_MUX_DETACHED,	/* mux machine */
 +	AD_MUX_WAITING,		/* mux machine */
 +	AD_MUX_ATTACHED,	/* mux machine */
 +	AD_MUX_COLLECTING_DISTRIBUTING	/* mux machine */
  } mux_states_t;
  
 -// tx machine states(43.4.15 in the 802.3ad standard)
 +/* tx machine states(43.4.15 in the 802.3ad standard) */
  typedef enum {
  	AD_TX_DUMMY,
 -	AD_TRANSMIT	   // tx Machine
 +	AD_TRANSMIT		/* tx Machine */
  } tx_states_t;
  
 -// rx indication types
 +/* rx indication types */
  typedef enum {
 -	AD_TYPE_LACPDU = 1,    // type lacpdu
 -	AD_TYPE_MARKER	   // type marker
 +	AD_TYPE_LACPDU = 1,	/* type lacpdu */
 +	AD_TYPE_MARKER		/* type marker */
  } pdu_type_t;
  
 -// rx marker indication types
 +/* rx marker indication types */
  typedef enum {
 -	AD_MARKER_INFORMATION_SUBTYPE = 1, // marker imformation subtype
 -	AD_MARKER_RESPONSE_SUBTYPE     // marker response subtype
 +	AD_MARKER_INFORMATION_SUBTYPE = 1,	/* marker imformation subtype */
 +	AD_MARKER_RESPONSE_SUBTYPE		/* marker response subtype */
  } bond_marker_subtype_t;
  
 -// timers types(43.4.9 in the 802.3ad standard)
 +/* timers types(43.4.9 in the 802.3ad standard) */
  typedef enum {
  	AD_CURRENT_WHILE_TIMER,
  	AD_ACTOR_CHURN_TIMER,
@@@ -105,35 -105,35 +105,35 @@@
  
  #pragma pack(1)
  
 -// Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard)
 +/* Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard) */
  typedef struct lacpdu {
 -	u8 subtype;		     // = LACP(= 0x01)
 +	u8 subtype;		/* = LACP(= 0x01) */
  	u8 version_number;
 -	u8 tlv_type_actor_info;	      // = actor information(type/length/value)
 -	u8 actor_information_length; // = 20
 +	u8 tlv_type_actor_info;	/* = actor information(type/length/value) */
 +	u8 actor_information_length;	/* = 20 */
  	__be16 actor_system_priority;
  	struct mac_addr actor_system;
  	__be16 actor_key;
  	__be16 actor_port_priority;
  	__be16 actor_port;
  	u8 actor_state;
 -	u8 reserved_3_1[3];	     // = 0
 -	u8 tlv_type_partner_info;     // = partner information
 -	u8 partner_information_length;	 // = 20
 +	u8 reserved_3_1[3];		/* = 0 */
 +	u8 tlv_type_partner_info;	/* = partner information */
 +	u8 partner_information_length;	/* = 20 */
  	__be16 partner_system_priority;
  	struct mac_addr partner_system;
  	__be16 partner_key;
  	__be16 partner_port_priority;
  	__be16 partner_port;
  	u8 partner_state;
 -	u8 reserved_3_2[3];	     // = 0
 -	u8 tlv_type_collector_info;	  // = collector information
 -	u8 collector_information_length; // = 16
 +	u8 reserved_3_2[3];		/* = 0 */
 +	u8 tlv_type_collector_info;	/* = collector information */
 +	u8 collector_information_length;/* = 16 */
  	__be16 collector_max_delay;
  	u8 reserved_12[12];
 -	u8 tlv_type_terminator;	     // = terminator
 -	u8 terminator_length;	     // = 0
 -	u8 reserved_50[50];	     // = 0
 +	u8 tlv_type_terminator;		/* = terminator */
 +	u8 terminator_length;		/* = 0 */
 +	u8 reserved_50[50];		/* = 0 */
  } __packed lacpdu_t;
  
  typedef struct lacpdu_header {
@@@ -141,20 -141,20 +141,20 @@@
  	struct lacpdu lacpdu;
  } __packed lacpdu_header_t;
  
 -// Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard)
 +/* Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard) */
  typedef struct bond_marker {
 -	u8 subtype;		 //  = 0x02  (marker PDU)
 -	u8 version_number;	 //  = 0x01
 -	u8 tlv_type;		 //  = 0x01  (marker information)
 -	//  = 0x02  (marker response information)
 -	u8 marker_length;	 //  = 0x16
 -	u16 requester_port;	 //   The number assigned to the port by the requester
 -	struct mac_addr requester_system;      //   The requester's system id
 -	u32 requester_transaction_id;	//   The transaction id allocated by the requester,
 -	u16 pad;		 //  = 0
 -	u8 tlv_type_terminator;	     //  = 0x00
 -	u8 terminator_length;	     //  = 0x00
 -	u8 reserved_90[90];	     //  = 0
 +	u8 subtype;		/* = 0x02  (marker PDU) */
 +	u8 version_number;	/* = 0x01 */
 +	u8 tlv_type;		/* = 0x01  (marker information) */
 +	/* = 0x02  (marker response information) */
 +	u8 marker_length;	/* = 0x16 */
 +	u16 requester_port;	/* The number assigned to the port by the requester */
 +	struct mac_addr requester_system;	/* The requester's system id */
 +	u32 requester_transaction_id;		/* The transaction id allocated by the requester, */
 +	u16 pad;		/* = 0 */
 +	u8 tlv_type_terminator;	/* = 0x00 */
 +	u8 terminator_length;	/* = 0x00 */
 +	u8 reserved_90[90];	/* = 0 */
  } __packed bond_marker_t;
  
  typedef struct bond_marker_header {
@@@ -173,7 -173,7 +173,7 @@@ struct port
  #pragma pack(8)
  #endif
  
 -// aggregator structure(43.4.5 in the 802.3ad standard)
 +/* aggregator structure(43.4.5 in the 802.3ad standard) */
  typedef struct aggregator {
  	struct mac_addr aggregator_mac_address;
  	u16 aggregator_identifier;
@@@ -183,12 -183,12 +183,12 @@@
  	struct mac_addr partner_system;
  	u16 partner_system_priority;
  	u16 partner_oper_aggregator_key;
 -	u16 receive_state;		// BOOLEAN
 -	u16 transmit_state;		// BOOLEAN
 +	u16 receive_state;	/* BOOLEAN */
 +	u16 transmit_state;	/* BOOLEAN */
  	struct port *lag_ports;
 -	// ****** PRIVATE PARAMETERS ******
 -	struct slave *slave;	    // pointer to the bond slave that this aggregator belongs to
 -	u16 is_active;	    // BOOLEAN. Indicates if this aggregator is active
 +	/* ****** PRIVATE PARAMETERS ****** */
 +	struct slave *slave;	/* pointer to the bond slave that this aggregator belongs to */
 +	u16 is_active;		/* BOOLEAN. Indicates if this aggregator is active */
  	u16 num_of_ports;
  } aggregator_t;
  
@@@ -201,12 -201,12 +201,12 @@@ struct port_params 
  	u16 port_state;
  };
  
 -// port structure(43.4.6 in the 802.3ad standard)
 +/* port structure(43.4.6 in the 802.3ad standard) */
  typedef struct port {
  	u16 actor_port_number;
  	u16 actor_port_priority;
 -	struct mac_addr actor_system;	       // This parameter is added here although it is not specified in the standard, just for simplification
 -	u16 actor_system_priority;	 // This parameter is added here although it is not specified in the standard, just for simplification
 +	struct mac_addr actor_system;	/* This parameter is added here although it is not specified in the standard, just for simplification */
 +	u16 actor_system_priority;	/* This parameter is added here although it is not specified in the standard, just for simplification */
  	u16 actor_port_aggregator_identifier;
  	bool ntt;
  	u16 actor_admin_port_key;
@@@ -219,24 -219,24 +219,24 @@@
  
  	bool is_enabled;
  
 -	// ****** PRIVATE PARAMETERS ******
 -	u16 sm_vars;	      // all state machines variables for this port
 -	rx_states_t sm_rx_state;	// state machine rx state
 -	u16 sm_rx_timer_counter;    // state machine rx timer counter
 -	periodic_states_t sm_periodic_state;// state machine periodic state
 -	u16 sm_periodic_timer_counter;	// state machine periodic timer counter
 -	mux_states_t sm_mux_state;	// state machine mux state
 -	u16 sm_mux_timer_counter;   // state machine mux timer counter
 -	tx_states_t sm_tx_state;	// state machine tx state
 -	u16 sm_tx_timer_counter;    // state machine tx timer counter(allways on - enter to transmit state 3 time per second)
 -	struct slave *slave;	    // pointer to the bond slave that this port belongs to
 -	struct aggregator *aggregator;	   // pointer to an aggregator that this port related to
 -	struct port *next_port_in_aggregator; // Next port on the linked list of the parent aggregator
 -	u32 transaction_id;	    // continuous number for identification of Marker PDU's;
 -	struct lacpdu lacpdu;	       // the lacpdu that will be sent for this port
 +	/* ****** PRIVATE PARAMETERS ****** */
 +	u16 sm_vars;		/* all state machines variables for this port */
 +	rx_states_t sm_rx_state;	/* state machine rx state */
 +	u16 sm_rx_timer_counter;	/* state machine rx timer counter */
 +	periodic_states_t sm_periodic_state;	/* state machine periodic state */
 +	u16 sm_periodic_timer_counter;	/* state machine periodic timer counter */
 +	mux_states_t sm_mux_state;	/* state machine mux state */
 +	u16 sm_mux_timer_counter;	/* state machine mux timer counter */
 +	tx_states_t sm_tx_state;	/* state machine tx state */
 +	u16 sm_tx_timer_counter;	/* state machine tx timer counter(allways on - enter to transmit state 3 time per second) */
 +	struct slave *slave;		/* pointer to the bond slave that this port belongs to */
 +	struct aggregator *aggregator;	/* pointer to an aggregator that this port related to */
 +	struct port *next_port_in_aggregator;	/* Next port on the linked list of the parent aggregator */
 +	u32 transaction_id;		/* continuous number for identification of Marker PDU's; */
 +	struct lacpdu lacpdu;		/* the lacpdu that will be sent for this port */
  } port_t;
  
 -// system structure
 +/* system structure */
  struct ad_system {
  	u16 sys_priority;
  	struct mac_addr sys_mac_addr;
@@@ -246,25 -246,27 +246,26 @@@
  #pragma pack()
  #endif
  
 -// ================= AD Exported structures to the main bonding code ==================
 +/* ========== AD Exported structures to the main bonding code ========== */
  #define BOND_AD_INFO(bond)   ((bond)->ad_info)
  #define SLAVE_AD_INFO(slave) ((slave)->ad_info)
  
  struct ad_bond_info {
 -	struct ad_system system;	    /* 802.3ad system structure */
 -	u32 agg_select_timer;	    // Timer to select aggregator after all adapter's hand shakes
 +	struct ad_system system;	/* 802.3ad system structure */
 +	u32 agg_select_timer;		/* Timer to select aggregator after all adapter's hand shakes */
+ 	u16 aggregator_identifier;
  };
  
  struct ad_slave_info {
 -	struct aggregator aggregator;	    // 802.3ad aggregator structure
 -	struct port port;		    // 802.3ad port structure
 -	spinlock_t state_machine_lock; /* mutex state machines vs.
 -					  incoming LACPDU */
 +	struct aggregator aggregator;	/* 802.3ad aggregator structure */
 +	struct port port;		/* 802.3ad port structure */
 +	spinlock_t state_machine_lock;	/* mutex state machines vs. incoming LACPDU */
  	u16 id;
  };
  
 -// ================= AD Exported functions to the main bonding code ==================
 +/* ========== AD Exported functions to the main bonding code ========== */
  void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution);
 -void  bond_3ad_bind_slave(struct slave *slave);
 +void bond_3ad_bind_slave(struct slave *slave);
  void bond_3ad_unbind_slave(struct slave *slave);
  void bond_3ad_state_machine_handler(struct work_struct *);
  void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
@@@ -279,5 -281,5 +280,5 @@@ int bond_3ad_lacpdu_recv(const struct s
  			 struct slave *slave);
  int bond_3ad_set_carrier(struct bonding *bond);
  void bond_3ad_update_lacp_rate(struct bonding *bond);
 -#endif //__BOND_3AD_H__
 +#endif /* __BOND_3AD_H__ */
  
diff --combined drivers/net/bonding/bond_main.c
index ac4a1b8,1c6104d..afae7ca
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@@ -673,12 -673,12 +673,12 @@@ static void bond_do_fail_over_mac(struc
  		write_unlock_bh(&bond->curr_slave_lock);
  
  		if (old_active) {
 -			memcpy(tmp_mac, new_active->dev->dev_addr, ETH_ALEN);
 +			ether_addr_copy(tmp_mac, new_active->dev->dev_addr);
  			memcpy(saddr.sa_data, old_active->dev->dev_addr,
  			       ETH_ALEN);
  			saddr.sa_family = new_active->dev->type;
  		} else {
 -			memcpy(saddr.sa_data, bond->dev->dev_addr, ETH_ALEN);
 +			ether_addr_copy(saddr.sa_data, bond->dev->dev_addr);
  			saddr.sa_family = bond->dev->type;
  		}
  
@@@ -692,7 -692,7 +692,7 @@@
  		if (!old_active)
  			goto out;
  
 -		memcpy(saddr.sa_data, tmp_mac, ETH_ALEN);
 +		ether_addr_copy(saddr.sa_data, tmp_mac);
  		saddr.sa_family = old_active->dev->type;
  
  		rv = dev_set_mac_address(old_active->dev, &saddr);
@@@ -798,11 -798,11 +798,11 @@@ void bond_change_active_slave(struct bo
  		return;
  
  	if (new_active) {
 -		new_active->jiffies = jiffies;
 +		new_active->last_link_up = jiffies;
  
  		if (new_active->link == BOND_LINK_BACK) {
  			if (USES_PRIMARY(bond->params.mode)) {
 -				pr_info("%s: making interface %s the new active one %d ms earlier.\n",
 +				pr_info("%s: making interface %s the new active one %d ms earlier\n",
  					bond->dev->name, new_active->dev->name,
  					(bond->params.updelay - new_active->delay) * bond->params.miimon);
  			}
@@@ -817,7 -817,7 +817,7 @@@
  				bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
  		} else {
  			if (USES_PRIMARY(bond->params.mode)) {
 -				pr_info("%s: making interface %s the new active one.\n",
 +				pr_info("%s: making interface %s the new active one\n",
  					bond->dev->name, new_active->dev->name);
  			}
  		}
@@@ -906,7 -906,7 +906,7 @@@ void bond_select_active_slave(struct bo
  			pr_info("%s: first active interface up!\n",
  				bond->dev->name);
  		} else {
 -			pr_info("%s: now running without any active interface !\n",
 +			pr_info("%s: now running without any active interface!\n",
  				bond->dev->name);
  		}
  	}
@@@ -1115,6 -1115,9 +1115,6 @@@ static rx_handler_result_t bond_handle_
  	slave = bond_slave_get_rcu(skb->dev);
  	bond = slave->bond;
  
 -	if (bond->params.arp_interval)
 -		slave->dev->last_rx = jiffies;
 -
  	recv_probe = ACCESS_ONCE(bond->recv_probe);
  	if (recv_probe) {
  		ret = recv_probe(skb, bond, slave);
@@@ -1180,13 -1183,13 +1180,13 @@@ int bond_enslave(struct net_device *bon
  	if (!bond->params.use_carrier &&
  	    slave_dev->ethtool_ops->get_link == NULL &&
  	    slave_ops->ndo_do_ioctl == NULL) {
 -		pr_warning("%s: Warning: no link monitoring support for %s\n",
 -			   bond_dev->name, slave_dev->name);
 +		pr_warn("%s: Warning: no link monitoring support for %s\n",
 +			bond_dev->name, slave_dev->name);
  	}
  
  	/* already enslaved */
  	if (slave_dev->flags & IFF_SLAVE) {
 -		pr_debug("Error, Device was already enslaved\n");
 +		pr_debug("Error: Device was already enslaved\n");
  		return -EBUSY;
  	}
  
@@@ -1199,9 -1202,9 +1199,9 @@@
  			       bond_dev->name, slave_dev->name, bond_dev->name);
  			return -EPERM;
  		} else {
 -			pr_warning("%s: Warning: enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n",
 -				   bond_dev->name, slave_dev->name,
 -				   slave_dev->name, bond_dev->name);
 +			pr_warn("%s: Warning: enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n",
 +				bond_dev->name, slave_dev->name,
 +				slave_dev->name, bond_dev->name);
  		}
  	} else {
  		pr_debug("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
@@@ -1214,7 -1217,7 +1214,7 @@@
  	 * enslaving it; the old ifenslave will not.
  	 */
  	if ((slave_dev->flags & IFF_UP)) {
 -		pr_err("%s is up. This may be due to an out of date ifenslave.\n",
 +		pr_err("%s is up - this may be due to an out of date ifenslave\n",
  		       slave_dev->name);
  		res = -EPERM;
  		goto err_undo_flags;
@@@ -1258,23 -1261,24 +1258,23 @@@
  						 bond_dev);
  		}
  	} else if (bond_dev->type != slave_dev->type) {
 -		pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it.\n",
 -		       slave_dev->name,
 -		       slave_dev->type, bond_dev->type);
 +		pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it\n",
 +		       slave_dev->name, slave_dev->type, bond_dev->type);
  		res = -EINVAL;
  		goto err_undo_flags;
  	}
  
  	if (slave_ops->ndo_set_mac_address == NULL) {
  		if (!bond_has_slaves(bond)) {
 -			pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address.\n",
 +			pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address\n",
  				bond_dev->name);
  			if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
  				bond->params.fail_over_mac = BOND_FOM_ACTIVE;
 -				pr_warn("%s: Setting fail_over_mac to active for active-backup mode.\n",
 +				pr_warn("%s: Setting fail_over_mac to active for active-backup mode\n",
  					bond_dev->name);
  			}
  		} else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
 -			pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active.\n",
 +			pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n",
  			       bond_dev->name);
  			res = -EOPNOTSUPP;
  			goto err_undo_flags;
@@@ -1313,7 -1317,7 +1313,7 @@@
  	 * that need it, and for restoring it upon release, and then
  	 * set it to the master's address
  	 */
 -	memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN);
 +	ether_addr_copy(new_slave->perm_hwaddr, slave_dev->dev_addr);
  
  	if (!bond->params.fail_over_mac ||
  	    bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
@@@ -1397,10 -1401,10 +1397,10 @@@
  
  	bond_update_speed_duplex(new_slave);
  
 -	new_slave->last_arp_rx = jiffies -
 +	new_slave->last_rx = jiffies -
  		(msecs_to_jiffies(bond->params.arp_interval) + 1);
  	for (i = 0; i < BOND_MAX_ARP_TARGETS; i++)
 -		new_slave->target_last_arp_rx[i] = new_slave->last_arp_rx;
 +		new_slave->target_last_arp_rx[i] = new_slave->last_rx;
  
  	if (bond->params.miimon && !bond->params.use_carrier) {
  		link_reporting = bond_check_dev_link(bond, slave_dev, 1);
@@@ -1415,12 -1419,12 +1415,12 @@@
  			 * supported); thus, we don't need to change
  			 * the messages for netif_carrier.
  			 */
 -			pr_warning("%s: Warning: MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details.\n",
 -			       bond_dev->name, slave_dev->name);
 +			pr_warn("%s: Warning: MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details\n",
 +				bond_dev->name, slave_dev->name);
  		} else if (link_reporting == -1) {
  			/* unable get link status using mii/ethtool */
 -			pr_warning("%s: Warning: can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface.\n",
 -				   bond_dev->name, slave_dev->name);
 +			pr_warn("%s: Warning: can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface\n",
 +				bond_dev->name, slave_dev->name);
  		}
  	}
  
@@@ -1444,10 -1448,10 +1444,10 @@@
  	}
  
  	if (new_slave->link != BOND_LINK_DOWN)
 -		new_slave->jiffies = jiffies;
 +		new_slave->last_link_up = jiffies;
  	pr_debug("Initial state of slave_dev is BOND_LINK_%s\n",
 -		new_slave->link == BOND_LINK_DOWN ? "DOWN" :
 -			(new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
 +		 new_slave->link == BOND_LINK_DOWN ? "DOWN" :
 +		 (new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
  
  	if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
  		/* if there is a primary slave, remember it */
@@@ -1506,8 -1510,9 +1506,8 @@@
  	slave_dev->npinfo = bond->dev->npinfo;
  	if (slave_dev->npinfo) {
  		if (slave_enable_netpoll(new_slave)) {
 -			pr_info("Error, %s: master_dev is using netpoll, "
 -				 "but new slave device does not support netpoll.\n",
 -				 bond_dev->name);
 +			pr_info("Error, %s: master_dev is using netpoll, but new slave device does not support netpoll\n",
 +				bond_dev->name);
  			res = -EBUSY;
  			goto err_detach;
  		}
@@@ -1538,15 -1543,17 +1538,17 @@@
  	bond_set_carrier(bond);
  
  	if (USES_PRIMARY(bond->params.mode)) {
+ 		block_netpoll_tx();
  		write_lock_bh(&bond->curr_slave_lock);
  		bond_select_active_slave(bond);
  		write_unlock_bh(&bond->curr_slave_lock);
+ 		unblock_netpoll_tx();
  	}
  
 -	pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
 +	pr_info("%s: Enslaving %s as %s interface with %s link\n",
  		bond_dev->name, slave_dev->name,
 -		bond_is_active_slave(new_slave) ? "n active" : " backup",
 -		new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
 +		bond_is_active_slave(new_slave) ? "an active" : "a backup",
 +		new_slave->link != BOND_LINK_DOWN ? "an up" : "a down");
  
  	/* enslave is successful */
  	return 0;
@@@ -1566,10 -1573,12 +1568,12 @@@ err_detach
  	if (bond->primary_slave == new_slave)
  		bond->primary_slave = NULL;
  	if (bond->curr_active_slave == new_slave) {
+ 		block_netpoll_tx();
  		write_lock_bh(&bond->curr_slave_lock);
  		bond_change_active_slave(bond, NULL);
  		bond_select_active_slave(bond);
  		write_unlock_bh(&bond->curr_slave_lock);
+ 		unblock_netpoll_tx();
  	}
  	slave_disable_netpoll(new_slave);
  
@@@ -1584,7 -1593,7 +1588,7 @@@ err_restore_mac
  		 * MAC if this slave's MAC is in use by the bond, or at
  		 * least print a warning.
  		 */
 -		memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN);
 +		ether_addr_copy(addr.sa_data, new_slave->perm_hwaddr);
  		addr.sa_family = slave_dev->type;
  		dev_set_mac_address(slave_dev, &addr);
  	}
@@@ -1629,7 -1638,7 +1633,7 @@@ static int __bond_release_one(struct ne
  	/* slave is not a slave or master is not master of this slave */
  	if (!(slave_dev->flags & IFF_SLAVE) ||
  	    !netdev_has_upper_dev(slave_dev, bond_dev)) {
 -		pr_err("%s: Error: cannot release %s.\n",
 +		pr_err("%s: Error: cannot release %s\n",
  		       bond_dev->name, slave_dev->name);
  		return -EINVAL;
  	}
@@@ -1663,7 -1672,7 +1667,7 @@@
  
  	write_unlock_bh(&bond->lock);
  
 -	pr_info("%s: releasing %s interface %s\n",
 +	pr_info("%s: Releasing %s interface %s\n",
  		bond_dev->name,
  		bond_is_active_slave(slave) ? "active" : "backup",
  		slave_dev->name);
@@@ -1676,10 -1685,10 +1680,10 @@@
  		     bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
  		if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) &&
  		    bond_has_slaves(bond))
 -			pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
 -				   bond_dev->name, slave_dev->name,
 -				   slave->perm_hwaddr,
 -				   bond_dev->name, slave_dev->name);
 +			pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s - set the HWaddr of %s to a different address to avoid conflicts\n",
 +				bond_dev->name, slave_dev->name,
 +				slave->perm_hwaddr,
 +				bond_dev->name, slave_dev->name);
  	}
  
  	if (bond->primary_slave == slave)
@@@ -1720,10 -1729,10 +1724,10 @@@
  		eth_hw_addr_random(bond_dev);
  
  		if (vlan_uses_dev(bond_dev)) {
 -			pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
 -				   bond_dev->name, bond_dev->name);
 -			pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
 -				   bond_dev->name);
 +			pr_warn("%s: Warning: clearing HW address of %s while it still has VLANs\n",
 +				bond_dev->name, bond_dev->name);
 +			pr_warn("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs\n",
 +				bond_dev->name);
  		}
  	}
  
@@@ -1738,7 -1747,7 +1742,7 @@@
  	bond_compute_features(bond);
  	if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
  	    (old_features & NETIF_F_VLAN_CHALLENGED))
 -		pr_info("%s: last VLAN challenged slave %s left bond %s. VLAN blocking is removed\n",
 +		pr_info("%s: last VLAN challenged slave %s left bond %s - VLAN blocking is removed\n",
  			bond_dev->name, slave_dev->name, bond_dev->name);
  
  	/* must do this from outside any spinlocks */
@@@ -1773,7 -1782,7 +1777,7 @@@
  	if (bond->params.fail_over_mac != BOND_FOM_ACTIVE ||
  	    bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
  		/* restore original ("permanent") mac address */
 -		memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
 +		ether_addr_copy(addr.sa_data, slave->perm_hwaddr);
  		addr.sa_family = slave_dev->type;
  		dev_set_mac_address(slave_dev, &addr);
  	}
@@@ -1806,7 -1815,7 +1810,7 @@@ static int  bond_release_and_destroy(st
  	ret = bond_release(bond_dev, slave_dev);
  	if (ret == 0 && !bond_has_slaves(bond)) {
  		bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
 -		pr_info("%s: destroying bond %s.\n",
 +		pr_info("%s: Destroying bond %s\n",
  			bond_dev->name, bond_dev->name);
  		unregister_netdevice(bond_dev);
  	}
@@@ -1875,7 -1884,7 +1879,7 @@@ static int bond_miimon_inspect(struct b
  			slave->link = BOND_LINK_FAIL;
  			slave->delay = bond->params.downdelay;
  			if (slave->delay) {
 -				pr_info("%s: link status down for %sinterface %s, disabling it in %d ms.\n",
 +				pr_info("%s: link status down for %sinterface %s, disabling it in %d ms\n",
  					bond->dev->name,
  					(bond->params.mode ==
  					 BOND_MODE_ACTIVEBACKUP) ?
@@@ -1891,8 -1900,8 +1895,8 @@@
  				 * recovered before downdelay expired
  				 */
  				slave->link = BOND_LINK_UP;
 -				slave->jiffies = jiffies;
 -				pr_info("%s: link status up again after %d ms for interface %s.\n",
 +				slave->last_link_up = jiffies;
 +				pr_info("%s: link status up again after %d ms for interface %s\n",
  					bond->dev->name,
  					(bond->params.downdelay - slave->delay) *
  					bond->params.miimon,
@@@ -1917,7 -1926,7 +1921,7 @@@
  			slave->delay = bond->params.updelay;
  
  			if (slave->delay) {
 -				pr_info("%s: link status up for interface %s, enabling it in %d ms.\n",
 +				pr_info("%s: link status up for interface %s, enabling it in %d ms\n",
  					bond->dev->name, slave->dev->name,
  					ignore_updelay ? 0 :
  					bond->params.updelay *
@@@ -1927,7 -1936,7 +1931,7 @@@
  		case BOND_LINK_BACK:
  			if (!link_state) {
  				slave->link = BOND_LINK_DOWN;
 -				pr_info("%s: link status down again after %d ms for interface %s.\n",
 +				pr_info("%s: link status down again after %d ms for interface %s\n",
  					bond->dev->name,
  					(bond->params.updelay - slave->delay) *
  					bond->params.miimon,
@@@ -1966,7 -1975,7 +1970,7 @@@ static void bond_miimon_commit(struct b
  
  		case BOND_LINK_UP:
  			slave->link = BOND_LINK_UP;
 -			slave->jiffies = jiffies;
 +			slave->last_link_up = jiffies;
  
  			if (bond->params.mode == BOND_MODE_8023AD) {
  				/* prevent it from being the active one */
@@@ -1979,7 -1988,7 +1983,7 @@@
  				bond_set_backup_slave(slave);
  			}
  
 -			pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n",
 +			pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex\n",
  				bond->dev->name, slave->dev->name,
  				slave->speed == SPEED_UNKNOWN ? 0 : slave->speed,
  				slave->duplex ? "full" : "half");
@@@ -2127,8 -2136,8 +2131,8 @@@ static void bond_arp_send(struct net_de
  {
  	struct sk_buff *skb;
  
 -	pr_debug("arp %d on slave %s: dst %pI4 src %pI4 vid %d\n", arp_op,
 -		 slave_dev->name, &dest_ip, &src_ip, vlan_id);
 +	pr_debug("arp %d on slave %s: dst %pI4 src %pI4 vid %d\n",
 +		 arp_op, slave_dev->name, &dest_ip, &src_ip, vlan_id);
  
  	skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip,
  			 NULL, slave_dev->dev_addr, NULL);
@@@ -2242,7 -2251,7 +2246,7 @@@ static void bond_validate_arp(struct bo
  		pr_debug("bva: sip %pI4 not found in targets\n", &sip);
  		return;
  	}
 -	slave->last_arp_rx = jiffies;
 +	slave->last_rx = jiffies;
  	slave->target_last_arp_rx[i] = jiffies;
  }
  
@@@ -2252,16 -2261,15 +2256,16 @@@ int bond_arp_rcv(const struct sk_buff *
  	struct arphdr *arp = (struct arphdr *)skb->data;
  	unsigned char *arp_ptr;
  	__be32 sip, tip;
 -	int alen;
 +	int alen, is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP);
  
 -	if (skb->protocol != __cpu_to_be16(ETH_P_ARP))
 +	if (!slave_do_arp_validate(bond, slave)) {
 +		if ((slave_do_arp_validate_only(bond, slave) && is_arp) ||
 +		    !slave_do_arp_validate_only(bond, slave))
 +			slave->last_rx = jiffies;
  		return RX_HANDLER_ANOTHER;
 -
 -	read_lock(&bond->lock);
 -
 -	if (!slave_do_arp_validate(bond, slave))
 -		goto out_unlock;
 +	} else if (!is_arp) {
 +		return RX_HANDLER_ANOTHER;
 +	}
  
  	alen = arp_hdr_len(bond->dev);
  
@@@ -2312,10 -2320,11 +2316,10 @@@
  		bond_validate_arp(bond, slave, sip, tip);
  	else if (bond->curr_active_slave &&
  		 time_after(slave_last_rx(bond, bond->curr_active_slave),
 -			    bond->curr_active_slave->jiffies))
 +			    bond->curr_active_slave->last_link_up))
  		bond_validate_arp(bond, slave, tip, sip);
  
  out_unlock:
 -	read_unlock(&bond->lock);
  	if (arp != (struct arphdr *)skb->data)
  		kfree(arp);
  	return RX_HANDLER_ANOTHER;
@@@ -2358,9 -2367,9 +2362,9 @@@ static void bond_loadbalance_arp_mon(st
  	oldcurrent = ACCESS_ONCE(bond->curr_active_slave);
  	/* see if any of the previous devices are up now (i.e. they have
  	 * xmt and rcv traffic). the curr_active_slave does not come into
 -	 * the picture unless it is null. also, slave->jiffies is not needed
 -	 * here because we send an arp on each slave and give a slave as
 -	 * long as it needs to get the tx/rx within the delta.
 +	 * the picture unless it is null. also, slave->last_link_up is not
 +	 * needed here because we send an arp on each slave and give a slave
 +	 * as long as it needs to get the tx/rx within the delta.
  	 * TODO: what about up/down delay in arp mode? it wasn't here before
  	 *       so it can wait
  	 */
@@@ -2369,7 -2378,7 +2373,7 @@@
  
  		if (slave->link != BOND_LINK_UP) {
  			if (bond_time_in_interval(bond, trans_start, 1) &&
 -			    bond_time_in_interval(bond, slave->dev->last_rx, 1)) {
 +			    bond_time_in_interval(bond, slave->last_rx, 1)) {
  
  				slave->link  = BOND_LINK_UP;
  				slave_state_changed = 1;
@@@ -2380,7 -2389,7 +2384,7 @@@
  				 * is closed.
  				 */
  				if (!oldcurrent) {
 -					pr_info("%s: link status definitely up for interface %s, ",
 +					pr_info("%s: link status definitely up for interface %s\n",
  						bond->dev->name,
  						slave->dev->name);
  					do_failover = 1;
@@@ -2398,7 -2407,7 +2402,7 @@@
  			 * if we don't know our ip yet
  			 */
  			if (!bond_time_in_interval(bond, trans_start, 2) ||
 -			    !bond_time_in_interval(bond, slave->dev->last_rx, 2)) {
 +			    !bond_time_in_interval(bond, slave->last_rx, 2)) {
  
  				slave->link  = BOND_LINK_DOWN;
  				slave_state_changed = 1;
@@@ -2406,8 -2415,9 +2410,8 @@@
  				if (slave->link_failure_count < UINT_MAX)
  					slave->link_failure_count++;
  
 -				pr_info("%s: interface %s is now down.\n",
 -					bond->dev->name,
 -					slave->dev->name);
 +				pr_info("%s: interface %s is now down\n",
 +					bond->dev->name, slave->dev->name);
  
  				if (slave == oldcurrent)
  					do_failover = 1;
@@@ -2486,7 -2496,7 +2490,7 @@@ static int bond_ab_arp_inspect(struct b
  		 * active.  This avoids bouncing, as the last receive
  		 * times need a full ARP monitor cycle to be updated.
  		 */
 -		if (bond_time_in_interval(bond, slave->jiffies, 2))
 +		if (bond_time_in_interval(bond, slave->last_link_up, 2))
  			continue;
  
  		/*
@@@ -2556,7 -2566,7 +2560,7 @@@ static void bond_ab_arp_commit(struct b
  					bond->current_arp_slave = NULL;
  				}
  
 -				pr_info("%s: link status definitely up for interface %s.\n",
 +				pr_info("%s: link status definitely up for interface %s\n",
  					bond->dev->name, slave->dev->name);
  
  				if (!bond->curr_active_slave ||
@@@ -2669,7 -2679,7 +2673,7 @@@ static bool bond_ab_arp_probe(struct bo
  
  			bond_set_slave_inactive_flags(slave);
  
 -			pr_info("%s: backup interface %s is now down.\n",
 +			pr_info("%s: backup interface %s is now down\n",
  				bond->dev->name, slave->dev->name);
  		}
  		if (slave == curr_arp_slave)
@@@ -2687,7 -2697,7 +2691,7 @@@
  	new_slave->link = BOND_LINK_BACK;
  	bond_set_slave_active_flags(new_slave);
  	bond_arp_send_all(bond, new_slave);
 -	new_slave->jiffies = jiffies;
 +	new_slave->last_link_up = jiffies;
  	rcu_assign_pointer(bond->current_arp_slave, new_slave);
  	rtnl_unlock();
  
@@@ -2855,12 -2865,15 +2859,15 @@@ static int bond_slave_netdev_event(unsi
  			break;
  		}
  
 -		pr_info("%s: Primary slave changed to %s, reselecting active slave.\n",
 -			bond->dev->name, bond->primary_slave ? slave_dev->name :
 -							       "none");
 +		pr_info("%s: Primary slave changed to %s, reselecting active slave\n",
 +			bond->dev->name,
 +			bond->primary_slave ? slave_dev->name : "none");
+ 
+ 		block_netpoll_tx();
  		write_lock_bh(&bond->curr_slave_lock);
  		bond_select_active_slave(bond);
  		write_unlock_bh(&bond->curr_slave_lock);
+ 		unblock_netpoll_tx();
  		break;
  	case NETDEV_FEAT_CHANGE:
  		bond_compute_features(bond);
@@@ -2890,7 -2903,8 +2897,7 @@@ static int bond_netdev_event(struct not
  	struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
  
  	pr_debug("event_dev: %s, event: %lx\n",
 -		 event_dev ? event_dev->name : "None",
 -		 event);
 +		 event_dev ? event_dev->name : "None", event);
  
  	if (!(event_dev->priv_flags & IFF_BONDING))
  		return NOTIFY_DONE;
@@@ -3057,7 -3071,8 +3064,7 @@@ static int bond_open(struct net_device 
  
  	if (bond->params.arp_interval) {  /* arp interval, in milliseconds. */
  		queue_delayed_work(bond->wq, &bond->arp_work, 0);
 -		if (bond->params.arp_validate)
 -			bond->recv_probe = bond_arp_rcv;
 +		bond->recv_probe = bond_arp_rcv;
  	}
  
  	if (bond->params.mode == BOND_MODE_8023AD) {
@@@ -3344,8 -3359,8 +3351,8 @@@ static int bond_change_mtu(struct net_d
  	struct list_head *iter;
  	int res = 0;
  
 -	pr_debug("bond=%p, name=%s, new_mtu=%d\n", bond,
 -		 (bond_dev ? bond_dev->name : "None"), new_mtu);
 +	pr_debug("bond=%p, name=%s, new_mtu=%d\n",
 +		 bond, bond_dev ? bond_dev->name : "None", new_mtu);
  
  	/* Can't hold bond->lock with bh disabled here since
  	 * some base drivers panic. On the other hand we can't
@@@ -3364,7 -3379,8 +3371,7 @@@
  
  	bond_for_each_slave(bond, slave, iter) {
  		pr_debug("s %p c_m %p\n",
 -			 slave,
 -			 slave->dev->netdev_ops->ndo_change_mtu);
 +			 slave, slave->dev->netdev_ops->ndo_change_mtu);
  
  		res = dev_set_mtu(slave->dev, new_mtu);
  
@@@ -3452,7 -3468,15 +3459,7 @@@ static int bond_set_mac_address(struct 
  	 */
  
  	bond_for_each_slave(bond, slave, iter) {
 -		const struct net_device_ops *slave_ops = slave->dev->netdev_ops;
  		pr_debug("slave %p %s\n", slave, slave->dev->name);
 -
 -		if (slave_ops->ndo_set_mac_address == NULL) {
 -			res = -EOPNOTSUPP;
 -			pr_debug("EOPNOTSUPP %s\n", slave->dev->name);
 -			goto unwind;
 -		}
 -
  		res = dev_set_mac_address(slave->dev, addr);
  		if (res) {
  			/* TODO: consider downing the slave
@@@ -3683,7 -3707,7 +3690,7 @@@ static inline int bond_slave_override(s
  
  
  static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb,
- 			     void *accel_priv)
+ 			     void *accel_priv, select_queue_fallback_t fallback)
  {
  	/*
  	 * This helper function exists to help dev_pick_tx get the correct
@@@ -3918,7 -3942,7 +3925,7 @@@ static void bond_uninit(struct net_devi
  	/* Release the bonded slaves */
  	bond_for_each_slave(bond, slave, iter)
  		__bond_release_one(bond_dev, slave->dev, true);
 -	pr_info("%s: released all slaves\n", bond_dev->name);
 +	pr_info("%s: Released all slaves\n", bond_dev->name);
  
  	list_del(&bond->bond_list);
  
@@@ -3996,7 -4020,7 +4003,7 @@@ static int bond_check_params(struct bon
  		if ((bond_mode != BOND_MODE_XOR) &&
  		    (bond_mode != BOND_MODE_8023AD)) {
  			pr_info("xmit_hash_policy param is irrelevant in mode %s\n",
 -			       bond_mode_name(bond_mode));
 +				bond_mode_name(bond_mode));
  		} else {
  			bond_opt_initstr(&newval, xmit_hash_policy);
  			valptr = bond_opt_parse(bond_opt_get(BOND_OPT_XMIT_HASH),
@@@ -4037,71 -4061,74 +4044,71 @@@
  		}
  		params->ad_select = valptr->value;
  		if (bond_mode != BOND_MODE_8023AD)
 -			pr_warning("ad_select param only affects 802.3ad mode\n");
 +			pr_warn("ad_select param only affects 802.3ad mode\n");
  	} else {
  		params->ad_select = BOND_AD_STABLE;
  	}
  
  	if (max_bonds < 0) {
 -		pr_warning("Warning: max_bonds (%d) not in range %d-%d, so it was reset to BOND_DEFAULT_MAX_BONDS (%d)\n",
 -			   max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS);
 +		pr_warn("Warning: max_bonds (%d) not in range %d-%d, so it was reset to BOND_DEFAULT_MAX_BONDS (%d)\n",
 +			max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS);
  		max_bonds = BOND_DEFAULT_MAX_BONDS;
  	}
  
  	if (miimon < 0) {
 -		pr_warning("Warning: miimon module parameter (%d), not in range 0-%d, so it was reset to 0\n",
 -			   miimon, INT_MAX);
 +		pr_warn("Warning: miimon module parameter (%d), not in range 0-%d, so it was reset to 0\n",
 +			miimon, INT_MAX);
  		miimon = 0;
  	}
  
  	if (updelay < 0) {
 -		pr_warning("Warning: updelay module parameter (%d), not in range 0-%d, so it was reset to 0\n",
 -			   updelay, INT_MAX);
 +		pr_warn("Warning: updelay module parameter (%d), not in range 0-%d, so it was reset to 0\n",
 +			updelay, INT_MAX);
  		updelay = 0;
  	}
  
  	if (downdelay < 0) {
 -		pr_warning("Warning: downdelay module parameter (%d), not in range 0-%d, so it was reset to 0\n",
 -			   downdelay, INT_MAX);
 +		pr_warn("Warning: downdelay module parameter (%d), not in range 0-%d, so it was reset to 0\n",
 +			downdelay, INT_MAX);
  		downdelay = 0;
  	}
  
  	if ((use_carrier != 0) && (use_carrier != 1)) {
 -		pr_warning("Warning: use_carrier module parameter (%d), not of valid value (0/1), so it was set to 1\n",
 -			   use_carrier);
 +		pr_warn("Warning: use_carrier module parameter (%d), not of valid value (0/1), so it was set to 1\n",
 +			use_carrier);
  		use_carrier = 1;
  	}
  
  	if (num_peer_notif < 0 || num_peer_notif > 255) {
 -		pr_warning("Warning: num_grat_arp/num_unsol_na (%d) not in range 0-255 so it was reset to 1\n",
 -			   num_peer_notif);
 +		pr_warn("Warning: num_grat_arp/num_unsol_na (%d) not in range 0-255 so it was reset to 1\n",
 +			num_peer_notif);
  		num_peer_notif = 1;
  	}
  
  	/* reset values for 802.3ad/TLB/ALB */
  	if (BOND_NO_USES_ARP(bond_mode)) {
  		if (!miimon) {
 -			pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure, speed and duplex which are essential for 802.3ad operation\n");
 -			pr_warning("Forcing miimon to 100msec\n");
 +			pr_warn("Warning: miimon must be specified, otherwise bonding will not detect link failure, speed and duplex which are essential for 802.3ad operation\n");
 +			pr_warn("Forcing miimon to 100msec\n");
  			miimon = BOND_DEFAULT_MIIMON;
  		}
  	}
  
  	if (tx_queues < 1 || tx_queues > 255) {
 -		pr_warning("Warning: tx_queues (%d) should be between "
 -			   "1 and 255, resetting to %d\n",
 -			   tx_queues, BOND_DEFAULT_TX_QUEUES);
 +		pr_warn("Warning: tx_queues (%d) should be between 1 and 255, resetting to %d\n",
 +			tx_queues, BOND_DEFAULT_TX_QUEUES);
  		tx_queues = BOND_DEFAULT_TX_QUEUES;
  	}
  
  	if ((all_slaves_active != 0) && (all_slaves_active != 1)) {
 -		pr_warning("Warning: all_slaves_active module parameter (%d), "
 -			   "not of valid value (0/1), so it was set to "
 -			   "0\n", all_slaves_active);
 +		pr_warn("Warning: all_slaves_active module parameter (%d), not of valid value (0/1), so it was set to 0\n",
 +			all_slaves_active);
  		all_slaves_active = 0;
  	}
  
  	if (resend_igmp < 0 || resend_igmp > 255) {
 -		pr_warning("Warning: resend_igmp (%d) should be between "
 -			   "0 and 255, resetting to %d\n",
 -			   resend_igmp, BOND_DEFAULT_RESEND_IGMP);
 +		pr_warn("Warning: resend_igmp (%d) should be between 0 and 255, resetting to %d\n",
 +			resend_igmp, BOND_DEFAULT_RESEND_IGMP);
  		resend_igmp = BOND_DEFAULT_RESEND_IGMP;
  	}
  
@@@ -4122,36 -4149,37 +4129,36 @@@
  			/* just warn the user the up/down delay will have
  			 * no effect since miimon is zero...
  			 */
 -			pr_warning("Warning: miimon module parameter not set and updelay (%d) or downdelay (%d) module parameter is set; updelay and downdelay have no effect unless miimon is set\n",
 -				   updelay, downdelay);
 +			pr_warn("Warning: miimon module parameter not set and updelay (%d) or downdelay (%d) module parameter is set; updelay and downdelay have no effect unless miimon is set\n",
 +				updelay, downdelay);
  		}
  	} else {
  		/* don't allow arp monitoring */
  		if (arp_interval) {
 -			pr_warning("Warning: miimon (%d) and arp_interval (%d) can't be used simultaneously, disabling ARP monitoring\n",
 -				   miimon, arp_interval);
 +			pr_warn("Warning: miimon (%d) and arp_interval (%d) can't be used simultaneously, disabling ARP monitoring\n",
 +				miimon, arp_interval);
  			arp_interval = 0;
  		}
  
  		if ((updelay % miimon) != 0) {
 -			pr_warning("Warning: updelay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
 -				   updelay, miimon,
 -				   (updelay / miimon) * miimon);
 +			pr_warn("Warning: updelay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
 +				updelay, miimon, (updelay / miimon) * miimon);
  		}
  
  		updelay /= miimon;
  
  		if ((downdelay % miimon) != 0) {
 -			pr_warning("Warning: downdelay (%d) is not a multiple of miimon (%d), downdelay rounded to %d ms\n",
 -				   downdelay, miimon,
 -				   (downdelay / miimon) * miimon);
 +			pr_warn("Warning: downdelay (%d) is not a multiple of miimon (%d), downdelay rounded to %d ms\n",
 +				downdelay, miimon,
 +				(downdelay / miimon) * miimon);
  		}
  
  		downdelay /= miimon;
  	}
  
  	if (arp_interval < 0) {
 -		pr_warning("Warning: arp_interval module parameter (%d) , not in range 0-%d, so it was reset to 0\n",
 -			   arp_interval, INT_MAX);
 +		pr_warn("Warning: arp_interval module parameter (%d), not in range 0-%d, so it was reset to 0\n",
 +			arp_interval, INT_MAX);
  		arp_interval = 0;
  	}
  
@@@ -4162,26 -4190,30 +4169,26 @@@
  		__be32 ip;
  		if (!in4_pton(arp_ip_target[i], -1, (u8 *)&ip, -1, NULL) ||
  		    IS_IP_TARGET_UNUSABLE_ADDRESS(ip)) {
 -			pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n",
 -				   arp_ip_target[i]);
 +			pr_warn("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n",
 +				arp_ip_target[i]);
  			arp_interval = 0;
  		} else {
  			if (bond_get_targets_ip(arp_target, ip) == -1)
  				arp_target[arp_ip_count++] = ip;
  			else
 -				pr_warning("Warning: duplicate address %pI4 in arp_ip_target, skipping\n",
 -					   &ip);
 +				pr_warn("Warning: duplicate address %pI4 in arp_ip_target, skipping\n",
 +					&ip);
  		}
  	}
  
  	if (arp_interval && !arp_ip_count) {
  		/* don't allow arping if no arp_ip_target given... */
 -		pr_warning("Warning: arp_interval module parameter (%d) specified without providing an arp_ip_target parameter, arp_interval was reset to 0\n",
 -			   arp_interval);
 +		pr_warn("Warning: arp_interval module parameter (%d) specified without providing an arp_ip_target parameter, arp_interval was reset to 0\n",
 +			arp_interval);
  		arp_interval = 0;
  	}
  
  	if (arp_validate) {
 -		if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
 -			pr_err("arp_validate only supported in active-backup mode\n");
 -			return -EINVAL;
 -		}
  		if (!arp_interval) {
  			pr_err("arp_validate requires arp_interval\n");
  			return -EINVAL;
@@@ -4223,23 -4255,23 +4230,23 @@@
  			arp_interval, valptr->string, arp_ip_count);
  
  		for (i = 0; i < arp_ip_count; i++)
 -			pr_info(" %s", arp_ip_target[i]);
 +			pr_cont(" %s", arp_ip_target[i]);
  
 -		pr_info("\n");
 +		pr_cont("\n");
  
  	} else if (max_bonds) {
  		/* miimon and arp_interval not set, we need one so things
  		 * work as expected, see bonding.txt for details
  		 */
 -		pr_debug("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n");
 +		pr_debug("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details\n");
  	}
  
  	if (primary && !USES_PRIMARY(bond_mode)) {
  		/* currently, using a primary only makes sense
  		 * in active backup, TLB or ALB modes
  		 */
 -		pr_warning("Warning: %s primary device specified but has no effect in %s mode\n",
 -			   primary, bond_mode_name(bond_mode));
 +		pr_warn("Warning: %s primary device specified but has no effect in %s mode\n",
 +			primary, bond_mode_name(bond_mode));
  		primary = NULL;
  	}
  
@@@ -4268,14 -4300,14 +4275,14 @@@
  		}
  		fail_over_mac_value = valptr->value;
  		if (bond_mode != BOND_MODE_ACTIVEBACKUP)
 -			pr_warning("Warning: fail_over_mac only affects active-backup mode.\n");
 +			pr_warn("Warning: fail_over_mac only affects active-backup mode\n");
  	} else {
  		fail_over_mac_value = BOND_FOM_NONE;
  	}
  
  	if (lp_interval == 0) {
 -		pr_warning("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n",
 -			   INT_MAX, BOND_ALB_DEFAULT_LP_INTERVAL);
 +		pr_warn("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n",
 +			INT_MAX, BOND_ALB_DEFAULT_LP_INTERVAL);
  		lp_interval = BOND_ALB_DEFAULT_LP_INTERVAL;
  	}
  
diff --combined drivers/net/bonding/bond_options.c
index 5f997b9,c378784..23f3655
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@@ -14,7 -14,7 +14,7 @@@
  #include <linux/errno.h>
  #include <linux/if.h>
  #include <linux/netdevice.h>
- #include <linux/rwlock.h>
+ #include <linux/spinlock.h>
  #include <linux/rcupdate.h>
  #include <linux/ctype.h>
  #include <linux/inet.h>
@@@ -47,14 -47,11 +47,14 @@@ static struct bond_opt_value bond_xmit_
  };
  
  static struct bond_opt_value bond_arp_validate_tbl[] = {
 -	{ "none",   BOND_ARP_VALIDATE_NONE,   BOND_VALFLAG_DEFAULT},
 -	{ "active", BOND_ARP_VALIDATE_ACTIVE, 0},
 -	{ "backup", BOND_ARP_VALIDATE_BACKUP, 0},
 -	{ "all",    BOND_ARP_VALIDATE_ALL,    0},
 -	{ NULL,     -1,                       0},
 +	{ "none",		BOND_ARP_VALIDATE_NONE,		BOND_VALFLAG_DEFAULT},
 +	{ "active",		BOND_ARP_VALIDATE_ACTIVE,	0},
 +	{ "backup",		BOND_ARP_VALIDATE_BACKUP,	0},
 +	{ "all",		BOND_ARP_VALIDATE_ALL,		0},
 +	{ "filter",		BOND_ARP_FILTER,		0},
 +	{ "filter_active",	BOND_ARP_FILTER_ACTIVE,		0},
 +	{ "filter_backup",	BOND_ARP_FILTER_BACKUP,		0},
 +	{ NULL,			-1,				0},
  };
  
  static struct bond_opt_value bond_arp_all_targets_tbl[] = {
@@@ -154,8 -151,7 +154,8 @@@ static struct bond_option bond_opts[] 
  		.id = BOND_OPT_ARP_VALIDATE,
  		.name = "arp_validate",
  		.desc = "validate src/dst of ARP probes",
 -		.unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_ACTIVEBACKUP)),
 +		.unsuppmodes = BIT(BOND_MODE_8023AD) | BIT(BOND_MODE_TLB) |
 +			       BIT(BOND_MODE_ALB),
  		.values = bond_arp_validate_tbl,
  		.set = bond_option_arp_validate_set
  	},
@@@ -477,10 -473,10 +477,10 @@@ static void bond_opt_error_interpret(st
  				p = strchr(val->string, '\n');
  				if (p)
  					*p = '\0';
 -				pr_err("%s: option %s: invalid value (%s).\n",
 +				pr_err("%s: option %s: invalid value (%s)\n",
  				       bond->dev->name, opt->name, val->string);
  			} else {
 -				pr_err("%s: option %s: invalid value (%llu).\n",
 +				pr_err("%s: option %s: invalid value (%llu)\n",
  				       bond->dev->name, opt->name, val->value);
  			}
  		}
@@@ -488,7 -484,7 +488,7 @@@
  		maxval = bond_opt_get_flags(opt, BOND_VALFLAG_MAX);
  		if (!maxval)
  			break;
 -		pr_err("%s: option %s: allowed values %llu - %llu.\n",
 +		pr_err("%s: option %s: allowed values %llu - %llu\n",
  		       bond->dev->name, opt->name, minval ? minval->value : 0,
  		       maxval->value);
  		break;
@@@ -496,11 -492,11 +496,11 @@@
  		bond_opt_dep_print(bond, opt);
  		break;
  	case -ENOTEMPTY:
 -		pr_err("%s: option %s: unable to set because the bond device has slaves.\n",
 +		pr_err("%s: option %s: unable to set because the bond device has slaves\n",
  		       bond->dev->name, opt->name);
  		break;
  	case -EBUSY:
 -		pr_err("%s: option %s: unable to set because the bond device is up.\n",
 +		pr_err("%s: option %s: unable to set because the bond device is up\n",
  		       bond->dev->name, opt->name);
  		break;
  	default:
@@@ -593,7 -589,7 +593,7 @@@ int bond_option_mode_set(struct bondin
  		bond->params.arp_interval = 0;
  		/* set miimon to default value */
  		bond->params.miimon = BOND_DEFAULT_MIIMON;
 -		pr_info("%s: Setting MII monitoring interval to %d.\n",
 +		pr_info("%s: Setting MII monitoring interval to %d\n",
  			bond->dev->name, bond->params.miimon);
  	}
  
@@@ -640,13 -636,13 +640,13 @@@ int bond_option_active_slave_set(struc
  
  	if (slave_dev) {
  		if (!netif_is_bond_slave(slave_dev)) {
 -			pr_err("Device %s is not bonding slave.\n",
 +			pr_err("Device %s is not bonding slave\n",
  			       slave_dev->name);
  			return -EINVAL;
  		}
  
  		if (bond->dev != netdev_master_upper_dev_get(slave_dev)) {
 -			pr_err("%s: Device %s is not our slave.\n",
 +			pr_err("%s: Device %s is not our slave\n",
  			       bond->dev->name, slave_dev->name);
  			return -EINVAL;
  		}
@@@ -657,7 -653,8 +657,7 @@@
  
  	/* check to see if we are clearing active */
  	if (!slave_dev) {
 -		pr_info("%s: Clearing current active slave.\n",
 -		bond->dev->name);
 +		pr_info("%s: Clearing current active slave\n", bond->dev->name);
  		rcu_assign_pointer(bond->curr_active_slave, NULL);
  		bond_select_active_slave(bond);
  	} else {
@@@ -668,16 -665,16 +668,16 @@@
  
  		if (new_active == old_active) {
  			/* do nothing */
 -			pr_info("%s: %s is already the current active slave.\n",
 +			pr_info("%s: %s is already the current active slave\n",
  				bond->dev->name, new_active->dev->name);
  		} else {
  			if (old_active && (new_active->link == BOND_LINK_UP) &&
  			    IS_UP(new_active->dev)) {
 -				pr_info("%s: Setting %s as active slave.\n",
 +				pr_info("%s: Setting %s as active slave\n",
  					bond->dev->name, new_active->dev->name);
  				bond_change_active_slave(bond, new_active);
  			} else {
 -				pr_err("%s: Could not set %s as active slave; either %s is down or the link is down.\n",
 +				pr_err("%s: Could not set %s as active slave; either %s is down or the link is down\n",
  				       bond->dev->name, new_active->dev->name,
  				       new_active->dev->name);
  				ret = -EINVAL;
@@@ -693,19 -690,19 +693,19 @@@
  
  int bond_option_miimon_set(struct bonding *bond, struct bond_opt_value *newval)
  {
 -	pr_info("%s: Setting MII monitoring interval to %llu.\n",
 +	pr_info("%s: Setting MII monitoring interval to %llu\n",
  		bond->dev->name, newval->value);
  	bond->params.miimon = newval->value;
  	if (bond->params.updelay)
 -		pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
 +		pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value\n",
  			bond->dev->name,
  			bond->params.updelay * bond->params.miimon);
  	if (bond->params.downdelay)
 -		pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
 +		pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n",
  			bond->dev->name,
  			bond->params.downdelay * bond->params.miimon);
  	if (newval->value && bond->params.arp_interval) {
 -		pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
 +		pr_info("%s: MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n",
  			bond->dev->name);
  		bond->params.arp_interval = 0;
  		if (bond->params.arp_validate)
@@@ -745,8 -742,9 +745,8 @@@ int bond_option_updelay_set(struct bond
  			bond->params.miimon);
  	}
  	bond->params.updelay = value / bond->params.miimon;
 -	pr_info("%s: Setting up delay to %d.\n",
 -		bond->dev->name,
 -		bond->params.updelay * bond->params.miimon);
 +	pr_info("%s: Setting up delay to %d\n",
 +		bond->dev->name, bond->params.updelay * bond->params.miimon);
  
  	return 0;
  }
@@@ -769,8 -767,9 +769,8 @@@ int bond_option_downdelay_set(struct bo
  			bond->params.miimon);
  	}
  	bond->params.downdelay = value / bond->params.miimon;
 -	pr_info("%s: Setting down delay to %d.\n",
 -		bond->dev->name,
 -		bond->params.downdelay * bond->params.miimon);
 +	pr_info("%s: Setting down delay to %d\n",
 +		bond->dev->name, bond->params.downdelay * bond->params.miimon);
  
  	return 0;
  }
@@@ -778,7 -777,7 +778,7 @@@
  int bond_option_use_carrier_set(struct bonding *bond,
  				struct bond_opt_value *newval)
  {
 -	pr_info("%s: Setting use_carrier to %llu.\n",
 +	pr_info("%s: Setting use_carrier to %llu\n",
  		bond->dev->name, newval->value);
  	bond->params.use_carrier = newval->value;
  
@@@ -788,17 -787,17 +788,17 @@@
  int bond_option_arp_interval_set(struct bonding *bond,
  				 struct bond_opt_value *newval)
  {
 -	pr_info("%s: Setting ARP monitoring interval to %llu.\n",
 +	pr_info("%s: Setting ARP monitoring interval to %llu\n",
  		bond->dev->name, newval->value);
  	bond->params.arp_interval = newval->value;
  	if (newval->value) {
  		if (bond->params.miimon) {
 -			pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
 +			pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring\n",
  				bond->dev->name, bond->dev->name);
  			bond->params.miimon = 0;
  		}
  		if (!bond->params.arp_targets[0])
 -			pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
 +			pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified\n",
  				bond->dev->name);
  	}
  	if (bond->dev->flags & IFF_UP) {
@@@ -813,7 -812,8 +813,7 @@@
  			cancel_delayed_work_sync(&bond->arp_work);
  		} else {
  			/* arp_validate can be set only in active-backup mode */
 -			if (bond->params.arp_validate)
 -				bond->recv_probe = bond_arp_rcv;
 +			bond->recv_probe = bond_arp_rcv;
  			cancel_delayed_work_sync(&bond->mii_work);
  			queue_delayed_work(bond->wq, &bond->arp_work, 0);
  		}
@@@ -856,11 -856,12 +856,11 @@@ static int _bond_option_arp_ip_target_a
  
  	ind = bond_get_targets_ip(targets, 0); /* first free slot */
  	if (ind == -1) {
 -		pr_err("%s: ARP target table is full!\n",
 -		       bond->dev->name);
 +		pr_err("%s: ARP target table is full!\n", bond->dev->name);
  		return -EINVAL;
  	}
  
 -	pr_info("%s: adding ARP target %pI4.\n", bond->dev->name, &target);
 +	pr_info("%s: Adding ARP target %pI4\n", bond->dev->name, &target);
  
  	_bond_options_arp_ip_target_set(bond, ind, target, jiffies);
  
@@@ -895,16 -896,17 +895,16 @@@ int bond_option_arp_ip_target_rem(struc
  
  	ind = bond_get_targets_ip(targets, target);
  	if (ind == -1) {
 -		pr_err("%s: unable to remove nonexistent ARP target %pI4.\n",
 +		pr_err("%s: unable to remove nonexistent ARP target %pI4\n",
  		       bond->dev->name, &target);
  		return -EINVAL;
  	}
  
  	if (ind == 0 && !targets[1] && bond->params.arp_interval)
 -		pr_warn("%s: removing last arp target with arp_interval on\n",
 +		pr_warn("%s: Removing last arp target with arp_interval on\n",
  			bond->dev->name);
  
 -	pr_info("%s: removing ARP target %pI4.\n", bond->dev->name,
 -		&target);
 +	pr_info("%s: Removing ARP target %pI4\n", bond->dev->name, &target);
  
  	/* not to race with bond_arp_rcv */
  	write_lock_bh(&bond->lock);
@@@ -952,7 -954,7 +952,7 @@@ int bond_option_arp_ip_targets_set(stru
  		else if (newval->string[0] == '-')
  			ret = bond_option_arp_ip_target_rem(bond, target);
  		else
 -			pr_err("no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
 +			pr_err("no command found in arp_ip_targets file for bond %s - use +<addr> or -<addr>\n",
  			       bond->dev->name);
  	} else {
  		target = newval->value;
@@@ -965,7 -967,7 +965,7 @@@
  int bond_option_arp_validate_set(struct bonding *bond,
  				 struct bond_opt_value *newval)
  {
 -	pr_info("%s: setting arp_validate to %s (%llu).\n",
 +	pr_info("%s: Setting arp_validate to %s (%llu)\n",
  		bond->dev->name, newval->string, newval->value);
  
  	if (bond->dev->flags & IFF_UP) {
@@@ -982,7 -984,7 +982,7 @@@
  int bond_option_arp_all_targets_set(struct bonding *bond,
  				    struct bond_opt_value *newval)
  {
 -	pr_info("%s: setting arp_all_targets to %s (%llu).\n",
 +	pr_info("%s: Setting arp_all_targets to %s (%llu)\n",
  		bond->dev->name, newval->string, newval->value);
  	bond->params.arp_all_targets = newval->value;
  
@@@ -1004,7 -1006,8 +1004,7 @@@ int bond_option_primary_set(struct bond
  		*p = '\0';
  	/* check to see if we are clearing primary */
  	if (!strlen(primary)) {
 -		pr_info("%s: Setting primary slave to None.\n",
 -			bond->dev->name);
 +		pr_info("%s: Setting primary slave to None\n", bond->dev->name);
  		bond->primary_slave = NULL;
  		memset(bond->params.primary, 0, sizeof(bond->params.primary));
  		bond_select_active_slave(bond);
@@@ -1013,7 -1016,7 +1013,7 @@@
  
  	bond_for_each_slave(bond, slave, iter) {
  		if (strncmp(slave->dev->name, primary, IFNAMSIZ) == 0) {
 -			pr_info("%s: Setting %s as primary slave.\n",
 +			pr_info("%s: Setting %s as primary slave\n",
  				bond->dev->name, slave->dev->name);
  			bond->primary_slave = slave;
  			strcpy(bond->params.primary, slave->dev->name);
@@@ -1023,14 -1026,15 +1023,14 @@@
  	}
  
  	if (bond->primary_slave) {
 -		pr_info("%s: Setting primary slave to None.\n",
 -			bond->dev->name);
 +		pr_info("%s: Setting primary slave to None\n", bond->dev->name);
  		bond->primary_slave = NULL;
  		bond_select_active_slave(bond);
  	}
  	strncpy(bond->params.primary, primary, IFNAMSIZ);
  	bond->params.primary[IFNAMSIZ - 1] = 0;
  
 -	pr_info("%s: Recording %s as primary, but it has not been enslaved to %s yet.\n",
 +	pr_info("%s: Recording %s as primary, but it has not been enslaved to %s yet\n",
  		bond->dev->name, primary, bond->dev->name);
  
  out:
@@@ -1044,7 -1048,7 +1044,7 @@@
  int bond_option_primary_reselect_set(struct bonding *bond,
  				     struct bond_opt_value *newval)
  {
 -	pr_info("%s: setting primary_reselect to %s (%llu).\n",
 +	pr_info("%s: Setting primary_reselect to %s (%llu)\n",
  		bond->dev->name, newval->string, newval->value);
  	bond->params.primary_reselect = newval->value;
  
@@@ -1060,7 -1064,7 +1060,7 @@@
  int bond_option_fail_over_mac_set(struct bonding *bond,
  				  struct bond_opt_value *newval)
  {
 -	pr_info("%s: Setting fail_over_mac to %s (%llu).\n",
 +	pr_info("%s: Setting fail_over_mac to %s (%llu)\n",
  		bond->dev->name, newval->string, newval->value);
  	bond->params.fail_over_mac = newval->value;
  
@@@ -1070,7 -1074,7 +1070,7 @@@
  int bond_option_xmit_hash_policy_set(struct bonding *bond,
  				     struct bond_opt_value *newval)
  {
 -	pr_info("%s: setting xmit hash policy to %s (%llu).\n",
 +	pr_info("%s: Setting xmit hash policy to %s (%llu)\n",
  		bond->dev->name, newval->string, newval->value);
  	bond->params.xmit_policy = newval->value;
  
@@@ -1080,7 -1084,7 +1080,7 @@@
  int bond_option_resend_igmp_set(struct bonding *bond,
  				struct bond_opt_value *newval)
  {
 -	pr_info("%s: Setting resend_igmp to %llu.\n",
 +	pr_info("%s: Setting resend_igmp to %llu\n",
  		bond->dev->name, newval->value);
  	bond->params.resend_igmp = newval->value;
  
@@@ -1154,7 -1158,7 +1154,7 @@@ int bond_option_pps_set(struct bonding 
  int bond_option_lacp_rate_set(struct bonding *bond,
  			      struct bond_opt_value *newval)
  {
 -	pr_info("%s: Setting LACP rate to %s (%llu).\n",
 +	pr_info("%s: Setting LACP rate to %s (%llu)\n",
  		bond->dev->name, newval->string, newval->value);
  	bond->params.lacp_fast = newval->value;
  	bond_3ad_update_lacp_rate(bond);
@@@ -1165,7 -1169,7 +1165,7 @@@
  int bond_option_ad_select_set(struct bonding *bond,
  			      struct bond_opt_value *newval)
  {
 -	pr_info("%s: Setting ad_select to %s (%llu).\n",
 +	pr_info("%s: Setting ad_select to %s (%llu)\n",
  		bond->dev->name, newval->string, newval->value);
  	bond->params.ad_select = newval->value;
  
@@@ -1195,7 -1199,8 +1195,7 @@@ int bond_option_queue_id_set(struct bon
  		goto err_no_cmd;
  
  	/* Check buffer length, valid ifname and queue id */
 -	if (strlen(newval->string) > IFNAMSIZ ||
 -	    !dev_valid_name(newval->string) ||
 +	if (!dev_valid_name(newval->string) ||
  	    qid > bond->dev->real_num_tx_queues)
  		goto err_no_cmd;
  
@@@ -1227,7 -1232,8 +1227,7 @@@ out
  	return ret;
  
  err_no_cmd:
 -	pr_info("invalid input for queue_id set for %s.\n",
 -		bond->dev->name);
 +	pr_info("invalid input for queue_id set for %s\n", bond->dev->name);
  	ret = -EPERM;
  	goto out;
  
@@@ -1248,7 -1254,7 +1248,7 @@@ int bond_option_slaves_set(struct bondi
  
  	dev = __dev_get_by_name(dev_net(bond->dev), ifname);
  	if (!dev) {
 -		pr_info("%s: Interface %s does not exist!\n",
 +		pr_info("%s: interface %s does not exist!\n",
  			bond->dev->name, ifname);
  		ret = -ENODEV;
  		goto out;
@@@ -1256,12 -1262,12 +1256,12 @@@
  
  	switch (command[0]) {
  	case '+':
 -		pr_info("%s: Adding slave %s.\n", bond->dev->name, dev->name);
 +		pr_info("%s: Adding slave %s\n", bond->dev->name, dev->name);
  		ret = bond_enslave(bond->dev, dev);
  		break;
  
  	case '-':
 -		pr_info("%s: Removing slave %s.\n", bond->dev->name, dev->name);
 +		pr_info("%s: Removing slave %s\n", bond->dev->name, dev->name);
  		ret = bond_release(bond->dev, dev);
  		break;
  
@@@ -1273,7 -1279,7 +1273,7 @@@ out
  	return ret;
  
  err_no_cmd:
 -	pr_err("no command found in slaves file for bond %s. Use +ifname or -ifname.\n",
 +	pr_err("no command found in slaves file for bond %s - use +ifname or -ifname\n",
  	       bond->dev->name);
  	ret = -EPERM;
  	goto out;
diff --combined drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 8363b9d,66c0df7..5ee13af
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@@ -1638,16 -1638,36 +1638,16 @@@ int bnx2x_enable_msix(struct bnx2x *bp
  	DP(BNX2X_MSG_SP, "about to request enable msix with %d vectors\n",
  	   msix_vec);
  
 -	rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], msix_vec);
 -
 +	rc = pci_enable_msix_range(bp->pdev, &bp->msix_table[0],
 +				   BNX2X_MIN_MSIX_VEC_CNT(bp), msix_vec);
  	/*
  	 * reconfigure number of tx/rx queues according to available
  	 * MSI-X vectors
  	 */
 -	if (rc >= BNX2X_MIN_MSIX_VEC_CNT(bp)) {
 -		/* how less vectors we will have? */
 -		int diff = msix_vec - rc;
 -
 -		BNX2X_DEV_INFO("Trying to use less MSI-X vectors: %d\n", rc);
 -
 -		rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], rc);
 -
 -		if (rc) {
 -			BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc);
 -			goto no_msix;
 -		}
 -		/*
 -		 * decrease number of queues by number of unallocated entries
 -		 */
 -		bp->num_ethernet_queues -= diff;
 -		bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
 -
 -		BNX2X_DEV_INFO("New queue configuration set: %d\n",
 -			       bp->num_queues);
 -	} else if (rc > 0) {
 +	if (rc == -ENOSPC) {
  		/* Get by with single vector */
 -		rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], 1);
 -		if (rc) {
 +		rc = pci_enable_msix_range(bp->pdev, &bp->msix_table[0], 1, 1);
 +		if (rc < 0) {
  			BNX2X_DEV_INFO("Single MSI-X is not attainable rc %d\n",
  				       rc);
  			goto no_msix;
@@@ -1660,22 -1680,8 +1660,22 @@@
  		bp->num_ethernet_queues = 1;
  		bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
  	} else if (rc < 0) {
 -		BNX2X_DEV_INFO("MSI-X is not attainable  rc %d\n", rc);
 +		BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc);
  		goto no_msix;
 +	} else if (rc < msix_vec) {
 +		/* how less vectors we will have? */
 +		int diff = msix_vec - rc;
 +
 +		BNX2X_DEV_INFO("Trying to use less MSI-X vectors: %d\n", rc);
 +
 +		/*
 +		 * decrease number of queues by number of unallocated entries
 +		 */
 +		bp->num_ethernet_queues -= diff;
 +		bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
 +
 +		BNX2X_DEV_INFO("New queue configuration set: %d\n",
 +			       bp->num_queues);
  	}
  
  	bp->flags |= USING_MSIX_FLAG;
@@@ -1867,7 -1873,7 +1867,7 @@@ void bnx2x_netif_stop(struct bnx2x *bp
  }
  
  u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
- 		       void *accel_priv)
+ 		       void *accel_priv, select_queue_fallback_t fallback)
  {
  	struct bnx2x *bp = netdev_priv(dev);
  
@@@ -1889,7 -1895,7 +1889,7 @@@
  	}
  
  	/* select a non-FCoE queue */
- 	return __netdev_pick_tx(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
+ 	return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
  }
  
  void bnx2x_set_num_queues(struct bnx2x *bp)
@@@ -4767,8 -4773,12 +4767,8 @@@ void bnx2x_tx_timeout(struct net_devic
  		bnx2x_panic();
  #endif
  
 -	smp_mb__before_clear_bit();
 -	set_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state);
 -	smp_mb__after_clear_bit();
 -
  	/* This allows the netif to be shutdown gracefully before resetting */
 -	schedule_delayed_work(&bp->sp_rtnl_task, 0);
 +	bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_TX_TIMEOUT, 0);
  }
  
  int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state)
@@@ -4896,15 -4906,3 +4896,15 @@@ void bnx2x_update_coalesce_sb_index(str
  	disable = disable ? 1 : (usec ? 0 : 1);
  	storm_memset_hc_disable(bp, port, fw_sb_id, sb_index, disable);
  }
 +
 +void bnx2x_schedule_sp_rtnl(struct bnx2x *bp, enum sp_rtnl_flag flag,
 +			    u32 verbose)
 +{
 +	smp_mb__before_clear_bit();
 +	set_bit(flag, &bp->sp_rtnl_state);
 +	smp_mb__after_clear_bit();
 +	DP((BNX2X_MSG_SP | verbose), "Scheduling sp_rtnl task [Flag: %d]\n",
 +	   flag);
 +	schedule_delayed_work(&bp->sp_rtnl_task, 0);
 +}
 +EXPORT_SYMBOL(bnx2x_schedule_sp_rtnl);
diff --combined drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 5135cc7,a89a40f..ec02b15
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@@ -496,7 -496,7 +496,7 @@@ int bnx2x_set_vf_vlan(struct net_devic
  
  /* select_queue callback */
  u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
- 		       void *accel_priv);
+ 		       void *accel_priv, select_queue_fallback_t fallback);
  
  static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
  					struct bnx2x_fastpath *fp,
@@@ -1324,7 -1324,4 +1324,7 @@@ void bnx2x_fill_fw_str(struct bnx2x *bp
  int bnx2x_drain_tx_queues(struct bnx2x *bp);
  void bnx2x_squeeze_objects(struct bnx2x *bp);
  
 +void bnx2x_schedule_sp_rtnl(struct bnx2x*, enum sp_rtnl_flag,
 +			    u32 verbose);
 +
  #endif /* BNX2X_CMN_H */
diff --combined drivers/net/ethernet/ti/cpsw.c
index 39d1253,651087b..0b6a280
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@@ -554,7 -554,7 +554,7 @@@ static void cpsw_set_promiscious(struc
  		 * common for both the interface as the interface shares
  		 * the same hardware resource.
  		 */
- 		for (i = 0; i <= priv->data.slaves; i++)
+ 		for (i = 0; i < priv->data.slaves; i++)
  			if (priv->slaves[i].ndev->flags & IFF_PROMISC)
  				flag = true;
  
@@@ -578,7 -578,7 +578,7 @@@
  			unsigned long timeout = jiffies + HZ;
  
  			/* Disable Learn for all ports */
- 			for (i = 0; i <= priv->data.slaves; i++) {
+ 			for (i = 0; i < priv->data.slaves; i++) {
  				cpsw_ale_control_set(ale, i,
  						     ALE_PORT_NOLEARN, 1);
  				cpsw_ale_control_set(ale, i,
@@@ -606,7 -606,7 +606,7 @@@
  			cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 0);
  
  			/* Enable Learn for all ports */
- 			for (i = 0; i <= priv->data.slaves; i++) {
+ 			for (i = 0; i < priv->data.slaves; i++) {
  				cpsw_ale_control_set(ale, i,
  						     ALE_PORT_NOLEARN, 0);
  				cpsw_ale_control_set(ale, i,
@@@ -1471,6 -1471,7 +1471,6 @@@ static int cpsw_hwtstamp_get(struct net
  static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
  {
  	struct cpsw_priv *priv = netdev_priv(dev);
 -	struct mii_ioctl_data *data = if_mii(req);
  	int slave_no = cpsw_slave_index(priv);
  
  	if (!netif_running(dev))
@@@ -1483,11 -1484,14 +1483,11 @@@
  	case SIOCGHWTSTAMP:
  		return cpsw_hwtstamp_get(dev, req);
  #endif
 -	case SIOCGMIIPHY:
 -		data->phy_id = priv->slaves[slave_no].phy->addr;
 -		break;
 -	default:
 -		return -ENOTSUPP;
  	}
  
 -	return 0;
 +	if (!priv->slaves[slave_no].phy)
 +		return -EOPNOTSUPP;
 +	return phy_mii_ioctl(priv->slaves[slave_no].phy, req, cmd);
  }
  
  static void cpsw_ndo_tx_timeout(struct net_device *ndev)
@@@ -1892,6 -1896,11 +1892,11 @@@ static int cpsw_probe_dt(struct cpsw_pl
  			memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
  
  		slave_data->phy_if = of_get_phy_mode(slave_node);
+ 		if (slave_data->phy_if < 0) {
+ 			pr_err("Missing or malformed slave[%d] phy-mode property\n",
+ 			       i);
+ 			return slave_data->phy_if;
+ 		}
  
  		if (data->dual_emac) {
  			if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
diff --combined drivers/net/hyperv/netvsc_drv.c
index 1eadc13,7141a19..bcd2df2
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@@ -88,8 -88,12 +88,12 @@@ static int netvsc_open(struct net_devic
  {
  	struct net_device_context *net_device_ctx = netdev_priv(net);
  	struct hv_device *device_obj = net_device_ctx->device_ctx;
+ 	struct netvsc_device *nvdev;
+ 	struct rndis_device *rdev;
  	int ret = 0;
  
+ 	netif_carrier_off(net);
+ 
  	/* Open up the device */
  	ret = rndis_filter_open(device_obj);
  	if (ret != 0) {
@@@ -99,6 -103,11 +103,11 @@@
  
  	netif_start_queue(net);
  
+ 	nvdev = hv_get_drvdata(device_obj);
+ 	rdev = nvdev->extension;
+ 	if (!rdev->link_state)
+ 		netif_carrier_on(net);
+ 
  	return ret;
  }
  
@@@ -146,7 -155,7 +155,7 @@@ static int netvsc_start_xmit(struct sk_
  	/* Allocate a netvsc packet based on # of frags. */
  	packet = kzalloc(sizeof(struct hv_netvsc_packet) +
  			 (num_pages * sizeof(struct hv_page_buffer)) +
 -			 sizeof(struct rndis_filter_packet) +
 +			 sizeof(struct rndis_message) +
  			 NDIS_VLAN_PPI_SIZE, GFP_ATOMIC);
  	if (!packet) {
  		/* out of memory, drop packet */
@@@ -229,23 -238,24 +238,24 @@@ void netvsc_linkstatus_callback(struct 
  	struct net_device *net;
  	struct net_device_context *ndev_ctx;
  	struct netvsc_device *net_device;
+ 	struct rndis_device *rdev;
  
  	net_device = hv_get_drvdata(device_obj);
+ 	rdev = net_device->extension;
+ 
+ 	rdev->link_state = status != 1;
+ 
  	net = net_device->ndev;
  
- 	if (!net) {
- 		netdev_err(net, "got link status but net device "
- 				"not initialized yet\n");
+ 	if (!net || net->reg_state != NETREG_REGISTERED)
  		return;
- 	}
  
+ 	ndev_ctx = netdev_priv(net);
  	if (status == 1) {
  		schedule_delayed_work(&ndev_ctx->dwork, 0);
  		schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
  	} else {
- 		netif_carrier_off(net);
+ 		schedule_delayed_work(&ndev_ctx->dwork, 0);
  	}
  }
  
@@@ -388,17 -398,35 +398,35 @@@ static const struct net_device_ops devi
   * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
   * another netif_notify_peers() into a delayed work, otherwise GARP packet
   * will not be sent after quick migration, and cause network disconnection.
+  * Also, we update the carrier status here.
   */
- static void netvsc_send_garp(struct work_struct *w)
+ static void netvsc_link_change(struct work_struct *w)
  {
  	struct net_device_context *ndev_ctx;
  	struct net_device *net;
  	struct netvsc_device *net_device;
+ 	struct rndis_device *rdev;
+ 	bool notify;
+ 
+ 	rtnl_lock();
  
  	ndev_ctx = container_of(w, struct net_device_context, dwork.work);
  	net_device = hv_get_drvdata(ndev_ctx->device_ctx);
+ 	rdev = net_device->extension;
  	net = net_device->ndev;
- 	netdev_notify_peers(net);
+ 
+ 	if (rdev->link_state) {
+ 		netif_carrier_off(net);
+ 		notify = false;
+ 	} else {
+ 		netif_carrier_on(net);
+ 		notify = true;
+ 	}
+ 
+ 	rtnl_unlock();
+ 
+ 	if (notify)
+ 		netdev_notify_peers(net);
  }
  
  
@@@ -414,13 -442,10 +442,10 @@@ static int netvsc_probe(struct hv_devic
  	if (!net)
  		return -ENOMEM;
  
  	net_device_ctx = netdev_priv(net);
  	net_device_ctx->device_ctx = dev;
  	hv_set_drvdata(dev, net);
- 	INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
+ 	INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
  	INIT_WORK(&net_device_ctx->work, do_set_multicast);
  
  	net->netdev_ops = &device_ops;
@@@ -443,8 -468,6 +468,6 @@@
  	}
  	memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
  
- 	netif_carrier_on(net);
- 
  	ret = register_netdev(net);
  	if (ret != 0) {
  		pr_err("Unable to register netdev.\n");
diff --combined drivers/net/macvlan.c
index 25685e3,a5d2189..44227c2
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@@ -534,6 -534,7 +534,6 @@@ static int macvlan_init(struct net_devi
  {
  	struct macvlan_dev *vlan = netdev_priv(dev);
  	const struct net_device *lowerdev = vlan->lowerdev;
 -	int i;
  
  	dev->state		= (dev->state & ~MACVLAN_STATE_MASK) |
  				  (lowerdev->state & MACVLAN_STATE_MASK);
@@@ -545,10 -546,16 +545,10 @@@
  
  	macvlan_set_lockdep_class(dev);
  
 -	vlan->pcpu_stats = alloc_percpu(struct vlan_pcpu_stats);
 +	vlan->pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
  	if (!vlan->pcpu_stats)
  		return -ENOMEM;
  
 -	for_each_possible_cpu(i) {
 -		struct vlan_pcpu_stats *mvlstats;
 -		mvlstats = per_cpu_ptr(vlan->pcpu_stats, i);
 -		u64_stats_init(&mvlstats->syncp);
 -	}
 -
  	return 0;
  }
  
@@@ -872,14 -879,15 +872,15 @@@ int macvlan_common_newlink(struct net *
  	dev->priv_flags |= IFF_MACVLAN;
  	err = netdev_upper_dev_link(lowerdev, dev);
  	if (err)
- 		goto destroy_port;
- 
+ 		goto unregister_netdev;
  
  	list_add_tail_rcu(&vlan->list, &port->vlans);
  	netif_stacked_transfer_operstate(lowerdev, dev);
  
  	return 0;
  
+ unregister_netdev:
+ 	unregister_netdevice(dev);
  destroy_port:
  	port->count -= 1;
  	if (!port->count)
diff --combined drivers/net/team/team.c
index adb46de,c8624a8..aea92f0
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@@ -1540,10 -1540,16 +1540,10 @@@ static int team_init(struct net_device 
  	mutex_init(&team->lock);
  	team_set_no_mode(team);
  
 -	team->pcpu_stats = alloc_percpu(struct team_pcpu_stats);
 +	team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats);
  	if (!team->pcpu_stats)
  		return -ENOMEM;
  
 -	for_each_possible_cpu(i) {
 -		struct team_pcpu_stats *team_stats;
 -		team_stats = per_cpu_ptr(team->pcpu_stats, i);
 -		u64_stats_init(&team_stats->syncp);
 -	}
 -
  	for (i = 0; i < TEAM_PORT_HASHENTRIES; i++)
  		INIT_HLIST_HEAD(&team->en_port_hlist[i]);
  	INIT_LIST_HEAD(&team->port_list);
@@@ -1642,7 -1648,7 +1642,7 @@@ static netdev_tx_t team_xmit(struct sk_
  }
  
  static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb,
- 			     void *accel_priv)
+ 			     void *accel_priv, select_queue_fallback_t fallback)
  {
  	/*
  	 * This helper function exists to help dev_pick_tx get the correct
diff --combined include/linux/netdevice.h
index 891432a,e8eeebd..5e47565
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@@ -752,6 -752,9 +752,9 @@@ struct netdev_phys_port_id 
  	unsigned char id_len;
  };
  
+ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
+ 				       struct sk_buff *skb);
+ 
  /*
   * This structure defines the management hooks for network devices.
   * The following hooks can be defined; unless noted otherwise, they are
@@@ -783,7 -786,7 +786,7 @@@
   *	Required can not be NULL.
   *
   * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb,
-  *                         void *accel_priv);
+  *                         void *accel_priv, select_queue_fallback_t fallback);
   *	Called to decide which queue to when device supports multiple
   *	transmit queues.
   *
@@@ -1005,7 -1008,8 +1008,8 @@@ struct net_device_ops 
  						   struct net_device *dev);
  	u16			(*ndo_select_queue)(struct net_device *dev,
  						    struct sk_buff *skb,
- 						    void *accel_priv);
+ 						    void *accel_priv,
+ 						    select_queue_fallback_t fallback);
  	void			(*ndo_change_rx_flags)(struct net_device *dev,
  						       int flags);
  	void			(*ndo_set_rx_mode)(struct net_device *dev);
@@@ -1312,7 -1316,13 +1316,7 @@@ struct net_device 
  /*
   * Cache lines mostly used on receive path (including eth_type_trans())
   */
 -	unsigned long		last_rx;	/* Time of last Rx
 -						 * This should not be set in
 -						 * drivers, unless really needed,
 -						 * because network stack (bonding)
 -						 * use it if/when necessary, to
 -						 * avoid dirtying this cache line.
 -						 */
 +	unsigned long		last_rx;	/* Time of last Rx */
  
  	/* Interface address info used in eth_type_trans() */
  	unsigned char		*dev_addr;	/* hw address, (before bcast
@@@ -1545,7 -1555,6 +1549,6 @@@ static inline void netdev_for_each_tx_q
  struct netdev_queue *netdev_pick_tx(struct net_device *dev,
  				    struct sk_buff *skb,
  				    void *accel_priv);
- u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb);
  
  /*
   * Net namespace inlines
@@@ -1720,20 -1729,6 +1723,20 @@@ struct pcpu_sw_netstats 
  	struct u64_stats_sync   syncp;
  };
  
 +#define netdev_alloc_pcpu_stats(type)				\
 +({								\
 +	typeof(type) *pcpu_stats = alloc_percpu(type);		\
 +	if (pcpu_stats)	{					\
 +		int i;						\
 +		for_each_possible_cpu(i) {			\
 +			typeof(type) *stat;			\
 +			stat = per_cpu_ptr(pcpu_stats, i);	\
 +			u64_stats_init(&stat->syncp);		\
 +		}						\
 +	}							\
 +	pcpu_stats;						\
 +})
 +
  #include <linux/notifier.h>
  
  /* netdevice notifier chain. Please remember to update the rtnetlink
@@@ -2284,6 -2279,26 +2287,26 @@@ static inline void netdev_reset_queue(s
  }
  
  /**
+  * 	netdev_cap_txqueue - check if selected tx queue exceeds device queues
+  * 	@dev: network device
+  * 	@queue_index: given tx queue index
+  *
+  * 	Returns 0 if given tx queue index >= number of device tx queues,
+  * 	otherwise returns the originally passed tx queue index.
+  */
+ static inline u16 netdev_cap_txqueue(struct net_device *dev, u16 queue_index)
+ {
+ 	if (unlikely(queue_index >= dev->real_num_tx_queues)) {
+ 		net_warn_ratelimited("%s selects TX queue %d, but real number of TX queues is %d\n",
+ 				     dev->name, queue_index,
+ 				     dev->real_num_tx_queues);
+ 		return 0;
+ 	}
+ 
+ 	return queue_index;
+ }
+ 
+ /**
   *	netif_running - test if up
   *	@dev: network device
   *
@@@ -3076,7 -3091,12 +3099,12 @@@ void netdev_change_features(struct net_
  void netif_stacked_transfer_operstate(const struct net_device *rootdev,
  					struct net_device *dev);
  
- netdev_features_t netif_skb_features(struct sk_buff *skb);
+ netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
+ 					 const struct net_device *dev);
+ static inline netdev_features_t netif_skb_features(struct sk_buff *skb)
+ {
+ 	return netif_skb_dev_features(skb, skb->dev);
+ }
  
  static inline bool net_gso_ok(netdev_features_t features, int gso_type)
  {
diff --combined net/core/rtnetlink.c
index 7b2ad56,1a0dac2..fc122fd
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@@ -1121,7 -1121,56 +1121,7 @@@ nla_put_failure
  	return -EMSGSIZE;
  }
  
 -static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 -{
 -	struct net *net = sock_net(skb->sk);
 -	int h, s_h;
 -	int idx = 0, s_idx;
 -	struct net_device *dev;
 -	struct hlist_head *head;
 -	struct nlattr *tb[IFLA_MAX+1];
 -	u32 ext_filter_mask = 0;
 -
 -	s_h = cb->args[0];
 -	s_idx = cb->args[1];
 -
 -	rcu_read_lock();
 -	cb->seq = net->dev_base_seq;
 -
 -	if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
 -			ifla_policy) >= 0) {
 -
 -		if (tb[IFLA_EXT_MASK])
 -			ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
 -	}
 -
 -	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
 -		idx = 0;
 -		head = &net->dev_index_head[h];
 -		hlist_for_each_entry_rcu(dev, head, index_hlist) {
 -			if (idx < s_idx)
 -				goto cont;
 -			if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
 -					     NETLINK_CB(cb->skb).portid,
 -					     cb->nlh->nlmsg_seq, 0,
 -					     NLM_F_MULTI,
 -					     ext_filter_mask) <= 0)
 -				goto out;
 -
 -			nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 -cont:
 -			idx++;
 -		}
 -	}
 -out:
 -	rcu_read_unlock();
 -	cb->args[1] = idx;
 -	cb->args[0] = h;
 -
 -	return skb->len;
 -}
 -
 -const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 +static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
  	[IFLA_IFNAME]		= { .type = NLA_STRING, .len = IFNAMSIZ-1 },
  	[IFLA_ADDRESS]		= { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
  	[IFLA_BROADCAST]	= { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
@@@ -1148,6 -1197,7 +1148,6 @@@
  	[IFLA_NUM_RX_QUEUES]	= { .type = NLA_U32 },
  	[IFLA_PHYS_PORT_ID]	= { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
  };
 -EXPORT_SYMBOL(ifla_policy);
  
  static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
  	[IFLA_INFO_KIND]	= { .type = NLA_STRING },
@@@ -1185,61 -1235,6 +1185,61 @@@ static const struct nla_policy ifla_por
  	[IFLA_PORT_RESPONSE]	= { .type = NLA_U16, },
  };
  
 +static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 +{
 +	struct net *net = sock_net(skb->sk);
 +	int h, s_h;
 +	int idx = 0, s_idx;
 +	struct net_device *dev;
 +	struct hlist_head *head;
 +	struct nlattr *tb[IFLA_MAX+1];
 +	u32 ext_filter_mask = 0;
 +
 +	s_h = cb->args[0];
 +	s_idx = cb->args[1];
 +
 +	rcu_read_lock();
 +	cb->seq = net->dev_base_seq;
 +
 +	if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
 +			ifla_policy) >= 0) {
 +
 +		if (tb[IFLA_EXT_MASK])
 +			ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
 +	}
 +
 +	for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
 +		idx = 0;
 +		head = &net->dev_index_head[h];
 +		hlist_for_each_entry_rcu(dev, head, index_hlist) {
 +			if (idx < s_idx)
 +				goto cont;
 +			if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
 +					     NETLINK_CB(cb->skb).portid,
 +					     cb->nlh->nlmsg_seq, 0,
 +					     NLM_F_MULTI,
 +					     ext_filter_mask) <= 0)
 +				goto out;
 +
 +			nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 +cont:
 +			idx++;
 +		}
 +	}
 +out:
 +	rcu_read_unlock();
 +	cb->args[1] = idx;
 +	cb->args[0] = h;
 +
 +	return skb->len;
 +}
 +
 +int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len)
 +{
 +	return nla_parse(tb, IFLA_MAX, head, len, ifla_policy);
 +}
 +EXPORT_SYMBOL(rtnl_nla_parse_ifla);
 +
  struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
  {
  	struct net *net;
@@@ -1968,16 -1963,21 +1968,21 @@@ replay
  
  		dev->ifindex = ifm->ifi_index;
  
- 		if (ops->newlink)
+ 		if (ops->newlink) {
  			err = ops->newlink(net, dev, tb, data);
- 		else
+ 			/* Drivers should call free_netdev() in ->destructor
+ 			 * and unregister it on failure so that device could be
+ 			 * finally freed in rtnl_unlock.
+ 			 */
+ 			if (err < 0)
+ 				goto out;
+ 		} else {
  			err = register_netdevice(dev);
- 
- 		if (err < 0) {
- 			free_netdev(dev);
- 			goto out;
+ 			if (err < 0) {
+ 				free_netdev(dev);
+ 				goto out;
+ 			}
  		}
- 
  		err = rtnl_configure_link(dev, ifm);
  		if (err < 0)
  			unregister_netdevice(dev);
diff --combined net/ipv4/ip_forward.c
index d9d9290,f3869c1..be8abe7
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@@ -39,6 -39,71 +39,71 @@@
  #include <net/route.h>
  #include <net/xfrm.h>
  
+ static bool ip_may_fragment(const struct sk_buff *skb)
+ {
+ 	return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) ||
+ 	       !skb->local_df;
+ }
+ 
+ static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
+ {
+ 	if (skb->len <= mtu || skb->local_df)
+ 		return false;
+ 
+ 	if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
+ 		return false;
+ 
+ 	return true;
+ }
+ 
+ static bool ip_gso_exceeds_dst_mtu(const struct sk_buff *skb)
+ {
+ 	unsigned int mtu;
+ 
+ 	if (skb->local_df || !skb_is_gso(skb))
+ 		return false;
+ 
+ 	mtu = ip_dst_mtu_maybe_forward(skb_dst(skb), true);
+ 
+ 	/* if seglen > mtu, do software segmentation for IP fragmentation on
+ 	 * output.  DF bit cannot be set since ip_forward would have sent
+ 	 * icmp error.
+ 	 */
+ 	return skb_gso_network_seglen(skb) > mtu;
+ }
+ 
+ /* called if GSO skb needs to be fragmented on forward */
+ static int ip_forward_finish_gso(struct sk_buff *skb)
+ {
+ 	struct dst_entry *dst = skb_dst(skb);
+ 	netdev_features_t features;
+ 	struct sk_buff *segs;
+ 	int ret = 0;
+ 
+ 	features = netif_skb_dev_features(skb, dst->dev);
+ 	segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+ 	if (IS_ERR(segs)) {
+ 		kfree_skb(skb);
+ 		return -ENOMEM;
+ 	}
+ 
+ 	consume_skb(skb);
+ 
+ 	do {
+ 		struct sk_buff *nskb = segs->next;
+ 		int err;
+ 
+ 		segs->next = NULL;
+ 		err = dst_output(segs);
+ 
+ 		if (err && ret == 0)
+ 			ret = err;
+ 		segs = nskb;
+ 	} while (segs);
+ 
+ 	return ret;
+ }
+ 
  static int ip_forward_finish(struct sk_buff *skb)
  {
  	struct ip_options *opt	= &(IPCB(skb)->opt);
@@@ -49,6 -114,9 +114,9 @@@
  	if (unlikely(opt->optlen))
  		ip_forward_options(skb);
  
+ 	if (ip_gso_exceeds_dst_mtu(skb))
+ 		return ip_forward_finish_gso(skb);
+ 
  	return dst_output(skb);
  }
  
@@@ -59,10 -127,6 +127,10 @@@ int ip_forward(struct sk_buff *skb
  	struct rtable *rt;	/* Route we use */
  	struct ip_options *opt	= &(IPCB(skb)->opt);
  
 +	/* that should never happen */
 +	if (skb->pkt_type != PACKET_HOST)
 +		goto drop;
 +
  	if (skb_warn_if_lro(skb))
  		goto drop;
  
@@@ -72,6 -136,9 +140,6 @@@
  	if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))
  		return NET_RX_SUCCESS;
  
 -	if (skb->pkt_type != PACKET_HOST)
 -		goto drop;
 -
  	skb_forward_csum(skb);
  
  	/*
@@@ -92,8 -159,7 +160,7 @@@
  
  	IPCB(skb)->flags |= IPSKB_FORWARDED;
  	mtu = ip_dst_mtu_maybe_forward(&rt->dst, true);
- 	if (unlikely(skb->len > mtu && !skb_is_gso(skb) &&
- 		     (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) {
+ 	if (!ip_may_fragment(skb) && ip_exceeds_mtu(skb, mtu)) {
  		IP_INC_STATS(dev_net(rt->dst.dev), IPSTATS_MIB_FRAGFAILS);
  		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
  			  htonl(mtu));
diff --combined net/ipv4/route.c
index 271554c,4c011ec..11e4384
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@@ -697,6 -697,7 +697,6 @@@ static void update_or_create_fnhe(struc
  
  out_unlock:
  	spin_unlock_bh(&fnhe_lock);
 -	return;
  }
  
  static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flowi4 *fl4,
@@@ -1596,6 -1597,7 +1596,7 @@@ static int __mkroute_input(struct sk_bu
  	rth->rt_gateway	= 0;
  	rth->rt_uses_gateway = 0;
  	INIT_LIST_HEAD(&rth->rt_uncached);
+ 	RT_CACHE_STAT_INC(in_slow_tot);
  
  	rth->dst.input = ip_forward;
  	rth->dst.output = ip_output;
@@@ -1694,10 -1696,11 +1695,11 @@@ static int ip_route_input_slow(struct s
  	fl4.daddr = daddr;
  	fl4.saddr = saddr;
  	err = fib_lookup(net, &fl4, &res);
- 	if (err != 0)
+ 	if (err != 0) {
+ 		if (!IN_DEV_FORWARD(in_dev))
+ 			err = -EHOSTUNREACH;
  		goto no_route;
- 
- 	RT_CACHE_STAT_INC(in_slow_tot);
+ 	}
  
  	if (res.type == RTN_BROADCAST)
  		goto brd_input;
@@@ -1711,8 -1714,10 +1713,10 @@@
  		goto local_input;
  	}
  
- 	if (!IN_DEV_FORWARD(in_dev))
+ 	if (!IN_DEV_FORWARD(in_dev)) {
+ 		err = -EHOSTUNREACH;
  		goto no_route;
+ 	}
  	if (res.type != RTN_UNICAST)
  		goto martian_destination;
  
@@@ -1767,6 -1772,7 +1771,7 @@@ local_input
  	rth->rt_gateway	= 0;
  	rth->rt_uses_gateway = 0;
  	INIT_LIST_HEAD(&rth->rt_uncached);
+ 	RT_CACHE_STAT_INC(in_slow_tot);
  	if (res.type == RTN_UNREACHABLE) {
  		rth->dst.input= ip_error;
  		rth->dst.error= -err;
diff --combined net/tipc/link.c
index e4f233d,da6018b..284d638
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@@ -77,19 -77,19 +77,19 @@@ static const char *link_unk_evt = "Unkn
  
  static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr,
  				       struct sk_buff *buf);
 -static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf);
 -static int  tipc_link_tunnel_rcv(struct tipc_link **l_ptr,
 +static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf);
 +static int  tipc_link_tunnel_rcv(struct tipc_node *n_ptr,
  				 struct sk_buff **buf);
  static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance);
 -static int  link_send_sections_long(struct tipc_port *sender,
 -				    struct iovec const *msg_sect,
 -				    unsigned int len, u32 destnode);
 +static int  tipc_link_iovec_long_xmit(struct tipc_port *sender,
 +				      struct iovec const *msg_sect,
 +				      unsigned int len, u32 destnode);
  static void link_state_event(struct tipc_link *l_ptr, u32 event);
  static void link_reset_statistics(struct tipc_link *l_ptr);
  static void link_print(struct tipc_link *l_ptr, const char *str);
 -static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf);
 -static void tipc_link_send_sync(struct tipc_link *l);
 -static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf);
 +static int tipc_link_frag_xmit(struct tipc_link *l_ptr, struct sk_buff *buf);
 +static void tipc_link_sync_xmit(struct tipc_link *l);
 +static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf);
  
  /*
   *  Simple link routines
@@@ -147,6 -147,11 +147,6 @@@ int tipc_link_is_active(struct tipc_lin
  /**
   * link_timeout - handle expiration of link timer
   * @l_ptr: pointer to link
 - *
 - * This routine must not grab "tipc_net_lock" to avoid a potential deadlock conflict
 - * with tipc_link_delete().  (There is no risk that the node will be deleted by
 - * another thread because tipc_link_delete() always cancels the link timer before
 - * tipc_node_delete() is called.)
   */
  static void link_timeout(struct tipc_link *l_ptr)
  {
@@@ -208,8 -213,8 +208,8 @@@ static void link_set_timer(struct tipc_
   * Returns pointer to link.
   */
  struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
 -			      struct tipc_bearer *b_ptr,
 -			      const struct tipc_media_addr *media_addr)
 +				   struct tipc_bearer *b_ptr,
 +				   const struct tipc_media_addr *media_addr)
  {
  	struct tipc_link *l_ptr;
  	struct tipc_msg *msg;
@@@ -274,43 -279,41 +274,43 @@@
  
  	k_init_timer(&l_ptr->timer, (Handler)link_timeout,
  		     (unsigned long)l_ptr);
 -	list_add_tail(&l_ptr->link_list, &b_ptr->links);
  
  	link_state_event(l_ptr, STARTING_EVT);
  
  	return l_ptr;
  }
  
 -/**
 - * tipc_link_delete - delete a link
 - * @l_ptr: pointer to link
 - *
 - * Note: 'tipc_net_lock' is write_locked, bearer is locked.
 - * This routine must not grab the node lock until after link timer cancellation
 - * to avoid a potential deadlock situation.
 - */
 -void tipc_link_delete(struct tipc_link *l_ptr)
 -{
 -	if (!l_ptr) {
 -		pr_err("Attempt to delete non-existent link\n");
 -		return;
 -	}
  
 -	k_cancel_timer(&l_ptr->timer);
 +void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down)
 +{
 +	struct tipc_link *l_ptr;
 +	struct tipc_node *n_ptr;
  
 -	tipc_node_lock(l_ptr->owner);
 -	tipc_link_reset(l_ptr);
 -	tipc_node_detach_link(l_ptr->owner, l_ptr);
 -	tipc_link_purge_queues(l_ptr);
 -	list_del_init(&l_ptr->link_list);
 -	tipc_node_unlock(l_ptr->owner);
 -	k_term_timer(&l_ptr->timer);
 -	kfree(l_ptr);
 +	list_for_each_entry(n_ptr, &tipc_node_list, list) {
 +		spin_lock_bh(&n_ptr->lock);
 +		l_ptr = n_ptr->links[bearer_id];
 +		if (l_ptr) {
 +			tipc_link_reset(l_ptr);
 +			if (shutting_down || !tipc_node_is_up(n_ptr)) {
 +				tipc_node_detach_link(l_ptr->owner, l_ptr);
 +				tipc_link_reset_fragments(l_ptr);
 +				spin_unlock_bh(&n_ptr->lock);
 +
 +				/* Nobody else can access this link now: */
 +				del_timer_sync(&l_ptr->timer);
 +				kfree(l_ptr);
 +			} else {
 +				/* Detach/delete when failover is finished: */
 +				l_ptr->flags |= LINK_STOPPED;
 +				spin_unlock_bh(&n_ptr->lock);
 +				del_timer_sync(&l_ptr->timer);
 +			}
 +			continue;
 +		}
 +		spin_unlock_bh(&n_ptr->lock);
 +	}
  }
  
 -
  /**
   * link_schedule_port - schedule port for deferred sending
   * @l_ptr: pointer to link
@@@ -458,19 -461,6 +458,19 @@@ void tipc_link_reset(struct tipc_link *
  	link_reset_statistics(l_ptr);
  }
  
 +void tipc_link_reset_list(unsigned int bearer_id)
 +{
 +	struct tipc_link *l_ptr;
 +	struct tipc_node *n_ptr;
 +
 +	list_for_each_entry(n_ptr, &tipc_node_list, list) {
 +		spin_lock_bh(&n_ptr->lock);
 +		l_ptr = n_ptr->links[bearer_id];
 +		if (l_ptr)
 +			tipc_link_reset(l_ptr);
 +		spin_unlock_bh(&n_ptr->lock);
 +	}
 +}
  
  static void link_activate(struct tipc_link *l_ptr)
  {
@@@ -489,10 -479,7 +489,10 @@@ static void link_state_event(struct tip
  	struct tipc_link *other;
  	u32 cont_intv = l_ptr->continuity_interval;
  
 -	if (!l_ptr->started && (event != STARTING_EVT))
 +	if (l_ptr->flags & LINK_STOPPED)
 +		return;
 +
 +	if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT))
  		return;		/* Not yet. */
  
  	/* Check whether changeover is going on */
@@@ -512,12 -499,12 +512,12 @@@
  			if (l_ptr->next_in_no != l_ptr->checkpoint) {
  				l_ptr->checkpoint = l_ptr->next_in_no;
  				if (tipc_bclink_acks_missing(l_ptr->owner)) {
 -					tipc_link_send_proto_msg(l_ptr, STATE_MSG,
 -								 0, 0, 0, 0, 0);
 +					tipc_link_proto_xmit(l_ptr, STATE_MSG,
 +							     0, 0, 0, 0, 0);
  					l_ptr->fsm_msg_cnt++;
  				} else if (l_ptr->max_pkt < l_ptr->max_pkt_target) {
 -					tipc_link_send_proto_msg(l_ptr, STATE_MSG,
 -								 1, 0, 0, 0, 0);
 +					tipc_link_proto_xmit(l_ptr, STATE_MSG,
 +							     1, 0, 0, 0, 0);
  					l_ptr->fsm_msg_cnt++;
  				}
  				link_set_timer(l_ptr, cont_intv);
@@@ -525,7 -512,7 +525,7 @@@
  			}
  			l_ptr->state = WORKING_UNKNOWN;
  			l_ptr->fsm_msg_cnt = 0;
 -			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
 +			tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
  			l_ptr->fsm_msg_cnt++;
  			link_set_timer(l_ptr, cont_intv / 4);
  			break;
@@@ -535,8 -522,7 +535,8 @@@
  			tipc_link_reset(l_ptr);
  			l_ptr->state = RESET_RESET;
  			l_ptr->fsm_msg_cnt = 0;
 -			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
 +			tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
 +					     0, 0, 0, 0, 0);
  			l_ptr->fsm_msg_cnt++;
  			link_set_timer(l_ptr, cont_intv);
  			break;
@@@ -558,8 -544,7 +558,8 @@@
  			tipc_link_reset(l_ptr);
  			l_ptr->state = RESET_RESET;
  			l_ptr->fsm_msg_cnt = 0;
 -			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
 +			tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
 +					     0, 0, 0, 0, 0);
  			l_ptr->fsm_msg_cnt++;
  			link_set_timer(l_ptr, cont_intv);
  			break;
@@@ -569,14 -554,14 +569,14 @@@
  				l_ptr->fsm_msg_cnt = 0;
  				l_ptr->checkpoint = l_ptr->next_in_no;
  				if (tipc_bclink_acks_missing(l_ptr->owner)) {
 -					tipc_link_send_proto_msg(l_ptr, STATE_MSG,
 -								 0, 0, 0, 0, 0);
 +					tipc_link_proto_xmit(l_ptr, STATE_MSG,
 +							     0, 0, 0, 0, 0);
  					l_ptr->fsm_msg_cnt++;
  				}
  				link_set_timer(l_ptr, cont_intv);
  			} else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) {
 -				tipc_link_send_proto_msg(l_ptr, STATE_MSG,
 -							 1, 0, 0, 0, 0);
 +				tipc_link_proto_xmit(l_ptr, STATE_MSG,
 +						     1, 0, 0, 0, 0);
  				l_ptr->fsm_msg_cnt++;
  				link_set_timer(l_ptr, cont_intv / 4);
  			} else {	/* Link has failed */
@@@ -585,8 -570,8 +585,8 @@@
  				tipc_link_reset(l_ptr);
  				l_ptr->state = RESET_UNKNOWN;
  				l_ptr->fsm_msg_cnt = 0;
 -				tipc_link_send_proto_msg(l_ptr, RESET_MSG,
 -							 0, 0, 0, 0, 0);
 +				tipc_link_proto_xmit(l_ptr, RESET_MSG,
 +						     0, 0, 0, 0, 0);
  				l_ptr->fsm_msg_cnt++;
  				link_set_timer(l_ptr, cont_intv);
  			}
@@@ -606,25 -591,24 +606,25 @@@
  			l_ptr->state = WORKING_WORKING;
  			l_ptr->fsm_msg_cnt = 0;
  			link_activate(l_ptr);
 -			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
 +			tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
  			l_ptr->fsm_msg_cnt++;
  			if (l_ptr->owner->working_links == 1)
 -				tipc_link_send_sync(l_ptr);
 +				tipc_link_sync_xmit(l_ptr);
  			link_set_timer(l_ptr, cont_intv);
  			break;
  		case RESET_MSG:
  			l_ptr->state = RESET_RESET;
  			l_ptr->fsm_msg_cnt = 0;
 -			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0);
 +			tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
 +					     1, 0, 0, 0, 0);
  			l_ptr->fsm_msg_cnt++;
  			link_set_timer(l_ptr, cont_intv);
  			break;
  		case STARTING_EVT:
 -			l_ptr->started = 1;
 +			l_ptr->flags |= LINK_STARTED;
  			/* fall through */
  		case TIMEOUT_EVT:
 -			tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);
 +			tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);
  			l_ptr->fsm_msg_cnt++;
  			link_set_timer(l_ptr, cont_intv);
  			break;
@@@ -642,17 -626,16 +642,17 @@@
  			l_ptr->state = WORKING_WORKING;
  			l_ptr->fsm_msg_cnt = 0;
  			link_activate(l_ptr);
 -			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
 +			tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
  			l_ptr->fsm_msg_cnt++;
  			if (l_ptr->owner->working_links == 1)
 -				tipc_link_send_sync(l_ptr);
 +				tipc_link_sync_xmit(l_ptr);
  			link_set_timer(l_ptr, cont_intv);
  			break;
  		case RESET_MSG:
  			break;
  		case TIMEOUT_EVT:
 -			tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
 +			tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG,
 +					     0, 0, 0, 0, 0);
  			l_ptr->fsm_msg_cnt++;
  			link_set_timer(l_ptr, cont_intv);
  			break;
@@@ -738,11 -721,11 +738,11 @@@ static void link_add_chain_to_outqueue(
  }
  
  /*
 - * tipc_link_send_buf() is the 'full path' for messages, called from
 - * inside TIPC when the 'fast path' in tipc_send_buf
 + * tipc_link_xmit() is the 'full path' for messages, called from
 + * inside TIPC when the 'fast path' in tipc_send_xmit
   * has failed, and from link_send()
   */
 -int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
 +int __tipc_link_xmit(struct tipc_link *l_ptr, struct sk_buff *buf)
  {
  	struct tipc_msg *msg = buf_msg(buf);
  	u32 size = msg_size(msg);
@@@ -770,7 -753,7 +770,7 @@@
  
  	/* Fragmentation needed ? */
  	if (size > max_packet)
 -		return link_send_long_buf(l_ptr, buf);
 +		return tipc_link_frag_xmit(l_ptr, buf);
  
  	/* Packet can be queued or sent. */
  	if (likely(!link_congested(l_ptr))) {
@@@ -814,11 -797,11 +814,11 @@@
  }
  
  /*
 - * tipc_link_send(): same as tipc_link_send_buf(), but the link to use has
 - * not been selected yet, and the the owner node is not locked
 + * tipc_link_xmit(): same as __tipc_link_xmit(), but the link to use
 + * has not been selected yet, and the the owner node is not locked
   * Called by TIPC internal users, e.g. the name distributor
   */
 -int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector)
 +int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector)
  {
  	struct tipc_link *l_ptr;
  	struct tipc_node *n_ptr;
@@@ -830,7 -813,7 +830,7 @@@
  		tipc_node_lock(n_ptr);
  		l_ptr = n_ptr->active_links[selector & 1];
  		if (l_ptr)
 -			res = tipc_link_send_buf(l_ptr, buf);
 +			res = __tipc_link_xmit(l_ptr, buf);
  		else
  			kfree_skb(buf);
  		tipc_node_unlock(n_ptr);
@@@ -842,14 -825,14 +842,14 @@@
  }
  
  /*
 - * tipc_link_send_sync - synchronize broadcast link endpoints.
 + * tipc_link_sync_xmit - synchronize broadcast link endpoints.
   *
   * Give a newly added peer node the sequence number where it should
   * start receiving and acking broadcast packets.
   *
   * Called with node locked
   */
 -static void tipc_link_send_sync(struct tipc_link *l)
 +static void tipc_link_sync_xmit(struct tipc_link *l)
  {
  	struct sk_buff *buf;
  	struct tipc_msg *msg;
@@@ -866,14 -849,14 +866,14 @@@
  }
  
  /*
 - * tipc_link_recv_sync - synchronize broadcast link endpoints.
 + * tipc_link_sync_rcv - synchronize broadcast link endpoints.
   * Receive the sequence number where we should start receiving and
   * acking broadcast packets from a newly added peer node, and open
   * up for reception of such packets.
   *
   * Called with node locked
   */
 -static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf)
 +static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf)
  {
  	struct tipc_msg *msg = buf_msg(buf);
  
@@@ -883,7 -866,7 +883,7 @@@
  }
  
  /*
 - * tipc_link_send_names - send name table entries to new neighbor
 + * tipc_link_names_xmit - send name table entries to new neighbor
   *
   * Send routine for bulk delivery of name table messages when contact
   * with a new neighbor occurs. No link congestion checking is performed
@@@ -891,7 -874,7 +891,7 @@@
   * small enough not to require fragmentation.
   * Called without any locks held.
   */
 -void tipc_link_send_names(struct list_head *message_list, u32 dest)
 +void tipc_link_names_xmit(struct list_head *message_list, u32 dest)
  {
  	struct tipc_node *n_ptr;
  	struct tipc_link *l_ptr;
@@@ -926,13 -909,13 +926,13 @@@
  }
  
  /*
 - * link_send_buf_fast: Entry for data messages where the
 + * tipc_link_xmit_fast: Entry for data messages where the
   * destination link is known and the header is complete,
   * inclusive total message length. Very time critical.
   * Link is locked. Returns user data length.
   */
 -static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf,
 -			      u32 *used_max_pkt)
 +static int tipc_link_xmit_fast(struct tipc_link *l_ptr, struct sk_buff *buf,
 +			       u32 *used_max_pkt)
  {
  	struct tipc_msg *msg = buf_msg(buf);
  	int res = msg_data_sz(msg);
@@@ -948,18 -931,18 +948,18 @@@
  		else
  			*used_max_pkt = l_ptr->max_pkt;
  	}
 -	return tipc_link_send_buf(l_ptr, buf);  /* All other cases */
 +	return __tipc_link_xmit(l_ptr, buf);  /* All other cases */
  }
  
  /*
 - * tipc_link_send_sections_fast: Entry for messages where the
 + * tipc_link_iovec_xmit_fast: Entry for messages where the
   * destination processor is known and the header is complete,
   * except for total message length.
   * Returns user data length or errno.
   */
 -int tipc_link_send_sections_fast(struct tipc_port *sender,
 -				 struct iovec const *msg_sect,
 -				 unsigned int len, u32 destaddr)
 +int tipc_link_iovec_xmit_fast(struct tipc_port *sender,
 +			      struct iovec const *msg_sect,
 +			      unsigned int len, u32 destaddr)
  {
  	struct tipc_msg *hdr = &sender->phdr;
  	struct tipc_link *l_ptr;
@@@ -985,8 -968,8 +985,8 @@@ again
  		l_ptr = node->active_links[selector];
  		if (likely(l_ptr)) {
  			if (likely(buf)) {
 -				res = link_send_buf_fast(l_ptr, buf,
 -							 &sender->max_pkt);
 +				res = tipc_link_xmit_fast(l_ptr, buf,
 +							  &sender->max_pkt);
  exit:
  				tipc_node_unlock(node);
  				read_unlock_bh(&tipc_net_lock);
@@@ -1012,8 -995,8 +1012,8 @@@
  			if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt)
  				goto again;
  
 -			return link_send_sections_long(sender, msg_sect, len,
 -						       destaddr);
 +			return tipc_link_iovec_long_xmit(sender, msg_sect,
 +							 len, destaddr);
  		}
  		tipc_node_unlock(node);
  	}
@@@ -1023,13 -1006,13 +1023,13 @@@
  	if (buf)
  		return tipc_reject_msg(buf, TIPC_ERR_NO_NODE);
  	if (res >= 0)
 -		return tipc_port_reject_sections(sender, hdr, msg_sect,
 -						 len, TIPC_ERR_NO_NODE);
 +		return tipc_port_iovec_reject(sender, hdr, msg_sect, len,
 +					      TIPC_ERR_NO_NODE);
  	return res;
  }
  
  /*
 - * link_send_sections_long(): Entry for long messages where the
 + * tipc_link_iovec_long_xmit(): Entry for long messages where the
   * destination node is known and the header is complete,
   * inclusive total message length.
   * Link and bearer congestion status have been checked to be ok,
@@@ -1042,9 -1025,9 +1042,9 @@@
   *
   * Returns user data length or errno.
   */
 -static int link_send_sections_long(struct tipc_port *sender,
 -				   struct iovec const *msg_sect,
 -				   unsigned int len, u32 destaddr)
 +static int tipc_link_iovec_long_xmit(struct tipc_port *sender,
 +				     struct iovec const *msg_sect,
 +				     unsigned int len, u32 destaddr)
  {
  	struct tipc_link *l_ptr;
  	struct tipc_node *node;
@@@ -1163,8 -1146,8 +1163,8 @@@ error
  	} else {
  reject:
  		kfree_skb_list(buf_chain);
 -		return tipc_port_reject_sections(sender, hdr, msg_sect,
 -						 len, TIPC_ERR_NO_NODE);
 +		return tipc_port_iovec_reject(sender, hdr, msg_sect,
 +					      len, TIPC_ERR_NO_NODE);
  	}
  
  	/* Append chain of fragments to send queue & send them */
@@@ -1408,6 -1391,12 +1408,12 @@@ static int link_recv_buf_validate(struc
  	u32 hdr_size;
  	u32 min_hdr_size;
  
+ 	/* If this packet comes from the defer queue, the skb has already
+ 	 * been validated
+ 	 */
+ 	if (unlikely(TIPC_SKB_CB(buf)->deferred))
+ 		return 1;
+ 
  	if (unlikely(buf->len < MIN_H_SIZE))
  		return 0;
  
@@@ -1452,6 -1441,7 +1458,6 @@@ void tipc_rcv(struct sk_buff *head, str
  		u32 seq_no;
  		u32 ackd;
  		u32 released = 0;
 -		int type;
  
  		head = head->next;
  		buf->next = NULL;
@@@ -1473,9 -1463,9 +1479,9 @@@
  
  		if (unlikely(msg_non_seq(msg))) {
  			if (msg_user(msg) ==  LINK_CONFIG)
 -				tipc_disc_recv_msg(buf, b_ptr);
 +				tipc_disc_rcv(buf, b_ptr);
  			else
 -				tipc_bclink_recv_pkt(buf);
 +				tipc_bclink_rcv(buf);
  			continue;
  		}
  
@@@ -1499,7 -1489,7 +1505,7 @@@
  		if ((n_ptr->block_setup & WAIT_PEER_DOWN) &&
  			msg_user(msg) == LINK_PROTOCOL &&
  			(msg_type(msg) == RESET_MSG ||
 -					msg_type(msg) == ACTIVATE_MSG) &&
 +			 msg_type(msg) == ACTIVATE_MSG) &&
  			!msg_redundant_link(msg))
  			n_ptr->block_setup &= ~WAIT_PEER_DOWN;
  
@@@ -1518,6 -1508,7 +1524,6 @@@
  		while ((crs != l_ptr->next_out) &&
  		       less_eq(buf_seqno(crs), ackd)) {
  			struct sk_buff *next = crs->next;
 -
  			kfree_skb(crs);
  			crs = next;
  			released++;
@@@ -1530,19 -1521,18 +1536,19 @@@
  		/* Try sending any messages link endpoint has pending */
  		if (unlikely(l_ptr->next_out))
  			tipc_link_push_queue(l_ptr);
 +
  		if (unlikely(!list_empty(&l_ptr->waiting_ports)))
  			tipc_link_wakeup_ports(l_ptr, 0);
 +
  		if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) {
  			l_ptr->stats.sent_acks++;
 -			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
 +			tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
  		}
  
 -		/* Now (finally!) process the incoming message */
 -protocol_check:
 +		/* Process the incoming packet */
  		if (unlikely(!link_working_working(l_ptr))) {
  			if (msg_user(msg) == LINK_PROTOCOL) {
 -				link_recv_proto_msg(l_ptr, buf);
 +				tipc_link_proto_rcv(l_ptr, buf);
  				head = link_insert_deferred_queue(l_ptr, head);
  				tipc_node_unlock(n_ptr);
  				continue;
@@@ -1571,65 -1561,67 +1577,65 @@@
  		l_ptr->next_in_no++;
  		if (unlikely(l_ptr->oldest_deferred_in))
  			head = link_insert_deferred_queue(l_ptr, head);
 -deliver:
 -		if (likely(msg_isdata(msg))) {
 -			tipc_node_unlock(n_ptr);
 -			tipc_port_recv_msg(buf);
 -			continue;
 +
 +		/* Deliver packet/message to correct user: */
 +		if (unlikely(msg_user(msg) ==  CHANGEOVER_PROTOCOL)) {
 +			if (!tipc_link_tunnel_rcv(n_ptr, &buf)) {
 +				tipc_node_unlock(n_ptr);
 +				continue;
 +			}
 +			msg = buf_msg(buf);
 +		} else if (msg_user(msg) == MSG_FRAGMENTER) {
 +			int rc;
 +
 +			l_ptr->stats.recv_fragments++;
 +			rc = tipc_link_frag_rcv(&l_ptr->reasm_head,
 +						&l_ptr->reasm_tail,
 +						&buf);
 +			if (rc == LINK_REASM_COMPLETE) {
 +				l_ptr->stats.recv_fragmented++;
 +				msg = buf_msg(buf);
 +			} else {
 +				if (rc == LINK_REASM_ERROR)
 +					tipc_link_reset(l_ptr);
 +				tipc_node_unlock(n_ptr);
 +				continue;
 +			}
  		}
 +
  		switch (msg_user(msg)) {
 -			int ret;
 +		case TIPC_LOW_IMPORTANCE:
 +		case TIPC_MEDIUM_IMPORTANCE:
 +		case TIPC_HIGH_IMPORTANCE:
 +		case TIPC_CRITICAL_IMPORTANCE:
 +			tipc_node_unlock(n_ptr);
 +			tipc_port_rcv(buf);
 +			continue;
  		case MSG_BUNDLER:
  			l_ptr->stats.recv_bundles++;
  			l_ptr->stats.recv_bundled += msg_msgcnt(msg);
  			tipc_node_unlock(n_ptr);
 -			tipc_link_recv_bundle(buf);
 +			tipc_link_bundle_rcv(buf);
  			continue;
  		case NAME_DISTRIBUTOR:
  			n_ptr->bclink.recv_permitted = true;
  			tipc_node_unlock(n_ptr);
 -			tipc_named_recv(buf);
 -			continue;
 -		case BCAST_PROTOCOL:
 -			tipc_link_recv_sync(n_ptr, buf);
 -			tipc_node_unlock(n_ptr);
 +			tipc_named_rcv(buf);
  			continue;
  		case CONN_MANAGER:
  			tipc_node_unlock(n_ptr);
 -			tipc_port_recv_proto_msg(buf);
 +			tipc_port_proto_rcv(buf);
  			continue;
 -		case MSG_FRAGMENTER:
 -			l_ptr->stats.recv_fragments++;
 -			ret = tipc_link_recv_fragment(&l_ptr->reasm_head,
 -						      &l_ptr->reasm_tail,
 -						      &buf);
 -			if (ret == LINK_REASM_COMPLETE) {
 -				l_ptr->stats.recv_fragmented++;
 -				msg = buf_msg(buf);
 -				goto deliver;
 -			}
 -			if (ret == LINK_REASM_ERROR)
 -				tipc_link_reset(l_ptr);
 -			tipc_node_unlock(n_ptr);
 -			continue;
 -		case CHANGEOVER_PROTOCOL:
 -			type = msg_type(msg);
 -			if (tipc_link_tunnel_rcv(&l_ptr, &buf)) {
 -				msg = buf_msg(buf);
 -				seq_no = msg_seqno(msg);
 -				if (type == ORIGINAL_MSG)
 -					goto deliver;
 -				goto protocol_check;
 -			}
 +		case BCAST_PROTOCOL:
 +			tipc_link_sync_rcv(n_ptr, buf);
  			break;
  		default:
  			kfree_skb(buf);
  			break;
  		}
  		tipc_node_unlock(n_ptr);
 -		tipc_net_route_msg(buf);
  		continue;
  unlock_discard:
 -
  		tipc_node_unlock(n_ptr);
  discard:
  		kfree_skb(buf);
@@@ -1696,7 -1688,7 +1702,7 @@@ static void link_handle_out_of_seq_msg(
  	u32 seq_no = buf_seqno(buf);
  
  	if (likely(msg_user(buf_msg(buf)) == LINK_PROTOCOL)) {
 -		link_recv_proto_msg(l_ptr, buf);
 +		tipc_link_proto_rcv(l_ptr, buf);
  		return;
  	}
  
@@@ -1717,8 -1709,9 +1723,9 @@@
  				&l_ptr->newest_deferred_in, buf)) {
  		l_ptr->deferred_inqueue_sz++;
  		l_ptr->stats.deferred_recv++;
+ 		TIPC_SKB_CB(buf)->deferred = true;
  		if ((l_ptr->deferred_inqueue_sz % 16) == 1)
 -			tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
 +			tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
  	} else
  		l_ptr->stats.duplicates++;
  }
@@@ -1726,8 -1719,9 +1733,8 @@@
  /*
   * Send protocol message to the other endpoint.
   */
 -void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ,
 -			      int probe_msg, u32 gap, u32 tolerance,
 -			      u32 priority, u32 ack_mtu)
 +void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg,
 +			  u32 gap, u32 tolerance, u32 priority, u32 ack_mtu)
  {
  	struct sk_buff *buf = NULL;
  	struct tipc_msg *msg = l_ptr->pmsg;
@@@ -1826,7 -1820,7 +1833,7 @@@
   * Note that network plane id propagates through the network, and may
   * change at any time. The node with lowest address rules
   */
 -static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf)
 +static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf)
  {
  	u32 rec_gap = 0;
  	u32 max_pkt_info;
@@@ -1945,8 -1939,8 +1952,8 @@@
  						      msg_last_bcast(msg));
  
  		if (rec_gap || (msg_probe(msg))) {
 -			tipc_link_send_proto_msg(l_ptr, STATE_MSG,
 -						 0, rec_gap, 0, 0, max_pkt_ack);
 +			tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, rec_gap, 0,
 +					     0, max_pkt_ack);
  		}
  		if (msg_seq_gap(msg)) {
  			l_ptr->stats.recv_nacks++;
@@@ -1985,7 -1979,7 +1992,7 @@@ static void tipc_link_tunnel_xmit(struc
  	}
  	skb_copy_to_linear_data(buf, tunnel_hdr, INT_H_SIZE);
  	skb_copy_to_linear_data_offset(buf, INT_H_SIZE, msg, length);
 -	tipc_link_send_buf(tunnel, buf);
 +	__tipc_link_xmit(tunnel, buf);
  }
  
  
@@@ -2018,7 -2012,7 +2025,7 @@@ void tipc_link_failover_send_queue(stru
  		if (buf) {
  			skb_copy_to_linear_data(buf, &tunnel_hdr, INT_H_SIZE);
  			msg_set_size(&tunnel_hdr, INT_H_SIZE);
 -			tipc_link_send_buf(tunnel, buf);
 +			__tipc_link_xmit(tunnel, buf);
  		} else {
  			pr_warn("%sunable to send changeover msg\n",
  				link_co_err);
@@@ -2052,7 -2046,7 +2059,7 @@@
  	}
  }
  
 -/* tipc_link_dup_send_queue(): A second link has become active. Tunnel a
 +/* tipc_link_dup_queue_xmit(): A second link has become active. Tunnel a
   * duplicate of the first link's send queue via the new link. This way, we
   * are guaranteed that currently queued packets from a socket are delivered
   * before future traffic from the same socket, even if this is using the
@@@ -2061,7 -2055,7 +2068,7 @@@
   * and sequence order is preserved per sender/receiver socket pair.
   * Owner node is locked.
   */
 -void tipc_link_dup_send_queue(struct tipc_link *l_ptr,
 +void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr,
  			      struct tipc_link *tunnel)
  {
  	struct sk_buff *iter;
@@@ -2091,7 -2085,7 +2098,7 @@@
  		skb_copy_to_linear_data(outbuf, &tunnel_hdr, INT_H_SIZE);
  		skb_copy_to_linear_data_offset(outbuf, INT_H_SIZE, iter->data,
  					       length);
 -		tipc_link_send_buf(tunnel, outbuf);
 +		__tipc_link_xmit(tunnel, outbuf);
  		if (!tipc_link_is_up(l_ptr))
  			return;
  		iter = iter->next;
@@@ -2118,114 -2112,89 +2125,114 @@@ static struct sk_buff *buf_extract(stru
  	return eb;
  }
  
 -/*  tipc_link_tunnel_rcv(): Receive a tunneled packet, sent
 - *  via other link as result of a failover (ORIGINAL_MSG) or
 - *  a new active link (DUPLICATE_MSG). Failover packets are
 - *  returned to the active link for delivery upwards.
 +
 +
 +/* tipc_link_dup_rcv(): Receive a tunnelled DUPLICATE_MSG packet.
 + * Owner node is locked.
 + */
 +static void tipc_link_dup_rcv(struct tipc_link *l_ptr,
 +			      struct sk_buff *t_buf)
 +{
 +	struct sk_buff *buf;
 +
 +	if (!tipc_link_is_up(l_ptr))
 +		return;
 +
 +	buf = buf_extract(t_buf, INT_H_SIZE);
 +	if (buf == NULL) {
 +		pr_warn("%sfailed to extract inner dup pkt\n", link_co_err);
 +		return;
 +	}
 +
 +	/* Add buffer to deferred queue, if applicable: */
 +	link_handle_out_of_seq_msg(l_ptr, buf);
 +}
 +
 +/*  tipc_link_failover_rcv(): Receive a tunnelled ORIGINAL_MSG packet
   *  Owner node is locked.
   */
 -static int tipc_link_tunnel_rcv(struct tipc_link **l_ptr,
 -				struct sk_buff **buf)
 +static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr,
 +					      struct sk_buff *t_buf)
  {
 -	struct sk_buff *tunnel_buf = *buf;
 -	struct tipc_link *dest_link;
 +	struct tipc_msg *t_msg = buf_msg(t_buf);
 +	struct sk_buff *buf = NULL;
  	struct tipc_msg *msg;
 -	struct tipc_msg *tunnel_msg = buf_msg(tunnel_buf);
 -	u32 msg_typ = msg_type(tunnel_msg);
 -	u32 msg_count = msg_msgcnt(tunnel_msg);
 -	u32 bearer_id = msg_bearer_id(tunnel_msg);
  
 -	if (bearer_id >= MAX_BEARERS)
 -		goto exit;
 -	dest_link = (*l_ptr)->owner->links[bearer_id];
 -	if (!dest_link)
 -		goto exit;
 -	if (dest_link == *l_ptr) {
 -		pr_err("Unexpected changeover message on link <%s>\n",
 -		       (*l_ptr)->name);
 -		goto exit;
 -	}
 -	*l_ptr = dest_link;
 -	msg = msg_get_wrapped(tunnel_msg);
 +	if (tipc_link_is_up(l_ptr))
 +		tipc_link_reset(l_ptr);
  
 -	if (msg_typ == DUPLICATE_MSG) {
 -		if (less(msg_seqno(msg), mod(dest_link->next_in_no)))
 -			goto exit;
 -		*buf = buf_extract(tunnel_buf, INT_H_SIZE);
 -		if (*buf == NULL) {
 -			pr_warn("%sduplicate msg dropped\n", link_co_err);
 +	/* First failover packet? */
 +	if (l_ptr->exp_msg_count == START_CHANGEOVER)
 +		l_ptr->exp_msg_count = msg_msgcnt(t_msg);
 +
 +	/* Should there be an inner packet? */
 +	if (l_ptr->exp_msg_count) {
 +		l_ptr->exp_msg_count--;
 +		buf = buf_extract(t_buf, INT_H_SIZE);
 +		if (buf == NULL) {
 +			pr_warn("%sno inner failover pkt\n", link_co_err);
  			goto exit;
  		}
 -		kfree_skb(tunnel_buf);
 -		return 1;
 -	}
 +		msg = buf_msg(buf);
  
 -	/* First original message ?: */
 -	if (tipc_link_is_up(dest_link)) {
 -		pr_info("%s<%s>, changeover initiated by peer\n", link_rst_msg,
 -			dest_link->name);
 -		tipc_link_reset(dest_link);
 -		dest_link->exp_msg_count = msg_count;
 -		if (!msg_count)
 -			goto exit;
 -	} else if (dest_link->exp_msg_count == START_CHANGEOVER) {
 -		dest_link->exp_msg_count = msg_count;
 -		if (!msg_count)
 +		if (less(msg_seqno(msg), l_ptr->reset_checkpoint)) {
 +			kfree_skb(buf);
 +			buf = NULL;
  			goto exit;
 +		}
 +		if (msg_user(msg) == MSG_FRAGMENTER) {
 +			l_ptr->stats.recv_fragments++;
 +			tipc_link_frag_rcv(&l_ptr->reasm_head,
 +					   &l_ptr->reasm_tail,
 +					   &buf);
 +		}
  	}
 +exit:
 +	if ((l_ptr->exp_msg_count == 0) && (l_ptr->flags & LINK_STOPPED)) {
 +		tipc_node_detach_link(l_ptr->owner, l_ptr);
 +		kfree(l_ptr);
 +	}
 +	return buf;
 +}
 +
 +/*  tipc_link_tunnel_rcv(): Receive a tunnelled packet, sent
 + *  via other link as result of a failover (ORIGINAL_MSG) or
 + *  a new active link (DUPLICATE_MSG). Failover packets are
 + *  returned to the active link for delivery upwards.
 + *  Owner node is locked.
 + */
 +static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr,
 +				struct sk_buff **buf)
 +{
 +	struct sk_buff *t_buf = *buf;
 +	struct tipc_link *l_ptr;
 +	struct tipc_msg *t_msg = buf_msg(t_buf);
 +	u32 bearer_id = msg_bearer_id(t_msg);
  
 -	/* Receive original message */
 -	if (dest_link->exp_msg_count == 0) {
 -		pr_warn("%sgot too many tunnelled messages\n", link_co_err);
 +	*buf = NULL;
 +
 +	if (bearer_id >= MAX_BEARERS)
  		goto exit;
 -	}
 -	dest_link->exp_msg_count--;
 -	if (less(msg_seqno(msg), dest_link->reset_checkpoint)) {
 +
 +	l_ptr = n_ptr->links[bearer_id];
 +	if (!l_ptr)
  		goto exit;
 -	} else {
 -		*buf = buf_extract(tunnel_buf, INT_H_SIZE);
 -		if (*buf != NULL) {
 -			kfree_skb(tunnel_buf);
 -			return 1;
 -		} else {
 -			pr_warn("%soriginal msg dropped\n", link_co_err);
 -		}
 -	}
 +
 +	if (msg_type(t_msg) == DUPLICATE_MSG)
 +		tipc_link_dup_rcv(l_ptr, t_buf);
 +	else if (msg_type(t_msg) == ORIGINAL_MSG)
 +		*buf = tipc_link_failover_rcv(l_ptr, t_buf);
 +	else
 +		pr_warn("%sunknown tunnel pkt received\n", link_co_err);
  exit:
 -	*buf = NULL;
 -	kfree_skb(tunnel_buf);
 -	return 0;
 +	kfree_skb(t_buf);
 +	return *buf != NULL;
  }
  
  /*
   *  Bundler functionality:
   */
 -void tipc_link_recv_bundle(struct sk_buff *buf)
 +void tipc_link_bundle_rcv(struct sk_buff *buf)
  {
  	u32 msgcount = msg_msgcnt(buf_msg(buf));
  	u32 pos = INT_H_SIZE;
@@@ -2248,11 -2217,11 +2255,11 @@@
   */
  
  /*
 - * link_send_long_buf: Entry for buffers needing fragmentation.
 + * tipc_link_frag_xmit: Entry for buffers needing fragmentation.
   * The buffer is complete, inclusive total message length.
   * Returns user data length.
   */
 -static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
 +static int tipc_link_frag_xmit(struct tipc_link *l_ptr, struct sk_buff *buf)
  {
  	struct sk_buff *buf_chain = NULL;
  	struct sk_buff *buf_chain_tail = (struct sk_buff *)&buf_chain;
@@@ -2315,11 -2284,12 +2322,11 @@@
  	return dsz;
  }
  
 -/*
 - * tipc_link_recv_fragment(): Called with node lock on. Returns
 +/* tipc_link_frag_rcv(): Called with node lock on. Returns
   * the reassembled buffer if message is complete.
   */
 -int tipc_link_recv_fragment(struct sk_buff **head, struct sk_buff **tail,
 -			    struct sk_buff **fbuf)
 +int tipc_link_frag_rcv(struct sk_buff **head, struct sk_buff **tail,
 +		       struct sk_buff **fbuf)
  {
  	struct sk_buff *frag = *fbuf;
  	struct tipc_msg *msg = buf_msg(frag);
@@@ -2333,7 -2303,6 +2340,7 @@@
  			goto out_free;
  		*head = frag;
  		skb_frag_list_init(*head);
 +		*fbuf = NULL;
  		return 0;
  	} else if (*head &&
  		   skb_try_coalesce(*head, frag, &headstolen, &delta)) {
@@@ -2353,12 -2322,10 +2360,12 @@@
  		*tail = *head = NULL;
  		return LINK_REASM_COMPLETE;
  	}
 +	*fbuf = NULL;
  	return 0;
  out_free:
  	pr_warn_ratelimited("Link unable to reassemble fragmented message\n");
  	kfree_skb(*fbuf);
 +	*fbuf = NULL;
  	return LINK_REASM_ERROR;
  }
  
@@@ -2392,40 -2359,35 +2399,40 @@@ void tipc_link_set_queue_limits(struct 
  	l_ptr->queue_limit[MSG_FRAGMENTER] = 4000;
  }
  
 -/**
 - * link_find_link - locate link by name
 - * @name: ptr to link name string
 - * @node: ptr to area to be filled with ptr to associated node
 - *
 +/* tipc_link_find_owner - locate owner node of link by link's name
 + * @name: pointer to link name string
 + * @bearer_id: pointer to index in 'node->links' array where the link was found.
   * Caller must hold 'tipc_net_lock' to ensure node and bearer are not deleted;
   * this also prevents link deletion.
   *
 - * Returns pointer to link (or 0 if invalid link name).
 + * Returns pointer to node owning the link, or 0 if no matching link is found.
   */
 -static struct tipc_link *link_find_link(const char *name,
 -					struct tipc_node **node)
 +static struct tipc_node *tipc_link_find_owner(const char *link_name,
 +					      unsigned int *bearer_id)
  {
  	struct tipc_link *l_ptr;
  	struct tipc_node *n_ptr;
 +	struct tipc_node *tmp_n_ptr;
 +	struct tipc_node *found_node = 0;
 +
  	int i;
  
 -	list_for_each_entry(n_ptr, &tipc_node_list, list) {
 +	*bearer_id = 0;
 +	list_for_each_entry_safe(n_ptr, tmp_n_ptr, &tipc_node_list, list) {
 +		tipc_node_lock(n_ptr);
  		for (i = 0; i < MAX_BEARERS; i++) {
  			l_ptr = n_ptr->links[i];
 -			if (l_ptr && !strcmp(l_ptr->name, name))
 -				goto found;
 +			if (l_ptr && !strcmp(l_ptr->name, link_name)) {
 +				*bearer_id = i;
 +				found_node = n_ptr;
 +				break;
 +			}
  		}
 +		tipc_node_unlock(n_ptr);
 +		if (found_node)
 +			break;
  	}
 -	l_ptr = NULL;
 -	n_ptr = NULL;
 -found:
 -	*node = n_ptr;
 -	return l_ptr;
 +	return found_node;
  }
  
  /**
@@@ -2467,33 -2429,32 +2474,33 @@@ static int link_cmd_set_value(const cha
  	struct tipc_link *l_ptr;
  	struct tipc_bearer *b_ptr;
  	struct tipc_media *m_ptr;
 +	int bearer_id;
  	int res = 0;
  
 -	l_ptr = link_find_link(name, &node);
 -	if (l_ptr) {
 -		/*
 -		 * acquire node lock for tipc_link_send_proto_msg().
 -		 * see "TIPC locking policy" in net.c.
 -		 */
 +	node = tipc_link_find_owner(name, &bearer_id);
 +	if (node) {
  		tipc_node_lock(node);
 -		switch (cmd) {
 -		case TIPC_CMD_SET_LINK_TOL:
 -			link_set_supervision_props(l_ptr, new_value);
 -			tipc_link_send_proto_msg(l_ptr,
 -				STATE_MSG, 0, 0, new_value, 0, 0);
 -			break;
 -		case TIPC_CMD_SET_LINK_PRI:
 -			l_ptr->priority = new_value;
 -			tipc_link_send_proto_msg(l_ptr,
 -				STATE_MSG, 0, 0, 0, new_value, 0);
 -			break;
 -		case TIPC_CMD_SET_LINK_WINDOW:
 -			tipc_link_set_queue_limits(l_ptr, new_value);
 -			break;
 -		default:
 -			res = -EINVAL;
 -			break;
 +		l_ptr = node->links[bearer_id];
 +
 +		if (l_ptr) {
 +			switch (cmd) {
 +			case TIPC_CMD_SET_LINK_TOL:
 +				link_set_supervision_props(l_ptr, new_value);
 +				tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0,
 +						     new_value, 0, 0);
 +				break;
 +			case TIPC_CMD_SET_LINK_PRI:
 +				l_ptr->priority = new_value;
 +				tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0,
 +						     0, new_value, 0);
 +				break;
 +			case TIPC_CMD_SET_LINK_WINDOW:
 +				tipc_link_set_queue_limits(l_ptr, new_value);
 +				break;
 +			default:
 +				res = -EINVAL;
 +				break;
 +			}
  		}
  		tipc_node_unlock(node);
  		return res;
@@@ -2588,7 -2549,6 +2595,7 @@@ struct sk_buff *tipc_link_cmd_reset_sta
  	char *link_name;
  	struct tipc_link *l_ptr;
  	struct tipc_node *node;
 +	unsigned int bearer_id;
  
  	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
  		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@@ -2599,19 -2559,15 +2606,19 @@@
  			return tipc_cfg_reply_error_string("link not found");
  		return tipc_cfg_reply_none();
  	}
 -
  	read_lock_bh(&tipc_net_lock);
 -	l_ptr = link_find_link(link_name, &node);
 -	if (!l_ptr) {
 +	node = tipc_link_find_owner(link_name, &bearer_id);
 +	if (!node) {
  		read_unlock_bh(&tipc_net_lock);
  		return tipc_cfg_reply_error_string("link not found");
  	}
 -
  	tipc_node_lock(node);
 +	l_ptr = node->links[bearer_id];
 +	if (!l_ptr) {
 +		tipc_node_unlock(node);
 +		read_unlock_bh(&tipc_net_lock);
 +		return tipc_cfg_reply_error_string("link not found");
 +	}
  	link_reset_statistics(l_ptr);
  	tipc_node_unlock(node);
  	read_unlock_bh(&tipc_net_lock);
@@@ -2641,27 -2597,18 +2648,27 @@@ static int tipc_link_stats(const char *
  	struct tipc_node *node;
  	char *status;
  	u32 profile_total = 0;
 +	unsigned int bearer_id;
  	int ret;
  
  	if (!strcmp(name, tipc_bclink_name))
  		return tipc_bclink_stats(buf, buf_size);
  
  	read_lock_bh(&tipc_net_lock);
 -	l = link_find_link(name, &node);
 -	if (!l) {
 +	node = tipc_link_find_owner(name, &bearer_id);
 +	if (!node) {
  		read_unlock_bh(&tipc_net_lock);
  		return 0;
  	}
  	tipc_node_lock(node);
 +
 +	l = node->links[bearer_id];
 +	if (!l) {
 +		tipc_node_unlock(node);
 +		read_unlock_bh(&tipc_net_lock);
 +		return 0;
 +	}
 +
  	s = &l->stats;
  
  	if (tipc_link_is_active(l))

-- 
LinuxNextTracking


More information about the linux-merge mailing list