/* QualComm baseLine update 1030 to 1040 begin */
static void ibs_wq(struct work_struct *work)
{
	unsigned long flags = 0;
	struct ibs_struct *ibs = container_of(work, struct ibs_struct,
						ws_ibs);
	struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;

	BT_DBG("hu %p, ibs_wq state: %lu\n", hu, ibs->ibs_wq_state);

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

	switch (ibs->ibs_wq_state) {
	case HCI_IBS_WQ_AWAKE_DEVICE:
		/* Vote for serial clock */
		ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);

		/* 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);
		break;
	case HCI_IBS_WQ_AWAKE_RX:
		ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
		ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;

		if (send_hci_ibs_cmd(HCI_IBS_WAKE_ACK, hu) < 0)
			BT_ERR("cannot acknowledge device wake up");

		ibs->ibs_sent_wacks++; /* debug */
		/* actually send the packets */
		hci_uart_tx_wakeup(hu);
		break;
	case HCI_IBS_WQ_RX_VOTE_OFF:
		ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_OFF, hu);
		break;
	case HCI_IBS_WQ_TX_VOTE_OFF:
		ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
		break;
	default:
		BT_DBG("Invalid state in ibs workqueue");
		break;
	}
	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
}
Beispiel #2
0
static void hci_ibs_wake_retrans_timeout(unsigned long arg)
{
	struct hci_uart *hu = (struct hci_uart *) arg;
	struct ibs_struct *ibs = hu->priv;
	unsigned long flags;
	unsigned long retransmit = 0;

	BT_DBG("hu %p wake retransmit 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_AWAKE:
		BT_ERR("spurrious timeout tx state %ld", ibs->tx_ibs_state);
		goto out;
	case HCI_IBS_TX_WAKING: /* No WAKE_ACK, retransmit WAKE */
		retransmit = 1;
		if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0) {
			BT_ERR("cannot acknowledge device wake up");
			goto out;
		}
		ibs->ibs_sent_wakes++; /* debug */
		mod_timer(&ibs->wake_retrans_timer, jiffies + wake_retrans);
		break;
	}
out:
	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
	if (retransmit)
		hci_uart_tx_wakeup(hu);
}
Beispiel #3
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;

	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 */
		break;
	}

	queue_work(ibs->workqueue, &ibs->ws_tx_vote_off);

