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); }
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 int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) { struct hci_uart *hu = hci_get_drvdata(hdev); struct qca_data *qca = hu->priv; struct sk_buff *skb; u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 }; if (baudrate > QCA_BAUDRATE_3000000) return -EINVAL; cmd[4] = baudrate; skb = bt_skb_alloc(sizeof(cmd), GFP_ATOMIC); if (!skb) { BT_ERR("Failed to allocate memory for baudrate packet"); return -ENOMEM; } /* Assign commands to change baudrate and packet type. */ memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd)); bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; skb_queue_tail(&qca->txq, skb); hci_uart_tx_wakeup(hu); /* wait 300ms to change new baudrate on controller side * controller will come back after they receive this HCI command * then host can communicate with new baudrate to controller */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(msecs_to_jiffies(BAUDRATE_SETTLE_TIMEOUT_MS)); set_current_state(TASK_INTERRUPTIBLE); return 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); }
static void ll_device_want_to_sleep(struct hci_uart *hu) { unsigned long flags; struct ll_struct *ll = hu->priv; BT_DBG("hu %p", hu); spin_lock_irqsave(&ll->hcill_lock, flags); if (ll->hcill_state != HCILL_AWAKE) BT_ERR("ERR: HCILL_GO_TO_SLEEP_IND in state %ld", ll->hcill_state); if (send_hcill_cmd(HCILL_GO_TO_SLEEP_ACK, hu) < 0) { BT_ERR("cannot acknowledge device sleep"); goto out; } ll->hcill_state = HCILL_ASLEEP; out: spin_unlock_irqrestore(&ll->hcill_lock, flags); hci_uart_tx_wakeup(hu); spin_lock_irqsave(&ll->hcill_lock, flags); if (ll->hcill_state == HCILL_ASLEEP) __ll_msm_serial_clock_request_off(hu->tty); spin_unlock_irqrestore(&ll->hcill_lock, flags); }
/* * Called upon a sleep-indication from the device */ static void ll_device_want_to_sleep(struct hci_uart *hu) { unsigned long flags; struct ll_struct *ll = hu->priv; BT_DBG("hu %p", hu); /* lock hcill state */ spin_lock_irqsave(&ll->hcill_lock, flags); /* sanity check */ if (ll->hcill_state != HCILL_AWAKE) BT_ERR("ERR: HCILL_GO_TO_SLEEP_IND in state %ld", ll->hcill_state); /* acknowledge device sleep */ if (send_hcill_cmd(HCILL_GO_TO_SLEEP_ACK, hu) < 0) { BT_ERR("cannot acknowledge device sleep"); goto out; } /* update state */ ll->hcill_state = HCILL_ASLEEP; out: spin_unlock_irqrestore(&ll->hcill_lock, flags); /* actually send the sleep ack packet */ hci_uart_tx_wakeup(hu); }
/* * Cabrcmed upon a sleep-indication from the device */ static void brcm_device_want_to_sleep(struct hci_uart *hu) { unsigned long flags; struct brcm_struct *brcm = hu->priv; BT_DBG("hu %p", hu); /* lock hcibrcm state */ spin_lock_irqsave(&brcm->hcibrcm_lock, flags); /* sanity check */ if (brcm->hcibrcm_state != HCIBRCM_AWAKE) BT_ERR("ERR: HCIBRCM_GO_TO_SLEEP_IND in state %ld", brcm->hcibrcm_state); /* acknowledge device sleep */ if (send_hcibrcm_cmd(HCIBRCM_GO_TO_SLEEP_ACK, hu) < 0) { BT_ERR("cannot acknowledge device sleep"); goto out; } /* update state */ brcm->hcibrcm_state = HCIBRCM_ASLEEP; out: spin_unlock_irqrestore(&brcm->hcibrcm_lock, flags); /* actuabrcmy send the sleep ack packet */ hci_uart_tx_wakeup(hu); spin_lock_irqsave(&brcm->hcibrcm_lock, flags); if (brcm->hcibrcm_state == HCIBRCM_ASLEEP) __brcm_msm_serial_clock_request_off(hu->tty); spin_unlock_irqrestore(&brcm->hcibrcm_lock, flags); }
/* Send frames from HCI layer */ static int hci_uart_send_frame(struct sk_buff *skb) { struct hci_dev* hdev = (struct hci_dev *) skb->dev; struct tty_struct *tty; struct hci_uart *hu; if (!hdev) { BT_ERR("Frame for uknown device (hdev=NULL)"); return -ENODEV; } if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; hu = (struct hci_uart *) hdev->driver_data; tty = hu->tty; BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); hu->proto->enqueue(hu, skb); hci_uart_tx_wakeup(hu); return 0; }
int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) #endif { #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) struct hci_dev *hdev = (struct hci_dev *)skb->dev; #endif struct hci_uart *hu; if (!hdev) { BT_ERR("Frame for unknown device (hdev=NULL)"); return -ENODEV; } if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; hu = GET_DRV_DATA(hdev); //(struct hci_uart *) hdev->driver_data; BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); #ifdef BTCOEX if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) rtk_btcoex_parse_cmd(skb->data, skb->len); if (bt_cb(skb)->pkt_type == HCI_ACLDATA_PKT) rtk_btcoex_parse_l2cap_data_tx(skb->data, skb->len); #endif hu->proto->enqueue(hu, skb); hci_uart_tx_wakeup(hu); return 0; }
/* Send frames from HCI layer */ static int hci_uart_send_frame(struct sk_buff *skb) { struct hci_dev* hdev = (struct hci_dev *) skb->dev; cyg_io_handle_t serial; struct hci_uart *hu; if (!hdev) { //BT_ERR printf("Frame for uknown device (hdev=NULL)\n"); return -ENODEV; } if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; hu = (struct hci_uart *) hdev->driver_data; serial = hu->tty; //BT_DBG printf("%s: type %d len %d\n", hdev->name, skb->pkt_type, skb->len); hu->proto->enqueue(hu, skb); hci_uart_tx_wakeup(hu); return 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); }
/* Send frames from HCI layer */ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_uart *hu = hci_get_drvdata(hdev); BT_DBG("%s: type %d len %d", hdev->name, hci_skb_pkt_type(skb), skb->len); hu->proto->enqueue(hu, skb); hci_uart_tx_wakeup(hu); return 0; }
/* * Cabrcmed upon a wake-up-indication from the device */ static void brcm_device_want_to_wakeup(struct hci_uart *hu) { unsigned long flags; struct brcm_struct *brcm = hu->priv; BT_DBG("hu %p", hu); /* lock hcibrcm state */ spin_lock_irqsave(&brcm->hcibrcm_lock, flags); switch (brcm->hcibrcm_state) { case HCIBRCM_ASLEEP_TO_AWAKE: /* * This state means that both the host and the BRF chip * have simultaneously sent a wake-up-indication packet. * Traditionaly, in this case, receiving a wake-up-indication * was enough and an additional wake-up-ack wasn't needed. * This has changed with the BRF6350, which does require an * explicit wake-up-ack. Other BRF versions, which do not * require an explicit ack here, do accept it, thus it is * perfectly safe to always send one. */ BT_DBG("dual wake-up-indication"); /* deliberate fabrcm-through - do not add break */ case HCIBRCM_ASLEEP: /* Make sure clock is on - we may have turned clock off since * receiving the wake up indicator */ __brcm_bcm_serial_clock_on(hu); /* acknowledge device wake up */ if (send_hcibrcm_cmd(HCIBRCM_WAKE_UP_ACK, hu) < 0) { BT_ERR("cannot acknowledge device wake up"); goto out; } break; default: /* any other state is ibrcmegal */ BT_ERR("received HCIBRCM_WAKE_UP_IND in state %ld", brcm->hcibrcm_state); break; } /* send pending packets and change state to HCIBRCM_AWAKE */ __brcm_do_awake(brcm); out: spin_unlock_irqrestore(&brcm->hcibrcm_lock, flags); /* actuabrcmy send the packets */ hci_uart_tx_wakeup(hu); }
/** hci_uart_write_wakeup - transmit buffer wakeup * @serdev: serial device * * This function is called by the serdev framework when it accepts * more data being sent. */ static void hci_uart_write_wakeup(struct serdev_device *serdev) { struct hci_uart *hu = serdev_device_get_drvdata(serdev); BT_DBG(""); if (!hu || serdev != hu->serdev) { WARN_ON(1); return; } if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) hci_uart_tx_wakeup(hu); }
/* 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); }
/* * 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); }
/* Send frames from HCI layer */ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_uart *hu = hci_get_drvdata(hdev); if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); hu->proto->enqueue(hu, skb); hci_uart_tx_wakeup(hu); return 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); }
/* * 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); }
static void qca_wq_serial_tx_clock_vote_off(struct work_struct *work) { struct qca_data *qca = container_of(work, struct qca_data, ws_tx_vote_off); struct hci_uart *hu = qca->hu; BT_DBG("hu %p tx clock vote off", hu); /* Run HCI tx handling unlocked */ hci_uart_tx_wakeup(hu); /* 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. */ serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu); }
/* Send frames from HCI layer */ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_uart *hu = hci_get_drvdata(hdev); BT_DBG("%s: type %d len %d", hdev->name, hci_skb_pkt_type(skb), skb->len); if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) return -EUNATCH; hu->proto->enqueue(hu, skb); hci_uart_tx_wakeup(hu); return 0; }
/* Send frames from HCI layer */ static int hci_uart_send_frame(struct sk_buff *skb) { struct hci_dev* hdev = (struct hci_dev *) skb->dev; struct hci_uart *hu; #ifdef CONFIG_TROUT_UART_TRANSPORT_DEBUG struct h4_struct *h4; int is_queue_empty = 0; #endif if (!hdev) { BT_ERR("Frame for unknown device (hdev=NULL)"); return -ENODEV; } if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; hu = (struct hci_uart *) hdev->driver_data; #ifdef CONFIG_TROUT_UART_TRANSPORT_DEBUG h4 = hu->priv; #endif BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); #ifdef CONFIG_TROUT_UART_TRANSPORT_DEBUG BT_UART_DBG("sk_data1:type 0x%x len =%d data:0x%x 0x%x 0x%x",bt_cb(skb)->pkt_type, skb->len,skb->data[0], skb->data[1], skb->data[2]); hu->proto->enqueue(hu, skb); if(!hci_is_ctl_act()) { is_queue_empty = is_skb_queue_empty(&h4->txq); hci_uart_tx_wakeup_sprd(hu, is_queue_empty, false, false); } else { if(NULL != &timer_retransmit) { del_timer(&timer_retransmit); } hci_uart_tx_wakeup_sprd(hu, 0, true, false); } #else hu->proto->enqueue(hu, skb); #endif #ifndef CONFIG_TROUT_UART_TRANSPORT_DEBUG hci_uart_tx_wakeup(hu); #endif 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 */ 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); }
/* hci_uart_tty_wakeup() * * Callback for transmit wakeup. Called when low level * device driver can accept more send data. * * Arguments: tty pointer to associated tty instance data * Return Value: None */ static void hci_uart_tty_wakeup(struct tty_struct *tty) { struct hci_uart *hu = (void *)tty->disc_data; BT_DBG(""); if (!hu) return; clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); if (tty != hu->tty) return; if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) hci_uart_tx_wakeup(hu); }
/* hci_uart_tty_wakeup() * * Callback for transmit wakeup. Called when low level * device driver can accept more send data. * * Arguments: tty pointer to associated tty instance data * Return Value: None */ static void hci_uart_tty_wakeup(cyg_io_handle_t tty) { struct hci_uart *hu = (struct hci_uart *)serial_getdisc(tty);//(void *)tty->disc_data; // BT_DBG(""); if (!hu) return; // clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); if (tty != hu->tty) return; if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) hci_uart_tx_wakeup(hu); }
static void ath_hci_uart_work(struct work_struct *work) { int status; struct ath_struct *ath; struct hci_uart *hu; ath = container_of(work, struct ath_struct, ctxtsw); hu = ath->hu; /* verify and wake up controller */ if (test_bit(BT_SLEEPENABLE, &flags)) status = ath_wakeup_ar3k(); /* Ready to send Data */ clear_bit(HCI_UART_SENDING, &hu->tx_state); hci_uart_tx_wakeup(hu); }
/* Called upon wake-up-acknowledgement from the device */ static void device_woke_up(struct hci_uart *hu) { unsigned long flags, idle_delay; struct qca_data *qca = hu->priv; struct sk_buff *skb = NULL; BT_DBG("hu %p woke up", hu); spin_lock_irqsave(&qca->hci_ibs_lock, flags); qca->ibs_recv_wacks++; switch (qca->tx_ibs_state) { case HCI_IBS_TX_AWAKE: /* Expect one if we send 2 WAKEs */ BT_DBG("Received HCI_IBS_WAKE_ACK in tx state %d", qca->tx_ibs_state); break; case HCI_IBS_TX_WAKING: /* Send pending packets */ while ((skb = skb_dequeue(&qca->tx_wait_q))) skb_queue_tail(&qca->txq, skb); /* Switch timers and change state to HCI_IBS_TX_AWAKE */ del_timer(&qca->wake_retrans_timer); idle_delay = msecs_to_jiffies(qca->tx_idle_delay); mod_timer(&qca->tx_idle_timer, jiffies + idle_delay); qca->tx_ibs_state = HCI_IBS_TX_AWAKE; break; case HCI_IBS_TX_ASLEEP: /* Fall through */ default: BT_ERR("Received HCI_IBS_WAKE_ACK in tx state %d", qca->tx_ibs_state); break; } spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); /* Actually send the packets */ hci_uart_tx_wakeup(hu); }
static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) { struct hci_uart *hu = hci_get_drvdata(hdev); struct qca_data *qca = hu->priv; struct qca_serdev *qcadev; struct sk_buff *skb; u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 }; if (baudrate > QCA_BAUDRATE_3200000) return -EINVAL; cmd[4] = baudrate; skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL); if (!skb) { bt_dev_err(hdev, "Failed to allocate baudrate packet"); return -ENOMEM; } /* Assign commands to change baudrate and packet type. */ skb_put_data(skb, cmd, sizeof(cmd)); hci_skb_pkt_type(skb) = HCI_COMMAND_PKT; skb_queue_tail(&qca->txq, skb); hci_uart_tx_wakeup(hu); qcadev = serdev_device_get_drvdata(hu->serdev); /* Wait for the baudrate change request to be sent */ while (!skb_queue_empty(&qca->txq)) usleep_range(100, 200); serdev_device_wait_until_sent(hu->serdev, msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); /* Give the controller time to process the request */ if (qcadev->btsoc_type == QCA_WCN3990) msleep(10); else msleep(300); return 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); }