Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / drivers / net / bonding / bond_3ad.c
index 0ddf4c6..494bf96 100644 (file)
@@ -93,7 +93,7 @@
 // compare MAC addresses
 #define MAC_ADDRESS_COMPARE(A, B) memcmp(A, B, ETH_ALEN)
 
-static struct mac_addr null_mac_addr = {{0, 0, 0, 0, 0, 0}};
+static struct mac_addr null_mac_addr = { { 0, 0, 0, 0, 0, 0 } };
 static u16 ad_ticks_per_sec;
 static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
 
@@ -129,9 +129,8 @@ static void ad_marker_response_received(struct bond_marker *marker, struct port
  */
 static inline struct bonding *__get_bond_by_port(struct port *port)
 {
-       if (port->slave == NULL) {
+       if (port->slave == NULL)
                return NULL;
-       }
 
        return bond_get_bond_by_slave(port->slave);
 }
@@ -144,9 +143,8 @@ static inline struct bonding *__get_bond_by_port(struct port *port)
  */
 static inline struct port *__get_first_port(struct bonding *bond)
 {
-       if (bond->slave_cnt == 0) {
+       if (bond->slave_cnt == 0)
                return NULL;
-       }
 
        return &(SLAVE_AD_INFO(bond->first_slave).port);
 }
@@ -164,9 +162,8 @@ static inline struct port *__get_next_port(struct port *port)
        struct slave *slave = port->slave;
 
        // If there's no bond for this port, or this is the last slave
-       if ((bond == NULL) || (slave->next == bond->first_slave)) {
+       if ((bond == NULL) || (slave->next == bond->first_slave))
                return NULL;
-       }
 
        return &(SLAVE_AD_INFO(slave->next).port);
 }
@@ -183,9 +180,8 @@ static inline struct aggregator *__get_first_agg(struct port *port)
        struct bonding *bond = __get_bond_by_port(port);
 
        // If there's no bond for this port, or bond has no slaves
-       if ((bond == NULL) || (bond->slave_cnt == 0)) {
+       if ((bond == NULL) || (bond->slave_cnt == 0))
                return NULL;
-       }
 
        return &(SLAVE_AD_INFO(bond->first_slave).aggregator);
 }
@@ -203,9 +199,8 @@ static inline struct aggregator *__get_next_agg(struct aggregator *aggregator)
        struct bonding *bond = bond_get_bond_by_slave(slave);
 
        // If there's no bond for this aggregator, or this is the last slave
-       if ((bond == NULL) || (slave->next == bond->first_slave)) {
+       if ((bond == NULL) || (slave->next == bond->first_slave))
                return NULL;
-       }
 
        return &(SLAVE_AD_INFO(slave->next).aggregator);
 }
@@ -240,9 +235,8 @@ static inline void __enable_port(struct port *port)
 {
        struct slave *slave = port->slave;
 
-       if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) {
+       if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev))
                bond_set_slave_active_flags(slave);
-       }
 }
 
 /**
@@ -252,7 +246,7 @@ static inline void __enable_port(struct port *port)
  */
 static inline int __port_is_enabled(struct port *port)
 {
-       return(port->slave->state == BOND_STATE_ACTIVE);
+       return bond_is_active_slave(port->slave);
 }
 
 /**
@@ -265,9 +259,8 @@ static inline u32 __get_agg_selection_mode(struct port *port)
 {
        struct bonding *bond = __get_bond_by_port(port);
 
-       if (bond == NULL) {
+       if (bond == NULL)
                return BOND_AD_STABLE;
-       }
 
        return BOND_AD_INFO(bond).agg_select_mode;
 }
@@ -281,31 +274,30 @@ static inline int __check_agg_selection_timer(struct port *port)
 {
        struct bonding *bond = __get_bond_by_port(port);
 
-       if (bond == NULL) {
+       if (bond == NULL)
                return 0;
-       }
 
        return BOND_AD_INFO(bond).agg_select_timer ? 1 : 0;
 }
 
 /**
- * __get_rx_machine_lock - lock the port's RX machine
+ * __get_state_machine_lock - lock the port's state machines
  * @port: the port we're looking at
  *
  */