out:
	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
}
Beispiel #4
0
static void ibs_wq_awake_rx(struct work_struct *work)
{
	struct ibs_struct *ibs = container_of(work, struct ibs_struct,
					ws_awake_rx);
	struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
	unsigned long flags;

	BT_DBG(" %p ", hu);

	ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);

	spin_lock_irqsave(&ibs->hci_ibs_lock, flags);

	ibs->rx_ibs_state = 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");

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

	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);

	/* actually send the packets */
	hci_uart_tx_wakeup(hu);

}
Beispiel #5
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;
	unsigned long flags;

	BT_DBG(" %p ", hu);

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

	spin_lock_irqsave(&ibs->hci_ibs_lock, flags);

	/* 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_irqrestore(&ibs->hci_ibs_lock, flags);

}
Beispiel #6
0
static void hci_ibs_tx_idle_timeout(unsigned long arg)
{
	struct hci_uart *hu = (struct hci_uart *)arg;
	struct qca_data *qca = hu->priv;
	unsigned long flags;

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

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

	switch (qca->tx_ibs_state) {
	case HCI_IBS_TX_AWAKE:
		/* TX_IDLE, go to SLEEP */
		if (send_hci_ibs_cmd(HCI_IBS_SLEEP_IND, hu) < 0) {
			BT_ERR("Failed to send SLEEP to device");
			break;
		}
		qca->tx_ibs_state = HCI_IBS_TX_ASLEEP;
		qca->ibs_sent_slps++;
		queue_work(qca->workqueue, &qca->ws_tx_vote_off);
		break;

	case HCI_IBS_TX_ASLEEP:
	case HCI_IBS_TX_WAKING:
		/* Fall through */

	default:
		BT_ERR("Spurrious timeout tx state %d", qca->tx_ibs_state);
		break;
	}

	spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
}
Beispiel #7
0
static void qca_wq_awake_rx(struct work_struct *work)
{
	struct qca_data *qca = container_of(work, struct qca_data,
					    ws_awake_rx);
	struct hci_uart *hu = qca->hu;

	BT_DBG("hu %p wq awake rx", hu);

	serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);

	spin_lock(&qca->hci_ibs_lock);
	qca->rx_ibs_state = 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("Failed to acknowledge device wake up");

	qca->ibs_sent_wacks++;

	spin_unlock(&qca->hci_ibs_lock);

	/* Actually send the packets */
	hci_uart_tx_wakeup(hu);
}
Beispiel #8
0
static void qca_wq_awake_device(struct work_struct *work)
{
	struct qca_data *qca = container_of(work, struct qca_data,
					    ws_awake_device);
	struct hci_uart *hu = qca->hu;
	unsigned long retrans_delay;

	BT_DBG("hu %p wq awake device", hu);

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

	spin_lock(&qca->hci_ibs_lock);

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

	qca->ibs_sent_wakes++;

	/* Start retransmit timer */
	retrans_delay = msecs_to_jiffies(qca->wake_retrans);
	mod_timer(&qca->wake_retrans_timer, jiffies + retrans_delay);

	spin_unlock(&qca->hci_ibs_lock);

	/* Actually send the packets */
	hci_uart_tx_wakeup(hu);
}
Beispiel #9
0
/* may be called from two simultaneous tasklets */
static int ibs_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
	unsigned long flags = 0;
	struct ibs_struct *ibs = hu->priv;

	BT_DBG("hu %p skb %p", hu, skb);

	/* Prepend skb with frame type */
	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);

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

	/* act according to current state */
	switch (ibs->tx_ibs_state) {
	case HCI_IBS_TX_AWAKE:
		BT_DBG("device awake, sending normally");
		skb_queue_tail(&ibs->txq, skb);
		mod_timer(&ibs->tx_idle_timer, jiffies + tx_idle_delay);
		break;

	case HCI_IBS_TX_ASLEEP:
		BT_DBG("device asleep, waking up and queueing packet");
		ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
		/* save packet for later */
		skb_queue_tail(&ibs->tx_wait_q, skb);
		/* awake device */
		if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0) {
			BT_ERR("cannot send WAKE to device");
			break;
		}
		ibs->ibs_sent_wakes++; /* debug */

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

		ibs->tx_ibs_state = HCI_IBS_TX_WAKING;
		break;

	case HCI_IBS_TX_WAKING:
		BT_DBG("device waking up, queueing packet");
		/* transient state; just keep packet for later */
		skb_queue_tail(&ibs->tx_wait_q, skb);
		break;

	default:
		BT_ERR("illegal tx state: %ld (losing packet)",
			ibs->tx_ibs_state);
		kfree_skb(skb);
		break;
	}

	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);

	return 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
		 */
		/* QualComm baseLine update 1030 to 1040 begin */
		/* awake rx clock */
		ibs->ibs_wq_state = HCI_IBS_WQ_AWAKE_RX;
		queue_work(ibs->workqueue, &ibs->ws_ibs);
		spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
		return;
		/* QualComm baseLine update 1030 to 1040 end */
	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);
}
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);
	/* QualComm baseLine update 1030 to 1040 begin */
	/* vote off tx clock */
	ibs->ibs_wq_state = HCI_IBS_WQ_TX_VOTE_OFF;
	queue_work(ibs->workqueue, &ibs->ws_ibs);
	/* QualComm baseLine update 1030 to 1040 end */
out:
	spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
}
Beispiel #12
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);
}
Beispiel #13
0
/* Called upon a wake-up-indication from the device.
 */
static void device_want_to_wakeup(struct hci_uart *hu)
{
	unsigned long flags;
	struct qca_data *qca = hu->priv;

	BT_DBG("hu %p want to wake up", hu);

	spin_lock_irqsave(&qca->hci_ibs_lock, flags);

	qca->ibs_recv_wakes++;

	switch (qca->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 awake rx clock.
		 */
		queue_work(qca->workqueue, &qca->ws_awake_rx);
		spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
		return;

	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("Failed to acknowledge device wake up");
			break;
		}
		qca->ibs_sent_wacks++;
		break;

	default:
		/* Any other state is illegal */
		BT_ERR("Received HCI_IBS_WAKE_IND in rx state %d",
		       qca->rx_ibs_state);
		break;
	}

	spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);

	/* Actually send the packets */
	hci_uart_tx_wakeup(hu);
}
Beispiel #14
0
static void hci_ibs_wake_retrans_timeout(unsigned long arg)
{
	struct hci_uart *hu = (struct hci_uart *)arg;
	struct qca_data *qca = hu->priv;
	unsigned long flags, retrans_delay;
	bool retransmit = false;

	BT_DBG("hu %p wake retransmit timeout in %d state",
		hu, qca->tx_ibs_state);

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

	switch (qca->tx_ibs_state) {
	case HCI_IBS_TX_WAKING:
		/* No WAKE_ACK, retransmit WAKE */
		retransmit = true;
		if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0) {
			BT_ERR("Failed to acknowledge device wake up");
			break;
		}
		qca->ibs_sent_wakes++;
		retrans_delay = msecs_to_jiffies(qca->wake_retrans);
		mod_timer(&qca->wake_retrans_timer, jiffies + retrans_delay);
		break;

	case HCI_IBS_TX_ASLEEP:
	case HCI_IBS_TX_AWAKE:
		/* Fall through */

	default:
		BT_ERR("Spurrious timeout tx state %d", qca->tx_ibs_state);
		break;
	}

	spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);

	if (retransmit)
		hci_uart_tx_wakeup(hu);
}