diff options
Diffstat (limited to 'net/tipc/bearer.c')
-rw-r--r-- | net/tipc/bearer.c | 110 |
1 files changed, 11 insertions, 99 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 4ec5c80e8a7c..aa62f93a9127 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -279,116 +279,31 @@ void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest) | |||
279 | } | 279 | } |
280 | 280 | ||
281 | /* | 281 | /* |
282 | * bearer_push(): Resolve bearer congestion. Force the waiting | 282 | * Interrupt enabling new requests after bearer blocking: |
283 | * links to push out their unsent packets, one packet per link | ||
284 | * per iteration, until all packets are gone or congestion reoccurs. | ||
285 | * 'tipc_net_lock' is read_locked when this function is called | ||
286 | * bearer.lock must be taken before calling | ||
287 | * Returns binary true(1) ore false(0) | ||
288 | */ | ||
289 | static int bearer_push(struct tipc_bearer *b_ptr) | ||
290 | { | ||
291 | u32 res = 0; | ||
292 | struct tipc_link *ln, *tln; | ||
293 | |||
294 | if (b_ptr->blocked) | ||
295 | return 0; | ||
296 | |||
297 | while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) { | ||
298 | list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) { | ||
299 | res = tipc_link_push_packet(ln); | ||
300 | if (res == PUSH_FAILED) | ||
301 | break; | ||
302 | if (res == PUSH_FINISHED) | ||
303 | list_move_tail(&ln->link_list, &b_ptr->links); | ||
304 | } | ||
305 | } | ||
306 | return list_empty(&b_ptr->cong_links); | ||
307 | } | ||
308 | |||
309 | void tipc_bearer_lock_push(struct tipc_bearer *b_ptr) | ||
310 | { | ||
311 | spin_lock_bh(&b_ptr->lock); | ||
312 | bearer_push(b_ptr); | ||
313 | spin_unlock_bh(&b_ptr->lock); | ||
314 | } | ||
315 | |||
316 | |||
317 | /* | ||
318 | * Interrupt enabling new requests after bearer congestion or blocking: | ||
319 | * See bearer_send(). | 283 | * See bearer_send(). |
320 | */ | 284 | */ |
321 | void tipc_continue(struct tipc_bearer *b_ptr) | 285 | void tipc_continue(struct tipc_bearer *b) |
322 | { | 286 | { |
323 | spin_lock_bh(&b_ptr->lock); | 287 | spin_lock_bh(&b->lock); |
324 | if (!list_empty(&b_ptr->cong_links)) | 288 | b->blocked = 0; |
325 | tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr); | 289 | spin_unlock_bh(&b->lock); |
326 | b_ptr->blocked = 0; | ||
327 | spin_unlock_bh(&b_ptr->lock); | ||
328 | } | 290 | } |
329 | 291 | ||
330 | /* | 292 | /* |
331 | * Schedule link for sending of messages after the bearer | 293 | * tipc_bearer_blocked - determines if bearer is currently blocked |
332 | * has been deblocked by 'continue()'. This method is called | ||
333 | * when somebody tries to send a message via this link while | ||
334 | * the bearer is congested. 'tipc_net_lock' is in read_lock here | ||
335 | * bearer.lock is busy | ||
336 | */ | 294 | */ |
337 | static void tipc_bearer_schedule_unlocked(struct tipc_bearer *b_ptr, | 295 | int tipc_bearer_blocked(struct tipc_bearer *b) |
338 | struct tipc_link *l_ptr) | ||
339 | { | 296 | { |
340 | list_move_tail(&l_ptr->link_list, &b_ptr->cong_links); | 297 | int res; |
341 | } | ||
342 | |||
343 | /* | ||
344 | * Schedule link for sending of messages after the bearer | ||
345 | * has been deblocked by 'continue()'. This method is called | ||
346 | * when somebody tries to send a message via this link while | ||
347 | * the bearer is congested. 'tipc_net_lock' is in read_lock here, | ||
348 | * bearer.lock is free | ||
349 | */ | ||
350 | void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr) | ||
351 | { | ||
352 | spin_lock_bh(&b_ptr->lock); | ||
353 | tipc_bearer_schedule_unlocked(b_ptr, l_ptr); | ||
354 | spin_unlock_bh(&b_ptr->lock); | ||
355 | } | ||
356 | |||
357 | 298 | ||
358 | /* | 299 | spin_lock_bh(&b->lock); |
359 | * tipc_bearer_resolve_congestion(): Check if there is bearer congestion, | 300 | res = b->blocked; |
360 | * and if there is, try to resolve it before returning. | 301 | spin_unlock_bh(&b->lock); |
361 | * 'tipc_net_lock' is read_locked when this function is called | ||
362 | */ | ||
363 | int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr, | ||
364 | struct tipc_link *l_ptr) | ||
365 | { | ||
366 | int res = 1; | ||
367 | 302 | ||
368 | if (list_empty(&b_ptr->cong_links)) | ||
369 | return 1; | ||
370 | spin_lock_bh(&b_ptr->lock); | ||
371 | if (!bearer_push(b_ptr)) { | ||
372 | tipc_bearer_schedule_unlocked(b_ptr, l_ptr); | ||
373 | res = 0; | ||
374 | } | ||
375 | spin_unlock_bh(&b_ptr->lock); | ||
376 | return res; | 303 | return res; |
377 | } | 304 | } |
378 | 305 | ||
379 | /** | 306 | /** |
380 | * tipc_bearer_congested - determines if bearer is currently congested | ||
381 | */ | ||
382 | int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr) | ||
383 | { | ||
384 | if (unlikely(b_ptr->blocked)) | ||
385 | return 1; | ||
386 | if (likely(list_empty(&b_ptr->cong_links))) | ||
387 | return 0; | ||
388 | return !tipc_bearer_resolve_congestion(b_ptr, l_ptr); | ||
389 | } | ||
390 | |||
391 | /** | ||
392 | * tipc_enable_bearer - enable bearer with the given name | 307 | * tipc_enable_bearer - enable bearer with the given name |
393 | */ | 308 | */ |
394 | int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) | 309 | int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) |
@@ -489,7 +404,6 @@ restart: | |||
489 | b_ptr->net_plane = bearer_id + 'A'; | 404 | b_ptr->net_plane = bearer_id + 'A'; |
490 | b_ptr->active = 1; | 405 | b_ptr->active = 1; |
491 | b_ptr->priority = priority; | 406 | b_ptr->priority = priority; |
492 | INIT_LIST_HEAD(&b_ptr->cong_links); | ||
493 | INIT_LIST_HEAD(&b_ptr->links); | 407 | INIT_LIST_HEAD(&b_ptr->links); |
494 | spin_lock_init(&b_ptr->lock); | 408 | spin_lock_init(&b_ptr->lock); |
495 | 409 | ||
@@ -528,7 +442,6 @@ int tipc_block_bearer(const char *name) | |||
528 | pr_info("Blocking bearer <%s>\n", name); | 442 | pr_info("Blocking bearer <%s>\n", name); |
529 | spin_lock_bh(&b_ptr->lock); | 443 | spin_lock_bh(&b_ptr->lock); |
530 | b_ptr->blocked = 1; | 444 | b_ptr->blocked = 1; |
531 | list_splice_init(&b_ptr->cong_links, &b_ptr->links); | ||
532 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 445 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { |
533 | struct tipc_node *n_ptr = l_ptr->owner; | 446 | struct tipc_node *n_ptr = l_ptr->owner; |
534 | 447 | ||
@@ -555,7 +468,6 @@ static void bearer_disable(struct tipc_bearer *b_ptr) | |||
555 | spin_lock_bh(&b_ptr->lock); | 468 | spin_lock_bh(&b_ptr->lock); |
556 | b_ptr->blocked = 1; | 469 | b_ptr->blocked = 1; |
557 | b_ptr->media->disable_bearer(b_ptr); | 470 | b_ptr->media->disable_bearer(b_ptr); |
558 | list_splice_init(&b_ptr->cong_links, &b_ptr->links); | ||
559 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 471 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { |
560 | tipc_link_delete(l_ptr); | 472 | tipc_link_delete(l_ptr); |
561 | } | 473 | } |