-static inline void __get_rx_machine_lock(struct port *port)
+static inline void __get_state_machine_lock(struct port *port)
 {
-       spin_lock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
+       spin_lock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock));
 }
 
 /**
- * __release_rx_machine_lock - unlock the port's RX machine
+ * __release_state_machine_lock - unlock the port's state machines
  * @port: the port we're looking at
  *
  */
-static inline void __release_rx_machine_lock(struct port *port)
+static inline void __release_state_machine_lock(struct port *port)
 {
-       spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
+       spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock));
 }
 
 /**
@@ -328,9 +320,9 @@ static u16 __get_link_speed(struct port *port)
         * link down, it sets the speed to 0.
         * This is done in spite of the fact that the e100 driver reports 0 to be
         * compatible with MVT in the future.*/
-       if (slave->link != BOND_LINK_UP) {
-               speed=0;
-       } else {
+       if (slave->link != BOND_LINK_UP)
+               speed = 0;
+       else {
                switch (slave->speed) {
                case SPEED_10:
                        speed = AD_LINK_SPEED_BITMASK_10MBPS;
@@ -375,18 +367,18 @@ static u8 __get_duplex(struct port *port)
 
        //  handling a special case: when the configuration starts with
        // link down, it sets the duplex to 0.
-       if (slave->link != BOND_LINK_UP) {
-               retval=0x0;
-       } else {
+       if (slave->link != BOND_LINK_UP)
+               retval = 0x0;
+       else {
                switch (slave->duplex) {
                case DUPLEX_FULL:
-                       retval=0x1;
+                       retval = 0x1;
                        pr_debug("Port %d Received status full duplex update from adapter\n",
                                 port->actor_port_number);
                        break;
                case DUPLEX_HALF:
                default:
-                       retval=0x0;
+                       retval = 0x0;
                        pr_debug("Port %d Received status NOT full duplex update from adapter\n",
                                 port->actor_port_number);
                        break;
@@ -396,14 +388,14 @@ static u8 __get_duplex(struct port *port)
 }
 
 /**
- * __initialize_port_locks - initialize a port's RX machine spinlock
+ * __initialize_port_locks - initialize a port's STATE machine spinlock
  * @port: the port we're looking at
  *
  */
 static inline void __initialize_port_locks(struct port *port)
 {
        // make sure it isn't called twice
-       spin_lock_init(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
+       spin_lock_init(&(SLAVE_AD_INFO(port->slave).state_machine_lock));
 }
 
 //conversions
@@ -419,15 +411,14 @@ static inline void __initialize_port_locks(struct port *port)
  */
 static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
 {
-       u16 retval=0;    //to silence the compiler
+       u16 retval = 0; /* to silence the compiler */
 
        switch (timer_type) {
        case AD_CURRENT_WHILE_TIMER:   // for rx machine usage
-               if (par) {            // for short or long timeout
+               if (par)
                        retval = (AD_SHORT_TIMEOUT_TIME*ad_ticks_per_sec); // short timeout
-               } else {
+               else
                        retval = (AD_LONG_TIMEOUT_TIME*ad_ticks_per_sec); // long timeout
-               }
                break;
        case AD_ACTOR_CHURN_TIMER:          // for local churn machine
                retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec);
@@ -519,11 +510,11 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
                port->actor_oper_port_state &= ~AD_STATE_DEFAULTED;
 
                // set the partner sync. to on if the partner is sync. and the port is matched
-               if ((port->sm_vars & AD_PORT_MATCHED) && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) {
+               if ((port->sm_vars & AD_PORT_MATCHED)
+                   && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION))
                        partner->port_state |= AD_STATE_SYNCHRONIZATION;
-               } else {
+               else
                        partner->port_state &= ~AD_STATE_SYNCHRONIZATION;
-               }
        }
 }
 
@@ -653,7 +644,7 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
  */
 static void __attach_bond_to_agg(struct port *port)
 {
-       port=NULL; // just to satisfy the compiler
+       port = NULL; /* just to satisfy the compiler */
        // This function does nothing since the parser/multiplexer of the receive
        // and the parser/multiplexer of the aggregator are already combined
 }
@@ -668,7 +659,7 @@ static void __attach_bond_to_agg(struct port *port)
  */
 static void __detach_bond_from_agg(struct port *port)
 {
-       port=NULL; // just to satisfy the compiler
+       port = NULL; /* just to satisfy the compiler */
        // This function does nothing sience the parser/multiplexer of the receive
        // and the parser/multiplexer of the aggregator are already combined
 }
@@ -685,7 +676,9 @@ static int __agg_ports_are_ready(struct aggregator *aggregator)
 
        if (aggregator) {
                // scan all ports in this aggregator to verfy if they are all ready
-               for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
+               for (port = aggregator->lag_ports;
+                    port;
+                    port = port->next_port_in_aggregator) {
                        if (!(port->sm_vars & AD_PORT_READY_N)) {
                                retval = 0;
                                break;
@@ -706,12 +699,12 @@ static void __set_agg_ports_ready(struct aggregator *aggregator, int val)
 {
        struct port *port;
 
-       for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
-               if (val) {
+       for (port = aggregator->lag_ports; port;
+            port = port->next_port_in_aggregator) {
+               if (val)
                        port->sm_vars |= AD_PORT_READY;
-               } else {
+               else
                        port->sm_vars &= ~AD_PORT_READY;
-               }
        }
 }
 
@@ -722,7 +715,7 @@ static void __set_agg_ports_ready(struct aggregator *aggregator, int val)
  */
 static u32 __get_agg_bandwidth(struct aggregator *aggregator)
 {
-       u32 bandwidth=0;
+       u32 bandwidth = 0;
        u32 basic_speed;
 
        if (aggregator->num_of_ports) {
@@ -744,7 +737,7 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
                        bandwidth = aggregator->num_of_ports * 10000;
                        break;
                default:
-                       bandwidth=0; // to silent the compilor ....
+                       bandwidth = 0; /*to silence the compiler ....*/
                }
        }
        return bandwidth;
@@ -835,9 +828,8 @@ static int ad_lacpdu_send(struct port *port)
        int length = sizeof(struct lacpdu_header);
 
        skb = dev_alloc_skb(length);
-       if (!skb) {
+       if (!skb)
                return -ENOMEM;
-       }
 
        skb->dev = slave->dev;
        skb_reset_mac_header(skb);
@@ -848,7 +840,7 @@ static int ad_lacpdu_send(struct port *port)
        lacpdu_header = (struct lacpdu_header *)skb_put(skb, length);
 
        memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
-       /* Note: source addres is set to be the member's PERMANENT address,
+       /* 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);
        lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU;
@@ -876,9 +868,8 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
        int length = sizeof(struct bond_marker_header);
 
        skb = dev_alloc_skb(length + 16);
-       if (!skb) {
+       if (!skb)
                return -ENOMEM;
-       }
 
        skb_reserve(skb, 16);
 
@@ -890,7 +881,7 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
        marker_header = (struct bond_marker_header *)skb_put(skb, length);
 
        memcpy(marker_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
-       /* Note: source addres is set to be the member's PERMANENT address,
+       /* 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);
        marker_header->hdr.h_proto = PKT_TYPE_LACPDU;
@@ -919,9 +910,10 @@ static void ad_mux_machine(struct port *port)
        } else {
                switch (port->sm_mux_state) {
                case AD_MUX_DETACHED:
-                       if ((port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) { // if SELECTED or STANDBY
+                       if ((port->sm_vars & AD_PORT_SELECTED)
+                           || (port->sm_vars & AD_PORT_STANDBY))
+                               /* if SELECTED or STANDBY */
                                port->sm_mux_state = AD_MUX_WAITING; // next state
-                       }
                        break;
                case AD_MUX_WAITING:
                        // if SELECTED == FALSE return to DETACH state
@@ -935,18 +927,18 @@ static void ad_mux_machine(struct port *port)
                        }
 
                        // check if the wait_while_timer expired
-                       if (port->sm_mux_timer_counter && !(--port->sm_mux_timer_counter)) {
+                       if (port->sm_mux_timer_counter
+                           && !(--port->sm_mux_timer_counter))
                                port->sm_vars |= AD_PORT_READY_N;
-                       }
 
                        // in order to withhold the selection logic to check all ports READY_N value
                        // every callback cycle to update ready variable, we check READY_N and update READY here
                        __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
 
                        // if the wait_while_timer expired, and the port is in READY state, move to ATTACHED state
-                       if ((port->sm_vars & AD_PORT_READY) && !port->sm_mux_timer_counter) {
+                       if ((port->sm_vars & AD_PORT_READY)
+                           && !port->sm_mux_timer_counter)
                                port->sm_mux_state = AD_MUX_ATTACHED;    // next state
-                       }
                        break;
                case AD_MUX_ATTACHED:
                        // check also if agg_select_timer expired(so the edable port will take place only after this timer)
@@ -1033,21 +1025,19 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
 {
        rx_states_t last_state;
 
-       // Lock to prevent 2 instances of this function to run simultaneously(rx interrupt and periodic machine callback)
-       __get_rx_machine_lock(port);
-
        // keep current State Machine state to compare later if it was changed
        last_state = port->sm_rx_state;
 
        // check if state machine should change state
        // first, check if port was reinitialized
-       if (port->sm_vars & AD_PORT_BEGIN) {
-               port->sm_rx_state = AD_RX_INITIALIZE;               // next state
-       }
+       if (port->sm_vars & AD_PORT_BEGIN)
+               /* next state */
+               port->sm_rx_state = AD_RX_INITIALIZE;
        // check if port is not enabled
-       else if (!(port->sm_vars & AD_PORT_BEGIN) && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED)) {
-               port->sm_rx_state = AD_RX_PORT_DISABLED;            // next state
-       }
+       else if (!(port->sm_vars & AD_PORT_BEGIN)
+                && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED))
+               /* next state */
+               port->sm_rx_state = AD_RX_PORT_DISABLED;
        // check if new lacpdu arrived
        else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || (port->sm_rx_state == AD_RX_DEFAULTED) || (port->sm_rx_state == AD_RX_CURRENT))) {
                port->sm_rx_timer_counter = 0; // zero timer
@@ -1069,13 +1059,16 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
                        // if no lacpdu arrived and no timer is on
                        switch (port->sm_rx_state) {
                        case AD_RX_PORT_DISABLED:
-                               if (port->sm_vars & AD_PORT_MOVED) {
+                               if (port->sm_vars & AD_PORT_MOVED)
                                        port->sm_rx_state = AD_RX_INITIALIZE;       // next state
-                               } else if (port->is_enabled && (port->sm_vars & AD_PORT_LACP_ENABLED)) {
+                               else if (port->is_enabled
+                                        && (port->sm_vars
+                                            & AD_PORT_LACP_ENABLED))
                                        port->sm_rx_state = AD_RX_EXPIRED;      // next state
-                               } else if (port->is_enabled && ((port->sm_vars & AD_PORT_LACP_ENABLED) == 0)) {
+                               else if (port->is_enabled
+                                        && ((port->sm_vars
+                                             & AD_PORT_LACP_ENABLED) == 0))
                                        port->sm_rx_state = AD_RX_LACP_DISABLED;    // next state
-                               }
                                break;
                        default:    //to silence the compiler
                                break;
@@ -1091,11 +1084,10 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
                         port->sm_rx_state);
                switch (port->sm_rx_state) {
                case AD_RX_INITIALIZE:
-                       if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
+                       if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS))
                                port->sm_vars &= ~AD_PORT_LACP_ENABLED;
-                       } else {
+                       else
                                port->sm_vars |= AD_PORT_LACP_ENABLED;
-                       }
                        port->sm_vars &= ~AD_PORT_SELECTED;
                        __record_default(port);
                        port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
@@ -1138,7 +1130,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
                                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->dev->master->name, port->slave->dev->name);
