diff options
Diffstat (limited to 'drivers/net/bonding/bond_3ad.c')
-rw-r--r-- | drivers/net/bonding/bond_3ad.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 1024ae158227..a5d5d0b5b155 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c | |||
@@ -281,23 +281,23 @@ static inline int __check_agg_selection_timer(struct port *port) | |||
281 | } | 281 | } |
282 | 282 | ||
283 | /** | 283 | /** |
284 | * __get_rx_machine_lock - lock the port's RX machine | 284 | * __get_state_machine_lock - lock the port's state machines |
285 | * @port: the port we're looking at | 285 | * @port: the port we're looking at |
286 | * | 286 | * |
287 | */ | 287 | */ |
288 | static inline void __get_rx_machine_lock(struct port *port) | 288 | static inline void __get_state_machine_lock(struct port *port) |
289 | { | 289 | { |
290 | spin_lock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); | 290 | spin_lock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); |
291 | } | 291 | } |
292 | 292 | ||
293 | /** | 293 | /** |
294 | * __release_rx_machine_lock - unlock the port's RX machine | 294 | * __release_state_machine_lock - unlock the port's state machines |
295 | * @port: the port we're looking at | 295 | * @port: the port we're looking at |
296 | * | 296 | * |
297 | */ | 297 | */ |
298 | static inline void __release_rx_machine_lock(struct port *port) | 298 | static inline void __release_state_machine_lock(struct port *port) |
299 | { | 299 | { |
300 | spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); | 300 | spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); |
301 | } | 301 | } |
302 | 302 | ||
303 | /** | 303 | /** |
@@ -388,14 +388,14 @@ static u8 __get_duplex(struct port *port) | |||
388 | } | 388 | } |
389 | 389 | ||
390 | /** | 390 | /** |
391 | * __initialize_port_locks - initialize a port's RX machine spinlock | 391 | * __initialize_port_locks - initialize a port's STATE machine spinlock |
392 | * @port: the port we're looking at | 392 | * @port: the port we're looking at |
393 | * | 393 | * |
394 | */ | 394 | */ |
395 | static inline void __initialize_port_locks(struct port *port) | 395 | static inline void __initialize_port_locks(struct port *port) |
396 | { | 396 | { |
397 | // make sure it isn't called twice | 397 | // make sure it isn't called twice |
398 | spin_lock_init(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); | 398 | spin_lock_init(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); |
399 | } | 399 | } |
400 | 400 | ||
401 | //conversions | 401 | //conversions |
@@ -1025,9 +1025,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
1025 | { | 1025 | { |
1026 | rx_states_t last_state; | 1026 | rx_states_t last_state; |
1027 | 1027 | ||
1028 | // Lock to prevent 2 instances of this function to run simultaneously(rx interrupt and periodic machine callback) | ||
1029 | __get_rx_machine_lock(port); | ||
1030 | |||
1031 | // keep current State Machine state to compare later if it was changed | 1028 | // keep current State Machine state to compare later if it was changed |
1032 | last_state = port->sm_rx_state; | 1029 | last_state = port->sm_rx_state; |
1033 | 1030 | ||
@@ -1133,7 +1130,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
1133 | pr_err("%s: An illegal loopback occurred on adapter (%s).\n" | 1130 | pr_err("%s: An illegal loopback occurred on adapter (%s).\n" |
1134 | "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", | 1131 | "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", |
1135 | port->slave->dev->master->name, port->slave->dev->name); | 1132 | port->slave->dev->master->name, port->slave->dev->name); |
1136 | __release_rx_machine_lock(port); | ||
1137 | return; | 1133 | return; |
1138 | } | 1134 | } |
1139 | __update_selected(lacpdu, port); | 1135 | __update_selected(lacpdu, port); |
@@ -1153,7 +1149,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
1153 | break; | 1149 | break; |
1154 | } | 1150 | } |
1155 | } | 1151 | } |
1156 | __release_rx_machine_lock(port); | ||
1157 | } | 1152 | } |
1158 | 1153 | ||
1159 | /** | 1154 | /** |
@@ -2155,6 +2150,12 @@ void bond_3ad_state_machine_handler(struct work_struct *work) | |||
2155 | goto re_arm; | 2150 | goto re_arm; |
2156 | } | 2151 | } |
2157 | 2152 | ||
2153 | /* Lock around state machines to protect data accessed | ||
2154 | * by all (e.g., port->sm_vars). ad_rx_machine may run | ||
2155 | * concurrently due to incoming LACPDU. | ||
2156 | */ | ||
2157 | __get_state_machine_lock(port); | ||
2158 | |||
2158 | ad_rx_machine(NULL, port); | 2159 | ad_rx_machine(NULL, port); |
2159 | ad_periodic_machine(port); | 2160 | ad_periodic_machine(port); |
2160 | ad_port_selection_logic(port); | 2161 | ad_port_selection_logic(port); |
@@ -2164,6 +2165,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work) | |||
2164 | // turn off the BEGIN bit, since we already handled it | 2165 | // turn off the BEGIN bit, since we already handled it |
2165 | if (port->sm_vars & AD_PORT_BEGIN) | 2166 | if (port->sm_vars & AD_PORT_BEGIN) |
2166 | port->sm_vars &= ~AD_PORT_BEGIN; | 2167 | port->sm_vars &= ~AD_PORT_BEGIN; |
2168 | |||
2169 | __release_state_machine_lock(port); | ||
2167 | } | 2170 | } |
2168 | 2171 | ||
2169 | re_arm: | 2172 | re_arm: |
@@ -2200,7 +2203,10 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u | |||
2200 | case AD_TYPE_LACPDU: | 2203 | case AD_TYPE_LACPDU: |
2201 | pr_debug("Received LACPDU on port %d\n", | 2204 | pr_debug("Received LACPDU on port %d\n", |
2202 | port->actor_port_number); | 2205 | port->actor_port_number); |
2206 | /* Protect against concurrent state machines */ | ||
2207 | __get_state_machine_lock(port); | ||
2203 | ad_rx_machine(lacpdu, port); | 2208 | ad_rx_machine(lacpdu, port); |
2209 | __release_state_machine_lock(port); | ||
2204 | break; | 2210 | break; |
2205 | 2211 | ||
2206 | case AD_TYPE_MARKER: | 2212 | case AD_TYPE_MARKER: |