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