diff options
| author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2008-08-02 14:10:57 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2008-08-22 16:29:56 -0400 |
| commit | 02589f60510030a3c1496e7a8c511e4f674ef5ff (patch) | |
| tree | 24650fdd0e2a0ad8145693164fa27e847379aacc /net/rfkill | |
| parent | c94c93da90a9e46a73a5733ff8454fb4b14733fb (diff) | |
rfkill: detect bogus double-registering (v2)
Detect and abort with -EEXIST if rfkill_register is called twice on the
same rfkill struct. And WARN_ON(it) for good measure.
While at it, flag when we are adding the first switch of a type, we will
need that information later.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
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) |
