| .. | .. |
|---|
| 50 | 50 | #define IBS_HOST_TX_IDLE_TIMEOUT_MS 2000 |
|---|
| 51 | 51 | #define CMD_TRANS_TIMEOUT_MS 100 |
|---|
| 52 | 52 | #define MEMDUMP_TIMEOUT_MS 8000 |
|---|
| 53 | +#define IBS_DISABLE_SSR_TIMEOUT_MS \ |
|---|
| 54 | + (MEMDUMP_TIMEOUT_MS + FW_DOWNLOAD_TIMEOUT_MS) |
|---|
| 55 | +#define FW_DOWNLOAD_TIMEOUT_MS 3000 |
|---|
| 53 | 56 | |
|---|
| 54 | 57 | /* susclk rate */ |
|---|
| 55 | 58 | #define SUSCLK_RATE_32KHZ 32768 |
|---|
| .. | .. |
|---|
| 68 | 71 | #define QCA_MEMDUMP_BYTE 0xFB |
|---|
| 69 | 72 | |
|---|
| 70 | 73 | enum qca_flags { |
|---|
| 71 | | - QCA_IBS_ENABLED, |
|---|
| 74 | + QCA_IBS_DISABLED, |
|---|
| 72 | 75 | QCA_DROP_VENDOR_EVENT, |
|---|
| 73 | 76 | QCA_SUSPENDING, |
|---|
| 74 | 77 | QCA_MEMDUMP_COLLECTION, |
|---|
| 75 | 78 | QCA_HW_ERROR_EVENT, |
|---|
| 76 | | - QCA_SSR_TRIGGERED |
|---|
| 79 | + QCA_SSR_TRIGGERED, |
|---|
| 80 | + QCA_BT_OFF, |
|---|
| 81 | + QCA_ROM_FW, |
|---|
| 82 | + QCA_DEBUGFS_CREATED, |
|---|
| 77 | 83 | }; |
|---|
| 78 | 84 | |
|---|
| 79 | 85 | enum qca_capabilities { |
|---|
| .. | .. |
|---|
| 628 | 634 | if (!hdev->debugfs) |
|---|
| 629 | 635 | return; |
|---|
| 630 | 636 | |
|---|
| 637 | + if (test_and_set_bit(QCA_DEBUGFS_CREATED, &qca->flags)) |
|---|
| 638 | + return; |
|---|
| 639 | + |
|---|
| 631 | 640 | ibs_dir = debugfs_create_dir("ibs", hdev->debugfs); |
|---|
| 632 | 641 | |
|---|
| 633 | 642 | /* read only */ |
|---|
| .. | .. |
|---|
| 870 | 879 | * Out-Of-Band(GPIOs control) sleep is selected. |
|---|
| 871 | 880 | * Don't wake the device up when suspending. |
|---|
| 872 | 881 | */ |
|---|
| 873 | | - if (!test_bit(QCA_IBS_ENABLED, &qca->flags) || |
|---|
| 882 | + if (test_bit(QCA_IBS_DISABLED, &qca->flags) || |
|---|
| 874 | 883 | test_bit(QCA_SUSPENDING, &qca->flags)) { |
|---|
| 875 | 884 | skb_queue_tail(&qca->txq, skb); |
|---|
| 876 | 885 | spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); |
|---|
| .. | .. |
|---|
| 905 | 914 | default: |
|---|
| 906 | 915 | BT_ERR("Illegal tx state: %d (losing packet)", |
|---|
| 907 | 916 | qca->tx_ibs_state); |
|---|
| 908 | | - kfree_skb(skb); |
|---|
| 917 | + dev_kfree_skb_irq(skb); |
|---|
| 909 | 918 | break; |
|---|
| 910 | 919 | } |
|---|
| 911 | 920 | |
|---|
| .. | .. |
|---|
| 1015 | 1024 | * the controller to send the dump is 8 seconds. let us |
|---|
| 1016 | 1025 | * start timer to handle this asynchronous activity. |
|---|
| 1017 | 1026 | */ |
|---|
| 1018 | | - clear_bit(QCA_IBS_ENABLED, &qca->flags); |
|---|
| 1027 | + set_bit(QCA_IBS_DISABLED, &qca->flags); |
|---|
| 1019 | 1028 | set_bit(QCA_MEMDUMP_COLLECTION, &qca->flags); |
|---|
| 1020 | 1029 | dump = (void *) skb->data; |
|---|
| 1021 | 1030 | dump_size = __le32_to_cpu(dump->dump_size); |
|---|
| .. | .. |
|---|
| 1621 | 1630 | struct hci_uart *hu = hci_get_drvdata(hdev); |
|---|
| 1622 | 1631 | enum qca_btsoc_type soc_type = qca_soc_type(hu); |
|---|
| 1623 | 1632 | struct qca_serdev *qcadev; |
|---|
| 1633 | + struct qca_data *qca = hu->priv; |
|---|
| 1624 | 1634 | int ret = 0; |
|---|
| 1625 | 1635 | |
|---|
| 1626 | 1636 | /* Non-serdev device usually is powered by external power |
|---|
| .. | .. |
|---|
| 1640 | 1650 | } |
|---|
| 1641 | 1651 | } |
|---|
| 1642 | 1652 | |
|---|
| 1653 | + clear_bit(QCA_BT_OFF, &qca->flags); |
|---|
| 1643 | 1654 | return ret; |
|---|
| 1644 | 1655 | } |
|---|
| 1645 | 1656 | |
|---|
| .. | .. |
|---|
| 1658 | 1669 | if (ret) |
|---|
| 1659 | 1670 | return ret; |
|---|
| 1660 | 1671 | |
|---|
| 1672 | + clear_bit(QCA_ROM_FW, &qca->flags); |
|---|
| 1661 | 1673 | /* Patch downloading has to be done without IBS mode */ |
|---|
| 1662 | | - clear_bit(QCA_IBS_ENABLED, &qca->flags); |
|---|
| 1674 | + set_bit(QCA_IBS_DISABLED, &qca->flags); |
|---|
| 1663 | 1675 | |
|---|
| 1664 | 1676 | /* Enable controller to do both LE scan and BR/EDR inquiry |
|---|
| 1665 | 1677 | * simultaneously. |
|---|
| .. | .. |
|---|
| 1710 | 1722 | ret = qca_uart_setup(hdev, qca_baudrate, soc_type, soc_ver, |
|---|
| 1711 | 1723 | firmware_name); |
|---|
| 1712 | 1724 | if (!ret) { |
|---|
| 1713 | | - set_bit(QCA_IBS_ENABLED, &qca->flags); |
|---|
| 1725 | + clear_bit(QCA_IBS_DISABLED, &qca->flags); |
|---|
| 1714 | 1726 | qca_debugfs_init(hdev); |
|---|
| 1715 | 1727 | hu->hdev->hw_error = qca_hw_error; |
|---|
| 1716 | 1728 | hu->hdev->cmd_timeout = qca_cmd_timeout; |
|---|
| 1717 | 1729 | } else if (ret == -ENOENT) { |
|---|
| 1718 | 1730 | /* No patch/nvm-config found, run with original fw/config */ |
|---|
| 1731 | + set_bit(QCA_ROM_FW, &qca->flags); |
|---|
| 1719 | 1732 | ret = 0; |
|---|
| 1720 | 1733 | } else if (ret == -EAGAIN) { |
|---|
| 1721 | 1734 | /* |
|---|
| 1722 | 1735 | * Userspace firmware loader will return -EAGAIN in case no |
|---|
| 1723 | 1736 | * patch/nvm-config is found, so run with original fw/config. |
|---|
| 1724 | 1737 | */ |
|---|
| 1738 | + set_bit(QCA_ROM_FW, &qca->flags); |
|---|
| 1725 | 1739 | ret = 0; |
|---|
| 1726 | 1740 | } else { |
|---|
| 1727 | 1741 | if (retries < MAX_INIT_RETRIES) { |
|---|
| .. | .. |
|---|
| 1814 | 1828 | * data in skb's. |
|---|
| 1815 | 1829 | */ |
|---|
| 1816 | 1830 | spin_lock_irqsave(&qca->hci_ibs_lock, flags); |
|---|
| 1817 | | - clear_bit(QCA_IBS_ENABLED, &qca->flags); |
|---|
| 1831 | + set_bit(QCA_IBS_DISABLED, &qca->flags); |
|---|
| 1818 | 1832 | qca_flush(hu); |
|---|
| 1819 | 1833 | spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); |
|---|
| 1820 | 1834 | |
|---|
| .. | .. |
|---|
| 1833 | 1847 | } else if (qcadev->bt_en) { |
|---|
| 1834 | 1848 | gpiod_set_value_cansleep(qcadev->bt_en, 0); |
|---|
| 1835 | 1849 | } |
|---|
| 1850 | + |
|---|
| 1851 | + set_bit(QCA_BT_OFF, &qca->flags); |
|---|
| 1836 | 1852 | } |
|---|
| 1837 | 1853 | |
|---|
| 1838 | 1854 | static int qca_power_off(struct hci_dev *hdev) |
|---|
| .. | .. |
|---|
| 2057 | 2073 | int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS); |
|---|
| 2058 | 2074 | struct serdev_device *serdev = to_serdev_device(dev); |
|---|
| 2059 | 2075 | struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); |
|---|
| 2076 | + struct hci_uart *hu = &qcadev->serdev_hu; |
|---|
| 2077 | + struct hci_dev *hdev = hu->hdev; |
|---|
| 2078 | + struct qca_data *qca = hu->priv; |
|---|
| 2060 | 2079 | const u8 ibs_wake_cmd[] = { 0xFD }; |
|---|
| 2061 | 2080 | const u8 edl_reset_soc_cmd[] = { 0x01, 0x00, 0xFC, 0x01, 0x05 }; |
|---|
| 2062 | 2081 | |
|---|
| 2063 | 2082 | if (qcadev->btsoc_type == QCA_QCA6390) { |
|---|
| 2083 | + if (test_bit(QCA_BT_OFF, &qca->flags) || |
|---|
| 2084 | + !test_bit(HCI_RUNNING, &hdev->flags)) |
|---|
| 2085 | + return; |
|---|
| 2086 | + |
|---|
| 2064 | 2087 | serdev_device_write_flush(serdev); |
|---|
| 2065 | 2088 | ret = serdev_device_write_buf(serdev, ibs_wake_cmd, |
|---|
| 2066 | 2089 | sizeof(ibs_wake_cmd)); |
|---|
| .. | .. |
|---|
| 2093 | 2116 | bool tx_pending = false; |
|---|
| 2094 | 2117 | int ret = 0; |
|---|
| 2095 | 2118 | u8 cmd; |
|---|
| 2119 | + u32 wait_timeout = 0; |
|---|
| 2096 | 2120 | |
|---|
| 2097 | 2121 | set_bit(QCA_SUSPENDING, &qca->flags); |
|---|
| 2098 | 2122 | |
|---|
| 2099 | | - /* Device is downloading patch or doesn't support in-band sleep. */ |
|---|
| 2100 | | - if (!test_bit(QCA_IBS_ENABLED, &qca->flags)) |
|---|
| 2123 | + /* if BT SoC is running with default firmware then it does not |
|---|
| 2124 | + * support in-band sleep |
|---|
| 2125 | + */ |
|---|
| 2126 | + if (test_bit(QCA_ROM_FW, &qca->flags)) |
|---|
| 2101 | 2127 | return 0; |
|---|
| 2102 | 2128 | |
|---|
| 2129 | + /* During SSR after memory dump collection, controller will be |
|---|
| 2130 | + * powered off and then powered on.If controller is powered off |
|---|
| 2131 | + * during SSR then we should wait until SSR is completed. |
|---|
| 2132 | + */ |
|---|
| 2133 | + if (test_bit(QCA_BT_OFF, &qca->flags) && |
|---|
| 2134 | + !test_bit(QCA_SSR_TRIGGERED, &qca->flags)) |
|---|
| 2135 | + return 0; |
|---|
| 2136 | + |
|---|
| 2137 | + if (test_bit(QCA_IBS_DISABLED, &qca->flags) || |
|---|
| 2138 | + test_bit(QCA_SSR_TRIGGERED, &qca->flags)) { |
|---|
| 2139 | + wait_timeout = test_bit(QCA_SSR_TRIGGERED, &qca->flags) ? |
|---|
| 2140 | + IBS_DISABLE_SSR_TIMEOUT_MS : |
|---|
| 2141 | + FW_DOWNLOAD_TIMEOUT_MS; |
|---|
| 2142 | + |
|---|
| 2143 | + /* QCA_IBS_DISABLED flag is set to true, During FW download |
|---|
| 2144 | + * and during memory dump collection. It is reset to false, |
|---|
| 2145 | + * After FW download complete. |
|---|
| 2146 | + */ |
|---|
| 2147 | + wait_on_bit_timeout(&qca->flags, QCA_IBS_DISABLED, |
|---|
| 2148 | + TASK_UNINTERRUPTIBLE, msecs_to_jiffies(wait_timeout)); |
|---|
| 2149 | + |
|---|
| 2150 | + if (test_bit(QCA_IBS_DISABLED, &qca->flags)) { |
|---|
| 2151 | + bt_dev_err(hu->hdev, "SSR or FW download time out"); |
|---|
| 2152 | + ret = -ETIMEDOUT; |
|---|
| 2153 | + goto error; |
|---|
| 2154 | + } |
|---|
| 2155 | + } |
|---|
| 2156 | + |
|---|
| 2103 | 2157 | cancel_work_sync(&qca->ws_awake_device); |
|---|
| 2104 | 2158 | cancel_work_sync(&qca->ws_awake_rx); |
|---|
| 2105 | 2159 | |
|---|