summaryrefslogtreecommitdiffstats
path: root/drivers/misc/ti-st/st_core.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-09 21:08:59 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-09 21:08:59 +0100
commit21a2cb565a74bf794d343ce22300c5f6c1568ae1 (patch)
tree5cf49d94bc8cc31a299417b8a362f0645b41c543 /drivers/misc/ti-st/st_core.c
parentMerge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vir... (diff)
parentisl29020: Remove a redundant semi-colon from return statement (diff)
downloadlinux-21a2cb565a74bf794d343ce22300c5f6c1568ae1.tar.xz
linux-21a2cb565a74bf794d343ce22300c5f6c1568ae1.zip
Merge branch 'char-misc-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
* 'char-misc-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: isl29020: Remove a redundant semi-colon from return statement BMP085: Remove redundant semi-colon from return statement drivers:misc: ti-st: DEBUG uart, baud rate mods drivers:misc: ti-st: flush UART upon fw failure drivers:misc: ti-st: protect registrations char_dev.c: fix up some whitespace errors s390: tape_class.h: remove kobj_map.h inclusion misc: ad525x_dpot: Add support for SPI module device table matching
Diffstat (limited to 'drivers/misc/ti-st/st_core.c')
-rw-r--r--drivers/misc/ti-st/st_core.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index ba168a7d54d4..2b62232c2c6a 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -137,6 +137,8 @@ void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
* st_reg_complete -
* to call registration complete callbacks
* of all protocol stack drivers
+ * This function is being called with spin lock held, protocol drivers are
+ * only expected to complete their waits and do nothing more than that.
*/
void st_reg_complete(struct st_data_s *st_gdata, char err)
{
@@ -538,11 +540,12 @@ long st_register(struct st_proto_s *new_proto)
set_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
st_recv = st_kim_recv;
+ /* enable the ST LL - to set default chip state */
+ st_ll_enable(st_gdata);
+
/* release lock previously held - re-locked below */
spin_unlock_irqrestore(&st_gdata->lock, flags);
- /* enable the ST LL - to set default chip state */
- st_ll_enable(st_gdata);
/* this may take a while to complete
* since it involves BT fw download
*/
@@ -553,10 +556,13 @@ long st_register(struct st_proto_s *new_proto)
(test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
pr_err(" KIM failure complete callback ");
st_reg_complete(st_gdata, err);
+ clear_bit(ST_REG_PENDING, &st_gdata->st_state);
}
return -EINVAL;
}
+ spin_lock_irqsave(&st_gdata->lock, flags);
+
clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
st_recv = st_int_recv;
@@ -576,10 +582,10 @@ long st_register(struct st_proto_s *new_proto)
if (st_gdata->is_registered[new_proto->chnl_id] == true) {
pr_err(" proto %d already registered ",
new_proto->chnl_id);
+ spin_unlock_irqrestore(&st_gdata->lock, flags);
return -EALREADY;
}
- spin_lock_irqsave(&st_gdata->lock, flags);
add_channel_to_table(st_gdata, new_proto);
st_gdata->protos_registered++;
new_proto->write = st_write;
@@ -619,7 +625,7 @@ long st_unregister(struct st_proto_s *proto)
spin_lock_irqsave(&st_gdata->lock, flags);
- if (st_gdata->list[proto->chnl_id] == NULL) {
+ if (st_gdata->is_registered[proto->chnl_id] == false) {
pr_err(" chnl_id %d not registered", proto->chnl_id);
spin_unlock_irqrestore(&st_gdata->lock, flags);
return -EPROTONOSUPPORT;
@@ -629,6 +635,10 @@ long st_unregister(struct st_proto_s *proto)
remove_channel_from_table(st_gdata, proto);
spin_unlock_irqrestore(&st_gdata->lock, flags);
+ /* paranoid check */
+ if (st_gdata->protos_registered < ST_EMPTY)
+ st_gdata->protos_registered = ST_EMPTY;
+
if ((st_gdata->protos_registered == ST_EMPTY) &&
(!test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
pr_info(" all chnl_ids unregistered ");