-                               __release_rx_machine_lock(port);
                                return;
                        }
                        __update_selected(lacpdu, port);
@@ -1149,15 +1140,15 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
                        // verify that if the aggregator is enabled, the port is enabled too.
                        //(because if the link goes down for a short time, the 802.3ad will not
                        // catch it, and the port will continue to be disabled)
-                       if (port->aggregator && port->aggregator->is_active && !__port_is_enabled(port)) {
+                       if (port->aggregator
+                           && port->aggregator->is_active
+                           && !__port_is_enabled(port))
                                __enable_port(port);
-                       }
                        break;
                default:    //to silence the compiler
                        break;
                }
        }
-       __release_rx_machine_lock(port);
 }
 
 /**
@@ -1183,7 +1174,8 @@ static void ad_tx_machine(struct port *port)
                        }
                }
                // restart tx timer(to verify that we will not exceed AD_MAX_TX_IN_SECOND
-               port->sm_tx_timer_counter=ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
+               port->sm_tx_timer_counter =
+                       ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
        }
 }
 
@@ -1216,9 +1208,9 @@ static void ad_periodic_machine(struct port *port)
                        // If not expired, check if there is some new timeout parameter from the partner state
                        switch (port->sm_periodic_state) {
                        case AD_FAST_PERIODIC:
-                               if (!(port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
+                               if (!(port->partner_oper.port_state
+                                     & AD_STATE_LACP_TIMEOUT))
                                        port->sm_periodic_state = AD_SLOW_PERIODIC;  // next state
-                               }
                                break;
                        case AD_SLOW_PERIODIC:
                                if ((port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
@@ -1237,11 +1229,11 @@ static void ad_periodic_machine(struct port *port)
                        port->sm_periodic_state = AD_FAST_PERIODIC;      // next state
                        break;
                case AD_PERIODIC_TX:
-                       if (!(port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
+                       if (!(port->partner_oper.port_state
+                             & AD_STATE_LACP_TIMEOUT))
                                port->sm_periodic_state = AD_SLOW_PERIODIC;  // next state
-                       } else {
+                       else
                                port->sm_periodic_state = AD_FAST_PERIODIC;  // next state
-                       }
                        break;
                default:    //to silence the compiler
                        break;
@@ -1287,35 +1279,37 @@ static void ad_port_selection_logic(struct port *port)
        int found = 0;
 
        // if the port is already Selected, do nothing
-       if (port->sm_vars & AD_PORT_SELECTED) {
+       if (port->sm_vars & AD_PORT_SELECTED)
                return;
-       }
 
        // if the port is connected to other aggregator, detach it
        if (port->aggregator) {
                // detach the port from its former aggregator
-               temp_aggregator=port->aggregator;
-               for (curr_port=temp_aggregator->lag_ports; curr_port; last_port=curr_port, curr_port=curr_port->next_port_in_aggregator) {
+               temp_aggregator = port->aggregator;
+               for (curr_port = temp_aggregator->lag_ports; curr_port;
+                    last_port = curr_port,
+                            curr_port = curr_port->next_port_in_aggregator) {
                        if (curr_port == port) {
                                temp_aggregator->num_of_ports--;
                                if (!last_port) {// if it is the first port attached to the aggregator
-                                       temp_aggregator->lag_ports=port->next_port_in_aggregator;
+                                       temp_aggregator->lag_ports =
+                                               port->next_port_in_aggregator;
                                } else {// not the first port attached to the aggregator
-                                       last_port->next_port_in_aggregator=port->next_port_in_aggregator;
+                                       last_port->next_port_in_aggregator =
+                                               port->next_port_in_aggregator;
                                }
 
                                // clear the port's relations to this aggregator
                                port->aggregator = NULL;
-                               port->next_port_in_aggregator=NULL;
-                               port->actor_port_aggregator_identifier=0;
+                               port->next_port_in_aggregator = NULL;
+                               port->actor_port_aggregator_identifier = 0;
 
                                pr_debug("Port %d left LAG %d\n",
                                         port->actor_port_number,
                                         temp_aggregator->aggregator_identifier);
                                // if the aggregator is empty, clear its parameters, and set it ready to be attached
-                               if (!temp_aggregator->lag_ports) {
+                               if (!temp_aggregator->lag_ports)
                                        ad_clear_agg(temp_aggregator);
-                               }
                                break;
                        }
                }
@@ -1333,9 +1327,8 @@ static void ad_port_selection_logic(struct port *port)
 
                // keep a free aggregator for later use(if needed)
                if (!aggregator->lag_ports) {
-                       if (!free_aggregator) {
-                               free_aggregator=aggregator;
-                       }
+                       if (!free_aggregator)
+                               free_aggregator = aggregator;
                        continue;
                }
                // check if current aggregator suits us
@@ -1350,10 +1343,11 @@ static void ad_port_selection_logic(struct port *port)
                   ) {
                        // attach to the founded aggregator
                        port->aggregator = aggregator;
-                       port->actor_port_aggregator_identifier=port->aggregator->aggregator_identifier;
-                       port->next_port_in_aggregator=aggregator->lag_ports;
+                       port->actor_port_aggregator_identifier =
+                               port->aggregator->aggregator_identifier;
+                       port->next_port_in_aggregator = aggregator->lag_ports;
                        port->aggregator->num_of_ports++;
-                       aggregator->lag_ports=port;
+                       aggregator->lag_ports = port;
                        pr_debug("Port %d joined LAG %d(existing LAG)\n",
                                 port->actor_port_number,
                                 port->aggregator->aggregator_identifier);
@@ -1370,20 +1364,23 @@ static void ad_port_selection_logic(struct port *port)
                if (free_aggregator) {
                        // assign port a new aggregator
                        port->aggregator = free_aggregator;
-                       port->actor_port_aggregator_identifier=port->aggregator->aggregator_identifier;
+                       port->actor_port_aggregator_identifier =
+                               port->aggregator->aggregator_identifier;
 
                        // update the new aggregator's parameters
                        // if port was responsed from the end-user
-                       if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS) {// if port is full duplex
+                       if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)
+                               /* if port is full duplex */
                                port->aggregator->is_individual = false;
