diff options
author | Maxim Uvarov <maxim.uvarov@oracle.com> | 2012-01-09 07:01:37 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-01-11 15:52:26 -0500 |
commit | f515e6b77045b4b1f54617d9fbf4a22b95a58757 (patch) | |
tree | d01dfbd06052f13c88aa6a93b69e9d33cc87c20c /drivers/net/bonding | |
parent | d6c25beba35a76c002bff9235484d75a6f8e7e6b (diff) |
bond_alb: don't disable softirq under bond_alb_xmit
No need to lock soft irqs under bond_alb_xmit()
which already has softirq disabled.
Changes:
1. add non-bh/bh version to tlb_clear_slave()
2. represent BH and non BH hash table locks
_lock_rx_hashtbl_bh/_unlock_rx_hashtbl_bh
_lock_rx_hashtbl/_unlock_rx_hashtbl
_lock_tx_hashtbl_bh/_unlock_tx_hashtbl_bh
_lock_tx_hashtbl/_unlock_tx_hashtbl
Signed-off-by: Maxim Uvarov <maxim.uvarov@oracle.com>
Signed-off-by: Cong Wang <amwang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r-- | drivers/net/bonding/bond_alb.c | 112 |
1 files changed, 76 insertions, 36 deletions
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 106b88a0473..342626f4bc4 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c | |||
@@ -99,16 +99,26 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size) | |||
99 | 99 | ||
100 | /*********************** tlb specific functions ***************************/ | 100 | /*********************** tlb specific functions ***************************/ |
101 | 101 | ||
102 | static inline void _lock_tx_hashtbl(struct bonding *bond) | 102 | static inline void _lock_tx_hashtbl_bh(struct bonding *bond) |
103 | { | 103 | { |
104 | spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); | 104 | spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); |
105 | } | 105 | } |
106 | 106 | ||
107 | static inline void _unlock_tx_hashtbl(struct bonding *bond) | 107 | static inline void _unlock_tx_hashtbl_bh(struct bonding *bond) |
108 | { | 108 | { |
109 | spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); | 109 | spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); |
110 | } | 110 | } |
111 | 111 | ||
112 | static inline void _lock_tx_hashtbl(struct bonding *bond) | ||
113 | { | ||
114 | spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); | ||
115 | } | ||
116 | |||
117 | static inline void _unlock_tx_hashtbl(struct bonding *bond) | ||
118 | { | ||
119 | spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); | ||
120 | } | ||
121 | |||
112 | /* Caller must hold tx_hashtbl lock */ | 122 | /* Caller must hold tx_hashtbl lock */ |
113 | static inline void tlb_init_table_entry(struct tlb_client_info *entry, int save_load) | 123 | static inline void tlb_init_table_entry(struct tlb_client_info *entry, int save_load) |
114 | { | 124 | { |
@@ -129,14 +139,13 @@ static inline void tlb_init_slave(struct slave *slave) | |||
129 | SLAVE_TLB_INFO(slave).head = TLB_NULL_INDEX; | 139 | SLAVE_TLB_INFO(slave).head = TLB_NULL_INDEX; |
130 | } | 140 | } |
131 | 141 | ||
132 | /* Caller must hold bond lock for read */ | 142 | /* Caller must hold bond lock for read, BH disabled */ |
133 | static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_load) | 143 | static void __tlb_clear_slave(struct bonding *bond, struct slave *slave, |
144 | int save_load) | ||
134 | { | 145 | { |
135 | struct tlb_client_info *tx_hash_table; | 146 | struct tlb_client_info *tx_hash_table; |
136 | u32 index; | 147 | u32 index; |
137 | 148 | ||
138 | _lock_tx_hashtbl(bond); | ||
139 | |||
140 | /* clear slave from tx_hashtbl */ | 149 | /* clear slave from tx_hashtbl */ |
141 | tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl; | 150 | tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl; |
142 | 151 | ||
@@ -151,8 +160,15 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_ | |||
151 | } | 160 | } |
152 | 161 | ||
153 | tlb_init_slave(slave); | 162 | tlb_init_slave(slave); |
163 | } | ||
154 | 164 | ||
155 | _unlock_tx_hashtbl(bond); | 165 | /* Caller must hold bond lock for read */ |
166 | static void tlb_clear_slave(struct bonding *bond, struct slave *slave, | ||
167 | int save_load) | ||
168 | { | ||
169 | _lock_tx_hashtbl_bh(bond); | ||
170 | __tlb_clear_slave(bond, slave, save_load); | ||
171 | _unlock_tx_hashtbl_bh(bond); | ||
156 | } | 172 | } |
157 | 173 | ||
158 | /* Must be called before starting the monitor timer */ | 174 | /* Must be called before starting the monitor timer */ |
@@ -169,7 +185,7 @@ static int tlb_initialize(struct bonding *bond) | |||
169 | bond->dev->name); | 185 | bond->dev->name); |
170 | return -1; | 186 | return -1; |
171 | } | 187 | } |
172 | _lock_tx_hashtbl(bond); | 188 | _lock_tx_hashtbl_bh(bond); |
173 | 189 | ||
174 | bond_info->tx_hashtbl = new_hashtbl; | 190 | bond_info->tx_hashtbl = new_hashtbl; |
175 | 191 | ||
@@ -177,7 +193,7 @@ static int tlb_initialize(struct bonding *bond) | |||
177 | tlb_init_table_entry(&bond_info->tx_hashtbl[i], 0); | 193 | tlb_init_table_entry(&bond_info->tx_hashtbl[i], 0); |
178 | } | 194 | } |
179 | 195 | ||
180 | _unlock_tx_hashtbl(bond); | 196 | _unlock_tx_hashtbl_bh(bond); |
181 | 197 | ||
182 | return 0; | 198 | return 0; |
183 | } | 199 | } |
@@ -187,12 +203,12 @@ static void tlb_deinitialize(struct bonding *bond) | |||
187 | { | 203 | { |
188 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); | 204 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); |
189 | 205 | ||
190 | _lock_tx_hashtbl(bond); | 206 | _lock_tx_hashtbl_bh(bond); |
191 | 207 | ||
192 | kfree(bond_info->tx_hashtbl); | 208 | kfree(bond_info->tx_hashtbl); |
193 | bond_info->tx_hashtbl = NULL; | 209 | bond_info->tx_hashtbl = NULL; |
194 | 210 | ||
195 | _unlock_tx_hashtbl(bond); | 211 | _unlock_tx_hashtbl_bh(bond); |
196 | } | 212 | } |
197 | 213 | ||
198 | static long long compute_gap(struct slave *slave) | 214 | static long long compute_gap(struct slave *slave) |
@@ -226,15 +242,13 @@ static struct slave *tlb_get_least_loaded_slave(struct bonding *bond) | |||
226 | return least_loaded; | 242 | return least_loaded; |
227 | } | 243 | } |
228 | 244 | ||
229 | /* Caller must hold bond lock for read */ | 245 | static struct slave *__tlb_choose_channel(struct bonding *bond, u32 hash_index, |
230 | static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len) | 246 | u32 skb_len) |
231 | { | 247 | { |
232 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); | 248 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); |
233 | struct tlb_client_info *hash_table; | 249 | struct tlb_client_info *hash_table; |
234 | struct slave *assigned_slave; | 250 | struct slave *assigned_slave; |
235 | 251 | ||
236 | _lock_tx_hashtbl(bond); | ||
237 | |||
238 | hash_table = bond_info->tx_hashtbl; | 252 | hash_table = bond_info->tx_hashtbl; |
239 | assigned_slave = hash_table[hash_index].tx_slave; | 253 | assigned_slave = hash_table[hash_index].tx_slave; |
240 | if (!assigned_slave) { | 254 | if (!assigned_slave) { |
@@ -263,22 +277,46 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3 | |||
263 | hash_table[hash_index].tx_bytes += skb_len; | 277 | hash_table[hash_index].tx_bytes += skb_len; |
264 | } | 278 | } |
265 | 279 | ||
266 | _unlock_tx_hashtbl(bond); | ||
267 | |||
268 | return assigned_slave; | 280 | return assigned_slave; |
269 | } | 281 | } |
270 | 282 | ||
283 | /* Caller must hold bond lock for read */ | ||
284 | static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, | ||
285 | u32 skb_len) | ||
286 | { | ||
287 | struct slave *tx_slave; | ||
288 | /* | ||
289 | * We don't need to disable softirq here, becase | ||
290 | * tlb_choose_channel() is only called by bond_alb_xmit() | ||
291 | * which already has softirq disabled. | ||
292 | */ | ||
293 | _lock_tx_hashtbl(bond); | ||
294 | tx_slave = __tlb_choose_channel(bond, hash_index, skb_len); | ||
295 | _unlock_tx_hashtbl(bond); | ||
296 | return tx_slave; | ||
297 | } | ||
298 | |||
271 | /*********************** rlb specific functions ***************************/ | 299 | /*********************** rlb specific functions ***************************/ |
272 | static inline void _lock_rx_hashtbl(struct bonding *bond) | 300 | static inline void _lock_rx_hashtbl_bh(struct bonding *bond) |
273 | { | 301 | { |
274 | spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); | 302 | spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); |
275 | } | 303 | } |
276 | 304 | ||
277 | static inline void _unlock_rx_hashtbl(struct bonding *bond) | 305 | static inline void _unlock_rx_hashtbl_bh(struct bonding *bond) |
278 | { | 306 | { |
279 | spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); | 307 | spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); |
280 | } | 308 | } |
281 | 309 | ||
310 | static inline void _lock_rx_hashtbl(struct bonding *bond) | ||
311 | { | ||
312 | spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); | ||
313 | } | ||
314 | |||
315 | static inline void _unlock_rx_hashtbl(struct bonding *bond) | ||
316 | { | ||
317 | spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); | ||
318 | } | ||
319 | |||
282 | /* when an ARP REPLY is received from a client update its info | 320 | /* when an ARP REPLY is received from a client update its info |
283 | * in the rx_hashtbl | 321 | * in the rx_hashtbl |
284 | */ | 322 | */ |
@@ -288,7 +326,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp) | |||
288 | struct rlb_client_info *client_info; | 326 | struct rlb_client_info *client_info; |
289 | u32 hash_index; | 327 | u32 hash_index; |
290 | 328 | ||
291 | _lock_rx_hashtbl(bond); | 329 | _lock_rx_hashtbl_bh(bond); |
292 | 330 | ||
293 | hash_index = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src)); | 331 | hash_index = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src)); |
294 | client_info = &(bond_info->rx_hashtbl[hash_index]); | 332 | client_info = &(bond_info->rx_hashtbl[hash_index]); |
@@ -303,7 +341,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp) | |||
303 | bond_info->rx_ntt = 1; | 341 | bond_info->rx_ntt = 1; |
304 | } | 342 | } |
305 | 343 | ||
306 | _unlock_rx_hashtbl(bond); | 344 | _unlock_rx_hashtbl_bh(bond); |
307 | } | 345 | } |
308 | 346 | ||
309 | static void rlb_arp_recv(struct sk_buff *skb, struct bonding *bond, | 347 | static void rlb_arp_recv(struct sk_buff *skb, struct bonding *bond, |
@@ -401,7 +439,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave) | |||
401 | u32 index, next_index; | 439 | u32 index, next_index; |
402 | 440 | ||
403 | /* clear slave from rx_hashtbl */ | 441 | /* clear slave from rx_hashtbl */ |
404 | _lock_rx_hashtbl(bond); | 442 | _lock_rx_hashtbl_bh(bond); |
405 | 443 | ||
406 | rx_hash_table = bond_info->rx_hashtbl; | 444 | rx_hash_table = bond_info->rx_hashtbl; |
407 | index = bond_info->rx_hashtbl_head; | 445 | index = bond_info->rx_hashtbl_head; |
@@ -432,7 +470,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave) | |||
432 | } | 470 | } |
433 | } | 471 | } |
434 | 472 | ||
435 | _unlock_rx_hashtbl(bond); | 473 | _unlock_rx_hashtbl_bh(bond); |
436 | 474 | ||
437 | write_lock_bh(&bond->curr_slave_lock); | 475 | write_lock_bh(&bond->curr_slave_lock); |
438 | 476 | ||
@@ -489,7 +527,7 @@ static void rlb_update_rx_clients(struct bonding *bond) | |||
489 | struct rlb_client_info *client_info; | 527 | struct rlb_client_info *client_info; |
490 | u32 hash_index; | 528 | u32 hash_index; |
491 | 529 | ||
492 | _lock_rx_hashtbl(bond); | 530 | _lock_rx_hashtbl_bh(bond); |
493 | 531 | ||
494 | hash_index = bond_info->rx_hashtbl_head; | 532 | hash_index = bond_info->rx_hashtbl_head; |
495 | for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) { | 533 | for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) { |
@@ -507,7 +545,7 @@ static void rlb_update_rx_clients(struct bonding *bond) | |||
507 | */ | 545 | */ |
508 | bond_info->rlb_update_delay_counter = RLB_UPDATE_DELAY; | 546 | bond_info->rlb_update_delay_counter = RLB_UPDATE_DELAY; |
509 | 547 | ||
510 | _unlock_rx_hashtbl(bond); | 548 | _unlock_rx_hashtbl_bh(bond); |
511 | } | 549 | } |
512 | 550 | ||
513 | /* The slave was assigned a new mac address - update the clients */ | 551 | /* The slave was assigned a new mac address - update the clients */ |
@@ -518,7 +556,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla | |||
518 | int ntt = 0; | 556 | int ntt = 0; |
519 | u32 hash_index; | 557 | u32 hash_index; |
520 | 558 | ||
521 | _lock_rx_hashtbl(bond); | 559 | _lock_rx_hashtbl_bh(bond); |
522 | 560 | ||
523 | hash_index = bond_info->rx_hashtbl_head; | 561 | hash_index = bond_info->rx_hashtbl_head; |
524 | for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) { | 562 | for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) { |
@@ -538,7 +576,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla | |||
538 | bond_info->rlb_update_retry_counter = RLB_UPDATE_RETRY; | 576 | bond_info->rlb_update_retry_counter = RLB_UPDATE_RETRY; |
539 | } | 577 | } |
540 | 578 | ||
541 | _unlock_rx_hashtbl(bond); | 579 | _unlock_rx_hashtbl_bh(bond); |
542 | } | 580 | } |
543 | 581 | ||
544 | /* mark all clients using src_ip to be updated */ | 582 | /* mark all clients using src_ip to be updated */ |
@@ -709,7 +747,7 @@ static void rlb_rebalance(struct bonding *bond) | |||
709 | int ntt; | 747 | int ntt; |
710 | u32 hash_index; | 748 | u32 hash_index; |
711 | 749 | ||
712 | _lock_rx_hashtbl(bond); | 750 | _lock_rx_hashtbl_bh(bond); |
713 | 751 | ||
714 | ntt = 0; | 752 | ntt = 0; |
715 | hash_index = bond_info->rx_hashtbl_head; | 753 | hash_index = bond_info->rx_hashtbl_head; |
@@ -727,7 +765,7 @@ static void rlb_rebalance(struct bonding *bond) | |||
727 | if (ntt) { | 765 | if (ntt) { |
728 | bond_info->rx_ntt = 1; | 766 | bond_info->rx_ntt = 1; |
729 | } | 767 | } |
730 | _unlock_rx_hashtbl(bond); | 768 | _unlock_rx_hashtbl_bh(bond); |
731 | } | 769 | } |
732 | 770 | ||
733 | /* Caller must hold rx_hashtbl lock */ | 771 | /* Caller must hold rx_hashtbl lock */ |
@@ -751,7 +789,7 @@ static int rlb_initialize(struct bonding *bond) | |||
751 | bond->dev->name); | 789 | bond->dev->name); |
752 | return -1; | 790 | return -1; |
753 | } | 791 | } |
754 | _lock_rx_hashtbl(bond); | 792 | _lock_rx_hashtbl_bh(bond); |
755 | 793 | ||
756 | bond_info->rx_hashtbl = new_hashtbl; | 794 | bond_info->rx_hashtbl = new_hashtbl; |
757 | 795 | ||
@@ -761,7 +799,7 @@ static int rlb_initialize(struct bonding *bond) | |||
761 | rlb_init_table_entry(bond_info->rx_hashtbl + i); | 799 | rlb_init_table_entry(bond_info->rx_hashtbl + i); |
762 | } | 800 | } |
763 | 801 | ||
764 | _unlock_rx_hashtbl(bond); | 802 | _unlock_rx_hashtbl_bh(bond); |
765 | 803 | ||
766 | /* register to receive ARPs */ | 804 | /* register to receive ARPs */ |
767 | bond->recv_probe = rlb_arp_recv; | 805 | bond->recv_probe = rlb_arp_recv; |
@@ -773,13 +811,13 @@ static void rlb_deinitialize(struct bonding *bond) | |||
773 | { | 811 | { |
774 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); | 812 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); |
775 | 813 | ||
776 | _lock_rx_hashtbl(bond); | 814 | _lock_rx_hashtbl_bh(bond); |
777 | 815 | ||
778 | kfree(bond_info->rx_hashtbl); | 816 | kfree(bond_info->rx_hashtbl); |
779 | bond_info->rx_hashtbl = NULL; | 817 | bond_info->rx_hashtbl = NULL; |
780 | bond_info->rx_hashtbl_head = RLB_NULL_INDEX; | 818 | bond_info->rx_hashtbl_head = RLB_NULL_INDEX; |
781 | 819 | ||
782 | _unlock_rx_hashtbl(bond); | 820 | _unlock_rx_hashtbl_bh(bond); |
783 | } | 821 | } |
784 | 822 | ||
785 | static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id) | 823 | static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id) |
@@ -787,7 +825,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id) | |||
787 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); | 825 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); |
788 | u32 curr_index; | 826 | u32 curr_index; |
789 | 827 | ||
790 | _lock_rx_hashtbl(bond); | 828 | _lock_rx_hashtbl_bh(bond); |
791 | 829 | ||
792 | curr_index = bond_info->rx_hashtbl_head; | 830 | curr_index = bond_info->rx_hashtbl_head; |
793 | while (curr_index != RLB_NULL_INDEX) { | 831 | while (curr_index != RLB_NULL_INDEX) { |
@@ -812,7 +850,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id) | |||
812 | curr_index = next_index; | 850 | curr_index = next_index; |
813 | } | 851 | } |
814 | 852 | ||
815 | _unlock_rx_hashtbl(bond); | 853 | _unlock_rx_hashtbl_bh(bond); |
816 | } | 854 | } |
817 | 855 | ||
818 | /*********************** tlb/rlb shared functions *********************/ | 856 | /*********************** tlb/rlb shared functions *********************/ |
@@ -1320,7 +1358,9 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) | |||
1320 | res = bond_dev_queue_xmit(bond, skb, tx_slave->dev); | 1358 | res = bond_dev_queue_xmit(bond, skb, tx_slave->dev); |
1321 | } else { | 1359 | } else { |
1322 | if (tx_slave) { | 1360 | if (tx_slave) { |
1323 | tlb_clear_slave(bond, tx_slave, 0); | 1361 | _lock_tx_hashtbl(bond); |
1362 | __tlb_clear_slave(bond, tx_slave, 0); | ||
1363 | _unlock_tx_hashtbl(bond); | ||
1324 | } | 1364 | } |
1325 | } | 1365 | } |
1326 | 1366 | ||