static void ad_mux_machine(struct port *port, bool *update_slave_arr)
{
struct bonding *bond = __get_bond_by_port(port);
+ struct aggregator *aggregator;
mux_states_t last_state;
/* keep current State Machine state to compare later if it was
*/
last_state = port->sm_mux_state;
+ aggregator = rcu_dereference(port->aggregator);
if (port->sm_vars & AD_PORT_BEGIN) {
port->sm_mux_state = AD_MUX_DETACHED;
} else {
* 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));
+ __set_agg_ports_ready(aggregator, __agg_ports_are_ready(aggregator));
port->sm_mux_state = AD_MUX_DETACHED;
break;
}
* update ready variable, we check READY_N and update
* READY here
*/
- __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
+ __set_agg_ports_ready(aggregator, __agg_ports_are_ready(aggregator));
/* if the wait_while_timer expired, and the port is
* in READY state, move to ATTACHED state
if ((port->sm_vars & AD_PORT_SELECTED) &&
(port->partner_oper.port_state & LACP_STATE_SYNCHRONIZATION) &&
!__check_agg_selection_timer(port)) {
- if (port->aggregator->is_active) {
+ if (aggregator->is_active) {
int state = AD_MUX_COLLECTING_DISTRIBUTING;
if (!bond->params.coupled_control)
* 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));
+ __set_agg_ports_ready(aggregator, __agg_ports_are_ready(aggregator));
port->sm_mux_state = AD_MUX_DETACHED;
- } else if (port->aggregator->is_active) {
+ } else if (aggregator->is_active) {
port->actor_oper_port_state |=
LACP_STATE_SYNCHRONIZATION;
}
* sure that a collecting distributing
* port in an active aggregator is enabled
*/
- if (port->aggregator->is_active &&
+ if (aggregator->is_active &&
!__port_is_collecting_distributing(port)) {
__enable_port(port);
*update_slave_arr = true;
*/
struct slave *slave = port->slave;
- if (port->aggregator->is_active &&
+ if (aggregator->is_active &&
bond_is_slave_rx_disabled(slave)) {
ad_enable_collecting(port);
*update_slave_arr = true;
* sure that a collecting distributing
* port in an active aggregator is enabled
*/
- if (port->aggregator &&
- port->aggregator->is_active &&
+ if (aggregator &&
+ aggregator->is_active &&
!__port_is_collecting_distributing(port)) {
__enable_port(port);
*update_slave_arr = true;
port->sm_mux_timer_counter = __ad_timer_to_ticks(AD_WAIT_WHILE_TIMER, 0);
break;
case AD_MUX_ATTACHED:
- if (port->aggregator->is_active)
+ if (aggregator->is_active)
port->actor_oper_port_state |=
LACP_STATE_SYNCHRONIZATION;
else
bond = __get_bond_by_port(port);
/* if the port is connected to other aggregator, detach it */
- if (port->aggregator) {
+ temp_aggregator = rcu_dereference(port->aggregator);
+ if (temp_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) {
/* clear the port's relations to this
* aggregator
*/
- port->aggregator = NULL;
+ RCU_INIT_POINTER(port->aggregator, NULL);
port->next_port_in_aggregator = NULL;
port->actor_port_aggregator_identifier = 0;
port->slave->bond->dev->name,
port->slave->dev->name,
port->actor_port_number,
- port->aggregator->aggregator_identifier);
+ temp_aggregator->aggregator_identifier);
}
}
/* search on all aggregators for a suitable aggregator for this port */
)
) {
/* attach to the founded aggregator */
- port->aggregator = aggregator;
+ rcu_assign_pointer(port->aggregator, aggregator);
port->actor_port_aggregator_identifier =
- port->aggregator->aggregator_identifier;
+ aggregator->aggregator_identifier;
port->next_port_in_aggregator = aggregator->lag_ports;
- port->aggregator->num_of_ports++;
+ aggregator->num_of_ports++;
aggregator->lag_ports = port;
slave_dbg(bond->dev, slave->dev, "Port %d joined LAG %d (existing LAG)\n",
port->actor_port_number,
- port->aggregator->aggregator_identifier);
+ aggregator->aggregator_identifier);
/* mark this port as selected */
port->sm_vars |= AD_PORT_SELECTED;
if (!found) {
if (free_aggregator) {
/* assign port a new aggregator */
- port->aggregator = free_aggregator;
port->actor_port_aggregator_identifier =
- port->aggregator->aggregator_identifier;
+ free_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_MASKS)
/* if port is full duplex */
- port->aggregator->is_individual = false;
+ free_aggregator->is_individual = false;
else
- port->aggregator->is_individual = true;
+ free_aggregator->is_individual = true;
- port->aggregator->actor_admin_aggregator_key =
+ free_aggregator->actor_admin_aggregator_key =
port->actor_admin_port_key;
- port->aggregator->actor_oper_aggregator_key =
+ free_aggregator->actor_oper_aggregator_key =
port->actor_oper_port_key;
- port->aggregator->partner_system =
+ free_aggregator->partner_system =
port->partner_oper.system;
- port->aggregator->partner_system_priority =
+ free_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;
- port->aggregator->lag_ports = port;
- port->aggregator->num_of_ports++;
+ free_aggregator->partner_oper_aggregator_key = port->partner_oper.key;
+ free_aggregator->receive_state = 1;
+ free_aggregator->transmit_state = 1;
+ free_aggregator->lag_ports = port;
+ free_aggregator->num_of_ports++;
+
+ rcu_assign_pointer(port->aggregator, free_aggregator);
/* mark this port as selected */
port->sm_vars |= AD_PORT_SELECTED;
slave_dbg(bond->dev, port->slave->dev, "Port %d joined LAG %d (new LAG)\n",
port->actor_port_number,
- port->aggregator->aggregator_identifier);
+ free_aggregator->aggregator_identifier);
} else {
slave_err(bond->dev, port->slave->dev,
"Port %d did not find a suitable aggregator\n",
* in all aggregator's ports, else set ready=FALSE in all
* aggregator's ports
*/
- __set_agg_ports_ready(port->aggregator,
- __agg_ports_are_ready(port->aggregator));
+ aggregator = rcu_dereference(port->aggregator);
+ __set_agg_ports_ready(aggregator, __agg_ports_are_ready(aggregator));
- aggregator = __get_first_agg(port);
- ad_agg_selection_logic(aggregator, update_slave_arr);
+ ad_agg_selection_logic(__get_first_agg(port), update_slave_arr);
- if (!port->aggregator->is_active)
+ if (!aggregator->is_active)
port->actor_oper_port_state &= ~LACP_STATE_SYNCHRONIZATION;
}
*/
static void ad_enable_collecting(struct port *port)
{
- if (port->aggregator->is_active) {
+ struct aggregator *aggregator = rcu_dereference(port->aggregator);
+
+ if (aggregator->is_active) {
struct slave *slave = port->slave;
slave_dbg(slave->bond->dev, slave->dev,
"Enabling collecting on port %d (LAG %d)\n",
port->actor_port_number,
- port->aggregator->aggregator_identifier);
+ aggregator->aggregator_identifier);
__enable_collecting_port(port);
}
}
*/
static void ad_disable_distributing(struct port *port, bool *update_slave_arr)
{
- if (port->aggregator && __agg_has_partner(port->aggregator)) {
+ struct aggregator *aggregator = rcu_dereference(port->aggregator);
+
+ if (aggregator && __agg_has_partner(aggregator)) {
slave_dbg(port->slave->bond->dev, port->slave->dev,
"Disabling distributing on port %d (LAG %d)\n",
port->actor_port_number,
- port->aggregator->aggregator_identifier);
+ aggregator->aggregator_identifier);
__disable_distributing_port(port);
/* Slave array needs an update */
*update_slave_arr = true;
static void ad_enable_collecting_distributing(struct port *port,
bool *update_slave_arr)
{
- if (port->aggregator->is_active) {
+ struct aggregator *aggregator = rcu_dereference(port->aggregator);
+
+ if (aggregator->is_active) {
slave_dbg(port->slave->bond->dev, port->slave->dev,
"Enabling port %d (LAG %d)\n",
port->actor_port_number,
- port->aggregator->aggregator_identifier);
+ aggregator->aggregator_identifier);
__enable_port(port);
/* Slave array needs update */
*update_slave_arr = true;
static void ad_disable_collecting_distributing(struct port *port,
bool *update_slave_arr)
{
- if (port->aggregator && __agg_has_partner(port->aggregator)) {
+ struct aggregator *aggregator = rcu_dereference(port->aggregator);
+
+ if (aggregator && __agg_has_partner(aggregator)) {
slave_dbg(port->slave->bond->dev, port->slave->dev,
"Disabling port %d (LAG %d)\n",
port->actor_port_number,
- port->aggregator->aggregator_identifier);
+ aggregator->aggregator_identifier);
__disable_port(port);
/* Slave array needs an update */
*update_slave_arr = true;
*/
for (temp_port = aggregator->lag_ports; temp_port;
temp_port = temp_port->next_port_in_aggregator) {
- temp_port->aggregator = new_aggregator;
+ rcu_assign_pointer(temp_port->aggregator, new_aggregator);
temp_port->actor_port_aggregator_identifier = new_aggregator->aggregator_identifier;
}
int __bond_3ad_get_active_agg_info(struct bonding *bond,
struct ad_info *ad_info)
{
- struct aggregator *aggregator = NULL;
+ struct aggregator *aggregator = NULL, *tmp;
struct list_head *iter;
struct slave *slave;
struct port *port;
bond_for_each_slave_rcu(bond, slave, iter) {
port = &(SLAVE_AD_INFO(slave)->port);
- if (port->aggregator && port->aggregator->is_active) {
- aggregator = port->aggregator;
+ tmp = rcu_dereference(port->aggregator);
+ if (tmp && tmp->is_active) {
+ aggregator = tmp;
break;
}
}