* 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)
 {
                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
                 */
                            (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;
 
                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;
 
        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;
        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 ");