diff options
author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2008-08-02 15:10:57 -0300 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-08-22 16:29:56 -0400 |
commit | 02589f60510030a3c1496e7a8c511e4f674ef5ff (patch) | |
tree | 24650fdd0e2a0ad8145693164fa27e847379aacc /net | |
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')
-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 35a9994e233..1f23de20a85 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -525,17 +525,44 @@ static struct class rfkill_class = { .dev_uevent = rfkill_dev_uevent, }; +static int rfkill_check_duplicity(const struct rfkill *rfkill) +{ + struct rfkill *p; + unsigned long seen[BITS_TO_LONGS(RFKILL_TYPE_MAX)]; + + memset(seen, 0, sizeof(seen)); + + list_for_each_entry(p, &rfkill_list, node) { + if (p == rfkill) { + WARN_ON(1); + return -EEXIST; + } + set_bit(p->type, seen); + } + + /* 0: first switch of its kind */ + return test_bit(rfkill->type, seen); +} + static int rfkill_add_switch(struct rfkill *rfkill) { + int error; + mutex_lock(&rfkill_mutex); + error = rfkill_check_duplicity(rfkill); + if (error < 0) + goto unlock_out; + rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0); list_add_tail(&rfkill->node, &rfkill_list); + error = 0; +unlock_out: mutex_unlock(&rfkill_mutex); - return 0; + return error; } static void rfkill_remove_switch(struct rfkill *rfkill) |