-                       } else {
+                       else
                                port->aggregator->is_individual = true;
-                       }
 
                        port->aggregator->actor_admin_aggregator_key = port->actor_admin_port_key;
                        port->aggregator->actor_oper_aggregator_key = port->actor_oper_port_key;
-                       port->aggregator->partner_system=port->partner_oper.system;
-                       port->aggregator->partner_system_priority = port->partner_oper.system_priority;
+                       port->aggregator->partner_system =
+                               port->partner_oper.system;
+                       port->aggregator->partner_system_priority =
+                               port->partner_oper.system_priority;
                        port->aggregator->partner_oper_aggregator_key = port->partner_oper.key;
                        port->aggregator->receive_state = 1;
                        port->aggregator->transmit_state = 1;
@@ -1704,9 +1701,8 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
                port->actor_admin_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
                port->actor_oper_port_state  = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
 
-               if (lacp_fast) {
+               if (lacp_fast)
                        port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
-               }
 
                memcpy(&port->partner_admin, &tmpl, sizeof(tmpl));
                memcpy(&port->partner_oper, &tmpl, sizeof(tmpl));
@@ -1785,13 +1781,16 @@ static void ad_marker_info_send(struct port *port)
        marker.requester_port = (((port->actor_port_number & 0xFF) << 8) |((u16)(port->actor_port_number & 0xFF00) >> 8));
        marker.requester_system = port->actor_system;
        // convert requester_port(u32) to Big Endian
