/* * functions called from TTY layer */ static int st_tty_open(struct tty_struct *tty) { int err = 0; struct st_data_s *st_gdata; pr_info("%s ", __func__); st_kim_ref(&st_gdata, 0); st_gdata->tty = tty; tty->disc_data = st_gdata; /* don't do an wakeup for now */ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); /* mem already allocated */ tty->receive_room = 65536; /* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); /* * signal to UIM via KIM that - * installation of N_TI_WL ldisc is complete */ st_kim_complete(st_gdata->kim_data); pr_debug("done %s", __func__); return err; }
/* * called in protocol stack drivers * via the write function pointer */ long st_write(struct sk_buff *skb) { struct st_data_s *st_gdata; long len; st_kim_ref(&st_gdata, 0); if (unlikely(skb == NULL || st_gdata == NULL || st_gdata->tty == NULL)) { pr_err("data/tty unavailable to perform write"); return -EINVAL; } pr_debug("%d to be written", skb->len); len = skb->len; /* * Refresh inactivity timeout for Power Management protection mechanism * It will prevent from S3 sleeping for a while as it is very likely * some incoming data will be received soon. */ wake_lock_timeout(&st_gdata->wake_lock, ST_PM_PROTECT_INACTIVITY_TIMEOUT); /* st_ll to decide where to enqueue the skb */ st_int_enqueue(st_gdata, skb); /* wake up */ st_tx_wakeup(st_gdata); /* return number of bytes written */ return len; }
/* to unregister a protocol - * to be called from protocol stack driver */ long st_unregister(struct st_proto_s *proto) { long err = 0; unsigned long flags = 0; struct st_data_s *st_gdata; pr_debug("%s: %d \n", __func__, proto->chnl_id); st_kim_ref(&st_gdata, 0); if (proto->chnl_id >= ST_MAX_CHANNELS) { pr_err(" chnl_id %d not supported\n", proto->chnl_id); return -EPROTONOSUPPORT; } spin_lock_irqsave(&st_gdata->lock, flags); if (st_gdata->is_registered[proto->chnl_id] == false) { pr_err(" chnl_id %d not registered\n", proto->chnl_id); spin_unlock_irqrestore(&st_gdata->lock, flags); return -EPROTONOSUPPORT; } st_gdata->protos_registered--; 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 \n"); /* stop traffic on tty */ if (st_gdata->tty) { tty_ldisc_flush(st_gdata->tty); stop_tty(st_gdata->tty); } /* all chnl_ids now unregistered */ st_kim_stop(st_gdata->kim_data); /* disable ST LL */ st_ll_disable(st_gdata); } return err; }
/* * called in protocol stack drivers * via the write function pointer */ long st_write(struct sk_buff *skb) { struct st_data_s *st_gdata; long len; st_kim_ref(&st_gdata, 0); if (unlikely(skb == NULL || st_gdata == NULL || st_gdata->tty == NULL)) { pr_err("data/tty unavailable to perform write"); return -EINVAL; } pr_debug("%d to be written", skb->len); len = skb->len; /* st_ll to decide where to enqueue the skb */ st_int_enqueue(st_gdata, skb); /* wake up */ st_tx_wakeup(st_gdata); /* return number of bytes written */ return len; }
/* * functions called from TTY layer */ static int st_tty_open(struct tty_struct *tty) { int err = 0; struct st_data_s *st_gdata; pr_info("%s ", __func__); st_kim_ref(&st_gdata, 0); st_gdata->tty = tty; tty->disc_data = st_gdata; if (tty->dev->parent) st_gdata->tty_dev = tty->dev->parent; else return -EINVAL; /* Asynchronous Get is enough here since we just want to avoid * interface to be released too early */ pm_runtime_get(st_gdata->tty_dev); /* don't do an wakeup for now */ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); /* mem already allocated */ tty->receive_room = 65536; /* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); /* * signal to UIM via KIM that - * installation of N_TI_WL ldisc is complete */ st_kim_complete(st_gdata->kim_data); pr_debug("done %s", __func__); return err; }
/* * functions called from protocol stack drivers * to be EXPORT-ed */ long st_register(struct st_proto_s *new_proto) { struct st_data_s *st_gdata; long err = 0; unsigned long flags = 0; st_kim_ref(&st_gdata, 0); if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL || new_proto->reg_complete_cb == NULL) { pr_err("gdata/new_proto/recv or reg_complete_cb not ready"); return -EINVAL; } if (new_proto->chnl_id >= ST_MAX_CHANNELS) { pr_err("chnl_id %d not supported", new_proto->chnl_id); return -EPROTONOSUPPORT; } if (st_gdata->is_registered[new_proto->chnl_id] == true) { pr_err("chnl_id %d already registered", new_proto->chnl_id); return -EALREADY; } /* can be from process context only */ spin_lock_irqsave(&st_gdata->lock, flags); if (test_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state)) { pr_info(" ST_REG_IN_PROGRESS:%d ", new_proto->chnl_id); /* fw download in progress */ add_channel_to_table(st_gdata, new_proto); st_gdata->protos_registered++; new_proto->write = st_write; set_bit(ST_REG_PENDING, &st_gdata->st_state); spin_unlock_irqrestore(&st_gdata->lock, flags); return -EINPROGRESS; } else if (st_gdata->protos_registered == ST_EMPTY) { pr_info(" chnl_id list empty :%d ", new_proto->chnl_id); 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); /* this may take a while to complete * since it involves BT fw download */ err = st_kim_start(st_gdata->kim_data); if (err != 0) { clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state); if ((st_gdata->protos_registered != ST_EMPTY) && (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; /* this is where all pending registration * are signalled to be complete by calling callback functions */ if ((st_gdata->protos_registered != ST_EMPTY) && (test_bit(ST_REG_PENDING, &st_gdata->st_state))) { pr_debug(" call reg complete callback "); st_reg_complete(st_gdata, 0); } clear_bit(ST_REG_PENDING, &st_gdata->st_state); /* check for already registered once more, * since the above check is old */ 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; } add_channel_to_table(st_gdata, new_proto); st_gdata->protos_registered++; new_proto->write = st_write; spin_unlock_irqrestore(&st_gdata->lock, flags); return err; } /* if fw is already downloaded & new stack registers protocol */ else { add_channel_to_table(st_gdata, new_proto); st_gdata->protos_registered++; new_proto->write = st_write; /* lock already held before entering else */ spin_unlock_irqrestore(&st_gdata->lock, flags); return err; } pr_debug("done %s(%d) ", __func__, new_proto->chnl_id); }