static void ibs_wq_serial_rx_clock_vote_off(struct work_struct *work)
{
	struct ibs_struct *ibs = container_of(work, struct ibs_struct,
					ws_rx_vote_off);
	struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;

	BT_DBG(" %p ", hu);

	ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_OFF, hu);

}
/*
 * Called upon wake-up-acknowledgement from the device
 */
static void ibs_device_woke_up(struct hci_uart *hu)
{
	unsigned long flags;
	struct ibs_struct *ibs = hu->priv;
	struct sk_buff *skb = NULL;

	BT_DBG("hu %p", hu);

	/* lock hci_ibs state */
	spin_lock_irqsave(&ibs->hci_ibs_lock, flags);

	/* debug */
	ibs->ibs_recv_wacks++;

	//Add check for rx_ibs_state when receive HCI_IBS_WAKE_ACK just after HCI_IBS_SLEEP_IND. 
	if(ibs->rx_ibs_state == HCI_IBS_RX_ASLEEP) {
		ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
		ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;
	}

	switch (ibs->tx_ibs_state) {
	case HCI_IBS_TX_ASLEEP:
		/* This could be spurrious rx wake on the BT chip.
		 * Send it another SLEEP othwise it will stay awake. */
	default:
		BT_ERR("received HCI_IBS_WAKE_ACK in tx state %ld",
			ibs->tx_ibs_state);
		break;
	case HCI_IBS_TX_AWAKE:
		/* expect one if we send 2 WAKEs */
		BT_DBG("received HCI_IBS_WAKE_ACK in tx state %ld",
			ibs->tx_ibs_state);
		break;
	case HCI_IBS_TX_WAKING:
		/* send pending packets */
		while ((skb = skb_dequeue(&ibs->tx_wait_q)))
			skb_queue_tail(&ibs->txq, skb);
		/* switch timers and change state to HCI_IBS_TX_AWAKE */
		del_timer(&ibs->wake_retrans_timer);
		mod_timer(&ibs->tx_idle_timer, jiffies + tx_idle_delay);
		ibs->tx_ibs_state = HCI_IBS_TX_AWAKE;
	}


	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);

	/* actually send the packets */
	hci_uart_tx_wakeup(hu);
}
示例#3
0
static void ibs_wq_serial_tx_clock_vote_off(struct work_struct *work)
{
	struct ibs_struct *ibs = container_of(work, struct ibs_struct,
					ws_tx_vote_off);
	struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;

	BT_DBG(" %p ", hu);

	hci_uart_tx_wakeup(hu);  /* run HCI tx handling unlocked */

	/* now that message queued to tty driver, vote for tty clocks off */
	/* It is up to the tty driver to pend the clocks off until tx done. */
	ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);

}
示例#4
0
/*
 * Called upon a wake-up-indication from the device
 */
static void ibs_device_want_to_wakeup(struct hci_uart *hu)
{
	unsigned long flags;
	struct ibs_struct *ibs = hu->priv;

	BT_DBG("hu %p", hu);

	/* lock hci_ibs state */
	spin_lock_irqsave(&ibs->hci_ibs_lock, flags);

	/* debug */
	ibs->ibs_recv_wakes++;

	switch (ibs->rx_ibs_state) {
	case HCI_IBS_RX_ASLEEP:
		/* Make sure clock is on - we may have turned clock off since
		 * receiving the wake up indicator
		 */
		ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
		ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;
		/* deliberate fall-through */

		

	case HCI_IBS_RX_AWAKE:
		/* Always acknowledge device wake up,
		 * sending IBS message doesn't count as TX ON.
		 */
		if (send_hci_ibs_cmd(HCI_IBS_WAKE_ACK, hu) < 0) {
			BT_ERR("cannot acknowledge device wake up");
			goto out;
		}
		ibs->ibs_sent_wacks++; /* debug */
		break;
	default:
		/* any other state is illegal */
		BT_ERR("received HCI_IBS_WAKE_IND in rx state %ld",
			ibs->rx_ibs_state);
		break;
	}

out:
	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);

	/* actually send the packets */
	hci_uart_tx_wakeup(hu);
}
示例#5
0
static void hci_ibs_tx_idle_timeout(unsigned long arg)
{
	struct hci_uart *hu = (struct hci_uart *) arg;
	struct ibs_struct *ibs = hu->priv;
	unsigned long flags;
	unsigned long vote_tx_sleep = 0;

	BT_DBG("hu %p idle timeout in %lu state", hu, ibs->tx_ibs_state);

	spin_lock_irqsave_nested(&ibs->hci_ibs_lock,
					flags, SINGLE_DEPTH_NESTING);

	switch (ibs->tx_ibs_state) {
	default:
	case HCI_IBS_TX_ASLEEP:
	case HCI_IBS_TX_WAKING:
		BT_ERR("spurrious timeout in tx state %ld", ibs->tx_ibs_state);
		goto out;
	case HCI_IBS_TX_AWAKE: /* TX_IDLE, go to SLEEP */
		if (send_hci_ibs_cmd(HCI_IBS_SLEEP_IND, hu) < 0) {
			BT_ERR("cannot send SLEEP to device");
			goto out;
		}
		ibs->tx_ibs_state = HCI_IBS_TX_ASLEEP;
		ibs->ibs_sent_slps++; /* debug */
		vote_tx_sleep = 1;
		break;
	}

	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);

	hci_uart_tx_wakeup(hu);  /* run HCI tx handling unlocked */

	if (!vote_tx_sleep)
		return;
	/* now that message queued to tty driver, vote for tty clocks off */
	/* It is up to the tty driver to pend the clocks off until tx done. */

	spin_lock_irqsave_nested(&ibs->hci_ibs_lock,
					flags, SINGLE_DEPTH_NESTING);
	ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
out:
	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
}
示例#6
0
/* Close protocol */
static int ibs_close(struct hci_uart *hu)
{
	struct ibs_struct *ibs = hu->priv;

	BT_DBG("hu %p", hu);

	ibs_msm_serial_clock_vote(HCI_IBS_VOTE_STATS_UPDATE, hu);
	ibs_log_local_stats(ibs);

	skb_queue_purge(&ibs->tx_wait_q);
	skb_queue_purge(&ibs->txq);
	del_timer(&ibs->tx_idle_timer);
	del_timer(&ibs->wake_retrans_timer);

	kfree_skb(ibs->rx_skb);

	hu->priv = NULL;

	kfree(ibs);

	return 0;
}
static void ibs_wq_awake_device(struct work_struct *work)
{
	struct ibs_struct *ibs = container_of(work, struct ibs_struct,
					ws_awake_device);
	struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;

	BT_DBG(" %p ", hu);

	/* Vote for serial clock */
	ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);

	spin_lock(&ibs->hci_ibs_lock);

	/* send wake indication to device */
	if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0)
		BT_ERR("cannot send WAKE to device");

	ibs->ibs_sent_wakes++; /* debug */

	/* start retransmit timer */
	mod_timer(&ibs->wake_retrans_timer, jiffies + wake_retrans);

	spin_unlock(&ibs->hci_ibs_lock);
}