-       marker.requester_transaction_id = (((++port->transaction_id & 0xFF) << 24) |((port->transaction_id & 0xFF00) << 8) |((port->transaction_id & 0xFF0000) >> 8) |((port->transaction_id & 0xFF000000) >> 24));
+       marker.requester_transaction_id =
+               (((++port->transaction_id & 0xFF) << 24)
+                | ((port->transaction_id & 0xFF00) << 8)
+                | ((port->transaction_id & 0xFF0000) >> 8)
+                | ((port->transaction_id & 0xFF000000) >> 24));
        marker.pad = 0;
        marker.tlv_type_terminator = 0x00;
        marker.terminator_length = 0x00;
-       for (index=0; index<90; index++) {
-               marker.reserved_90[index]=0;
-       }
+       for (index = 0; index < 90; index++)
+               marker.reserved_90[index] = 0;
 
        // send the marker information
        if (ad_marker_send(port, &marker) >= 0) {
@@ -1816,7 +1815,7 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
        //marker = *marker_info;
        memcpy(&marker, marker_info, sizeof(struct bond_marker));
        // change the marker subtype to marker response
-       marker.tlv_type=AD_MARKER_RESPONSE_SUBTYPE;
+       marker.tlv_type = AD_MARKER_RESPONSE_SUBTYPE;
        // send the marker response
 
        if (ad_marker_send(port, &marker) >= 0) {
@@ -1837,8 +1836,8 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
 static void ad_marker_response_received(struct bond_marker *marker,
        struct port *port)
 {
-       marker=NULL; // just to satisfy the compiler
-       port=NULL;  // just to satisfy the compiler
+       marker = NULL; /* just to satisfy the compiler */
+       port = NULL;  /* just to satisfy the compiler */
        // DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW
 }
 
@@ -1912,7 +1911,7 @@ int bond_3ad_bind_slave(struct slave *slave)
                return -1;
        }
 
-       //check that the slave has not been intialized yet.
+       //check that the slave has not been initialized yet.
        if (SLAVE_AD_INFO(slave).port.slave != slave) {
 
                // port initialization
@@ -1932,9 +1931,8 @@ int bond_3ad_bind_slave(struct slave *slave)
                port->actor_admin_port_key |= (__get_link_speed(port) << 1);
                port->actor_oper_port_key = port->actor_admin_port_key;
                // if the port is not full duplex, then the port should be not lacp Enabled
-               if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
+               if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS))
                        port->sm_vars &= ~AD_PORT_LACP_ENABLED;
