diff options
Diffstat (limited to 'net/rfkill')
-rw-r--r-- | net/rfkill/rfkill.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index 35a9994e2339..1f23de20a85e 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c | |||
@@ -525,17 +525,44 @@ static struct class rfkill_class = { | |||
525 | .dev_uevent = rfkill_dev_uevent, | 525 | .dev_uevent = rfkill_dev_uevent, |
526 | }; | 526 | }; |
527 | 527 | ||
528 | static int rfkill_check_duplicity(const struct rfkill *rfkill) | ||
529 | { | ||
530 | struct rfkill *p; | ||
531 | unsigned long seen[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; | ||
532 | |||
533 | memset(seen, 0, sizeof(seen)); | ||
534 | |||
535 | list_for_each_entry(p, &rfkill_list, node) { | ||
536 | if (p == rfkill) { | ||
537 | WARN_ON(1); | ||
538 | return -EEXIST; | ||
539 | } | ||
540 | set_bit(p->type, seen); | ||
541 | } | ||
542 | |||
543 | /* 0: first switch of its kind */ | ||
544 | return test_bit(rfkill->type, seen); | ||
545 | } | ||
546 | |||
528 | static int rfkill_add_switch(struct rfkill *rfkill) | 547 | static int rfkill_add_switch(struct rfkill *rfkill) |
529 | { | 548 | { |
549 | int error; | ||
550 | |||
530 | mutex_lock(&rfkill_mutex); | 551 | mutex_lock(&rfkill_mutex); |
531 | 552 | ||
553 | error = rfkill_check_duplicity(rfkill); | ||
554 | if (error < 0) | ||
555 | goto unlock_out; | ||
556 | |||
532 | rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0); | 557 | rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0); |
533 | 558 | ||
534 | list_add_tail(&rfkill->node, &rfkill_list); | 559 | list_add_tail(&rfkill->node, &rfkill_list); |
535 | 560 | ||
561 | error = 0; | ||
562 | unlock_out: | ||
536 | mutex_unlock(&rfkill_mutex); | 563 | mutex_unlock(&rfkill_mutex); |
537 | 564 | ||
538 | return 0; | 565 | return error; |
539 | } | 566 | } |
540 | 567 | ||
541 | static void rfkill_remove_switch(struct rfkill *rfkill) | 568 | static void rfkill_remove_switch(struct rfkill *rfkill) |