diff options
Diffstat (limited to 'drivers/net/team/team.c')
-rw-r--r-- | drivers/net/team/team.c | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index c61ae35a53ce..bdf87a971382 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c | |||
@@ -371,13 +371,18 @@ static int team_option_set(struct team *team, | |||
371 | static LIST_HEAD(mode_list); | 371 | static LIST_HEAD(mode_list); |
372 | static DEFINE_SPINLOCK(mode_list_lock); | 372 | static DEFINE_SPINLOCK(mode_list_lock); |
373 | 373 | ||
374 | static struct team_mode *__find_mode(const char *kind) | 374 | struct team_mode_item { |
375 | struct list_head list; | ||
376 | const struct team_mode *mode; | ||
377 | }; | ||
378 | |||
379 | static struct team_mode_item *__find_mode(const char *kind) | ||
375 | { | 380 | { |
376 | struct team_mode *mode; | 381 | struct team_mode_item *mitem; |
377 | 382 | ||
378 | list_for_each_entry(mode, &mode_list, list) { | 383 | list_for_each_entry(mitem, &mode_list, list) { |
379 | if (strcmp(mode->kind, kind) == 0) | 384 | if (strcmp(mitem->mode->kind, kind) == 0) |
380 | return mode; | 385 | return mitem; |
381 | } | 386 | } |
382 | return NULL; | 387 | return NULL; |
383 | } | 388 | } |
@@ -392,49 +397,65 @@ static bool is_good_mode_name(const char *name) | |||
392 | return true; | 397 | return true; |
393 | } | 398 | } |
394 | 399 | ||
395 | int team_mode_register(struct team_mode *mode) | 400 | int team_mode_register(const struct team_mode *mode) |
396 | { | 401 | { |
397 | int err = 0; | 402 | int err = 0; |
403 | struct team_mode_item *mitem; | ||
398 | 404 | ||
399 | if (!is_good_mode_name(mode->kind) || | 405 | if (!is_good_mode_name(mode->kind) || |
400 | mode->priv_size > TEAM_MODE_PRIV_SIZE) | 406 | mode->priv_size > TEAM_MODE_PRIV_SIZE) |
401 | return -EINVAL; | 407 | return -EINVAL; |
408 | |||
409 | mitem = kmalloc(sizeof(*mitem), GFP_KERNEL); | ||
410 | if (!mitem) | ||
411 | return -ENOMEM; | ||
412 | |||
402 | spin_lock(&mode_list_lock); | 413 | spin_lock(&mode_list_lock); |
403 | if (__find_mode(mode->kind)) { | 414 | if (__find_mode(mode->kind)) { |
404 | err = -EEXIST; | 415 | err = -EEXIST; |
416 | kfree(mitem); | ||
405 | goto unlock; | 417 | goto unlock; |
406 | } | 418 | } |
407 | list_add_tail(&mode->list, &mode_list); | 419 | mitem->mode = mode; |
420 | list_add_tail(&mitem->list, &mode_list); | ||
408 | unlock: | 421 | unlock: |
409 | spin_unlock(&mode_list_lock); | 422 | spin_unlock(&mode_list_lock); |
410 | return err; | 423 | return err; |
411 | } | 424 | } |
412 | EXPORT_SYMBOL(team_mode_register); | 425 | EXPORT_SYMBOL(team_mode_register); |
413 | 426 | ||
414 | int team_mode_unregister(struct team_mode *mode) | 427 | void team_mode_unregister(const struct team_mode *mode) |
415 | { | 428 | { |
429 | struct team_mode_item *mitem; | ||
430 | |||
416 | spin_lock(&mode_list_lock); | 431 | spin_lock(&mode_list_lock); |
417 | list_del_init(&mode->list); | 432 | mitem = __find_mode(mode->kind); |
433 | if (mitem) { | ||
434 | list_del_init(&mitem->list); | ||
435 | kfree(mitem); | ||
436 | } | ||
418 | spin_unlock(&mode_list_lock); | 437 | spin_unlock(&mode_list_lock); |
419 | return 0; | ||
420 | } | 438 | } |
421 | EXPORT_SYMBOL(team_mode_unregister); | 439 | EXPORT_SYMBOL(team_mode_unregister); |
422 | 440 | ||
423 | static struct team_mode *team_mode_get(const char *kind) | 441 | static const struct team_mode *team_mode_get(const char *kind) |
424 | { | 442 | { |
425 | struct team_mode *mode; | 443 | struct team_mode_item *mitem; |
444 | const struct team_mode *mode = NULL; | ||
426 | 445 | ||
427 | spin_lock(&mode_list_lock); | 446 | spin_lock(&mode_list_lock); |
428 | mode = __find_mode(kind); | 447 | mitem = __find_mode(kind); |
429 | if (!mode) { | 448 | if (!mitem) { |
430 | spin_unlock(&mode_list_lock); | 449 | spin_unlock(&mode_list_lock); |
431 | request_module("team-mode-%s", kind); | 450 | request_module("team-mode-%s", kind); |
432 | spin_lock(&mode_list_lock); | 451 | spin_lock(&mode_list_lock); |
433 | mode = __find_mode(kind); | 452 | mitem = __find_mode(kind); |
434 | } | 453 | } |
435 | if (mode) | 454 | if (mitem) { |
455 | mode = mitem->mode; | ||
436 | if (!try_module_get(mode->owner)) | 456 | if (!try_module_get(mode->owner)) |
437 | mode = NULL; | 457 | mode = NULL; |
458 | } | ||
438 | 459 | ||
439 | spin_unlock(&mode_list_lock); | 460 | spin_unlock(&mode_list_lock); |
440 | return mode; | 461 | return mode; |
@@ -523,7 +544,7 @@ static int __team_change_mode(struct team *team, | |||
523 | 544 | ||
524 | static int team_change_mode(struct team *team, const char *kind) | 545 | static int team_change_mode(struct team *team, const char *kind) |
525 | { | 546 | { |
526 | struct team_mode *new_mode; | 547 | const struct team_mode *new_mode; |
527 | struct net_device *dev = team->dev; | 548 | struct net_device *dev = team->dev; |
528 | int err; | 549 | int err; |
529 | 550 | ||