-               }
                // actor system is the bond's system
                port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr;
                // tx timer(to verify that no more than MAX_TX_IN_SECOND lacpdu's are sent in one second)
@@ -2006,9 +2004,10 @@ void bond_3ad_unbind_slave(struct slave *slave)
                        new_aggregator = __get_first_agg(port);
                        for (; new_aggregator; new_aggregator = __get_next_agg(new_aggregator)) {
                                // if the new aggregator is empty, or it is connected to our port only
-                               if (!new_aggregator->lag_ports || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator)) {
+                               if (!new_aggregator->lag_ports
+                                   || ((new_aggregator->lag_ports == port)
+                                       && !new_aggregator->lag_ports->next_port_in_aggregator))
                                        break;
-                               }
                        }
                        // if new aggregator found, copy the aggregator's parameters
                        // and connect the related lag_ports to the new aggregator
@@ -2037,17 +2036,17 @@ void bond_3ad_unbind_slave(struct slave *slave)
                                new_aggregator->num_of_ports = aggregator->num_of_ports;
 
                                // update the information that is written on the ports about the aggregator
-                               for (temp_port=aggregator->lag_ports; temp_port; temp_port=temp_port->next_port_in_aggregator) {
-                                       temp_port->aggregator=new_aggregator;
+                               for (temp_port = aggregator->lag_ports; temp_port;
+                                    temp_port = temp_port->next_port_in_aggregator) {
+                                       temp_port->aggregator = new_aggregator;
                                        temp_port->actor_port_aggregator_identifier = new_aggregator->aggregator_identifier;
                                }
 
                                // clear the aggregator
                                ad_clear_agg(aggregator);
 
-                               if (select_new_active_agg) {
+                               if (select_new_active_agg)
                                        ad_agg_selection_logic(__get_first_agg(port));
-                               }
                        } else {
                                pr_warning("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n",
                                           slave->dev->master->name);
@@ -2071,15 +2070,16 @@ void bond_3ad_unbind_slave(struct slave *slave)
        for (; temp_aggregator; temp_aggregator = __get_next_agg(temp_aggregator)) {
                prev_port = NULL;
                // search the port in the aggregator's related ports
-               for (temp_port=temp_aggregator->lag_ports; temp_port; prev_port=temp_port, temp_port=temp_port->next_port_in_aggregator) {
+               for (temp_port = temp_aggregator->lag_ports; temp_port;
+                    prev_port = temp_port,
+                            temp_port = temp_port->next_port_in_aggregator) {
                        if (temp_port == port) { // the aggregator found - detach the port from this aggregator
-                               if (prev_port) {
+                               if (prev_port)
                                        prev_port->next_port_in_aggregator = temp_port->next_port_in_aggregator;
-                               } else {
+                               else
                                        temp_aggregator->lag_ports = temp_port->next_port_in_aggregator;
-                               }
                                temp_aggregator->num_of_ports--;
-                               if (temp_aggregator->num_of_ports==0) {
+                               if (temp_aggregator->num_of_ports == 0) {
                                        select_new_active_agg = temp_aggregator->is_active;
                                        // clear the aggregator
                                        ad_clear_agg(temp_aggregator);
@@ -2094,7 +2094,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
                        }
                }
        }
-       port->slave=NULL;
+       port->slave = NULL;
 }
 
 /**
@@ -2119,14 +2119,12 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
 
        read_lock(&bond->lock);
 
-       if (bond->kill_timers) {
+       if (bond->kill_timers)
                goto out;
-       }
 
        //check if there are any slaves
-       if (bond->slave_cnt == 0) {
+       if (bond->slave_cnt == 0)
                goto re_arm;
-       }
 
        // check if agg_select_timer timer after initialize is timed out
        if (BOND_AD_INFO(bond).agg_select_timer && !(--BOND_AD_INFO(bond).agg_select_timer)) {
@@ -2152,6 +2150,12 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
                        goto re_arm;
                }
 
+               /* Lock around state machines to protect data accessed
+                * by all (e.g., port->sm_vars).  ad_rx_machine may run
+                * concurrently due to incoming LACPDU.
+                */
+               __get_state_machine_lock(port);
+
                ad_rx_machine(NULL, port);
                ad_periodic_machine(port);
                ad_port_selection_logic(port);
@@ -2159,9 +2163,10 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
                ad_tx_machine(port);
 
                // turn off the BEGIN bit, since we already handled it
-               if (port->sm_vars & AD_PORT_BEGIN) {
+               if (port->sm_vars & AD_PORT_BEGIN)
                        port->sm_vars &= ~AD_PORT_BEGIN;
-               }
+
+               __release_state_machine_lock(port);
        }
 
 re_arm:
@@ -2198,7 +2203,10 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
                case AD_TYPE_LACPDU:
                        pr_debug("Received LACPDU on port %d\n",
                                 port->actor_port_number);
+                       /* Protect against concurrent state machines */
+                       __get_state_machine_lock(port);
                        ad_rx_machine(lacpdu, port);
+                       __release_state_machine_lock(port);
                        break;
 
                case AD_TYPE_MARKER:
@@ -2245,7 +2253,8 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
        }
 
        port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
-       port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
+       port->actor_oper_port_key = port->actor_admin_port_key |=
+               (__get_link_speed(port) << 1);
        pr_debug("Port %d changed speed\n", port->actor_port_number);
        // there is no need to reselect a new aggregator, just signal the
        // state machines to reinitialize
@@ -2262,7 +2271,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
 {
        struct port *port;
 
-       port=&(SLAVE_AD_INFO(slave).port);
+       port = &(SLAVE_AD_INFO(slave).port);
 
        // if slave is null, the whole port is not initialized
        if (!port->slave) {
@@ -2272,7 +2281,8 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
        }
 
        port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
-       port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
+       port->actor_oper_port_key = port->actor_admin_port_key |=
+               __get_duplex(port);
        pr_debug("Port %d changed duplex\n", port->actor_port_number);
        // there is no need to reselect a new aggregator, just signal the
        // state machines to reinitialize
@@ -2304,14 +2314,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
        if (link == BOND_LINK_UP) {
                port->is_enabled = true;
                port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
-               port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
+               port->actor_oper_port_key = port->actor_admin_port_key |=
+                       __get_duplex(port);
                port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
-               port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
+               port->actor_oper_port_key = port->actor_admin_port_key |=
+                       (__get_link_speed(port) << 1);
        } else {
                /* link has failed */
                port->is_enabled = false;
                port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
-               port->actor_oper_port_key= (port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS);
+               port->actor_oper_port_key = (port->actor_admin_port_key &=
+                                            ~AD_SPEED_KEY_BITS);
        }
        //BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN")));
        // there is no need to reselect a new aggregator, just signal the
@@ -2394,9 +2407,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
         */
        read_lock(&bond->lock);
 
-       if (!BOND_IS_OK(bond)) {
+       if (!BOND_IS_OK(bond))
                goto out;
-       }
 
        if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
                pr_debug("%s: Error: bond_3ad_get_active_agg_info failed\n",
@@ -2420,9 +2432,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 
                if (agg && (agg->aggregator_identifier == agg_id)) {
                        slave_agg_no--;
-                       if (slave_agg_no < 0) {
+                       if (slave_agg_no < 0)
                                break;
-                       }
                }
        }
 
@@ -2438,9 +2449,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
                int slave_agg_id = 0;
                struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
 
-               if (agg) {
+               if (agg)
                        slave_agg_id = agg->aggregator_identifier;
-               }
 
                if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
                        res = bond_dev_queue_xmit(bond, skb, slave->dev);
@@ -2466,12 +2476,15 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac
        if (!(dev->flags & IFF_MASTER))
                goto out;
 
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (!skb)
+               goto out;
+
        if (!pskb_may_pull(skb, sizeof(struct lacpdu)))
                goto out;
 
        read_lock(&bond->lock);
-       slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev),
-                                       orig_dev);
+       slave = bond_get_slave_by_dev(netdev_priv(dev), orig_dev);
        if (!slave)
                goto out_unlock;