diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 21:08:59 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-09 21:08:59 +0100 |
commit | 21a2cb565a74bf794d343ce22300c5f6c1568ae1 (patch) | |
tree | 5cf49d94bc8cc31a299417b8a362f0645b41c543 /drivers/misc/ti-st/st_core.c | |
parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vir... (diff) | |
parent | isl29020: Remove a redundant semi-colon from return statement (diff) | |
download | linux-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.c | 18 |
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 "); |