Merge tag 'gcc-plugins-v5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / bluetooth / hci_qca.c
index 1c9a2d4..4a96368 100644 (file)
@@ -50,6 +50,8 @@
 #define IBS_HOST_TX_IDLE_TIMEOUT_MS    2000
 #define CMD_TRANS_TIMEOUT_MS           100
 #define MEMDUMP_TIMEOUT_MS             8000
+#define IBS_DISABLE_SSR_TIMEOUT_MS     (MEMDUMP_TIMEOUT_MS + 1000)
+#define FW_DOWNLOAD_TIMEOUT_MS         3000
 
 /* susclk rate */
 #define SUSCLK_RATE_32KHZ      32768
 #define QCA_MEMDUMP_BYTE               0xFB
 
 enum qca_flags {
-       QCA_IBS_ENABLED,
+       QCA_IBS_DISABLED,
        QCA_DROP_VENDOR_EVENT,
        QCA_SUSPENDING,
        QCA_MEMDUMP_COLLECTION,
        QCA_HW_ERROR_EVENT,
-       QCA_SSR_TRIGGERED
+       QCA_SSR_TRIGGERED,
+       QCA_BT_OFF
 };
 
 enum qca_capabilities {
@@ -631,7 +634,7 @@ static void qca_debugfs_init(struct hci_dev *hdev)
        ibs_dir = debugfs_create_dir("ibs", hdev->debugfs);
 
        /* read only */
-       mode = S_IRUGO;
+       mode = 0444;
        debugfs_create_u8("tx_ibs_state", mode, ibs_dir, &qca->tx_ibs_state);
        debugfs_create_u8("rx_ibs_state", mode, ibs_dir, &qca->rx_ibs_state);
        debugfs_create_u64("ibs_sent_sleeps", mode, ibs_dir,
@@ -658,7 +661,7 @@ static void qca_debugfs_init(struct hci_dev *hdev)
        debugfs_create_u32("vote_off_ms", mode, ibs_dir, &qca->vote_off_ms);
 
        /* read/write */
-       mode = S_IRUGO | S_IWUSR;
+       mode = 0644;
        debugfs_create_u32("wake_retrans", mode, ibs_dir, &qca->wake_retrans);
        debugfs_create_u32("tx_idle_delay", mode, ibs_dir,
                           &qca->tx_idle_delay);
@@ -870,7 +873,7 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb)
         * Out-Of-Band(GPIOs control) sleep is selected.
         * Don't wake the device up when suspending.
         */
-       if (!test_bit(QCA_IBS_ENABLED, &qca->flags) ||
+       if (test_bit(QCA_IBS_DISABLED, &qca->flags) ||
            test_bit(QCA_SUSPENDING, &qca->flags)) {
                skb_queue_tail(&qca->txq, skb);
                spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
@@ -1015,7 +1018,7 @@ static void qca_controller_memdump(struct work_struct *work)
                         * the controller to send the dump is 8 seconds. let us
                         * start timer to handle this asynchronous activity.
                         */
-                       clear_bit(QCA_IBS_ENABLED, &qca->flags);
+                       set_bit(QCA_IBS_DISABLED, &qca->flags);
                        set_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
                        dump = (void *) skb->data;
                        dump_size = __le32_to_cpu(dump->dump_size);
@@ -1302,7 +1305,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
 
        /* Give the controller time to process the request */
        if (qca_is_wcn399x(qca_soc_type(hu)))
-               msleep(10);
+               usleep_range(1000, 10000);
        else
                msleep(300);
 
@@ -1350,7 +1353,7 @@ static int qca_send_power_pulse(struct hci_uart *hu, bool on)
        if (on)
                msleep(100);
        else
-               msleep(10);
+               usleep_range(1000, 10000);
 
        return 0;
 }
@@ -1619,6 +1622,7 @@ static int qca_power_on(struct hci_dev *hdev)
        struct hci_uart *hu = hci_get_drvdata(hdev);
        enum qca_btsoc_type soc_type = qca_soc_type(hu);
        struct qca_serdev *qcadev;
+       struct qca_data *qca = hu->priv;
        int ret = 0;
 
        /* Non-serdev device usually is powered by external power
@@ -1638,6 +1642,7 @@ static int qca_power_on(struct hci_dev *hdev)
                }
        }
 
+       clear_bit(QCA_BT_OFF, &qca->flags);
        return ret;
 }
 
@@ -1650,14 +1655,14 @@ static int qca_setup(struct hci_uart *hu)
        enum qca_btsoc_type soc_type = qca_soc_type(hu);
        const char *firmware_name = qca_get_firmware_name(hu);
        int ret;
-       int soc_ver = 0;
+       struct qca_btsoc_version ver;
 
        ret = qca_check_speeds(hu);
        if (ret)
                return ret;
 
        /* Patch downloading has to be done without IBS mode */
-       clear_bit(QCA_IBS_ENABLED, &qca->flags);
+       set_bit(QCA_IBS_DISABLED, &qca->flags);
 
        /* Enable controller to do both LE scan and BR/EDR inquiry
         * simultaneously.
@@ -1679,7 +1684,7 @@ retry:
        if (qca_is_wcn399x(soc_type)) {
                set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
 
-               ret = qca_read_soc_version(hdev, &soc_ver, soc_type);
+               ret = qca_read_soc_version(hdev, &ver, soc_type);
                if (ret)
                        goto out;
        } else {
@@ -1698,17 +1703,16 @@ retry:
 
        if (!qca_is_wcn399x(soc_type)) {
                /* Get QCA version information */
-               ret = qca_read_soc_version(hdev, &soc_ver, soc_type);
+               ret = qca_read_soc_version(hdev, &ver, soc_type);
                if (ret)
                        goto out;
        }
 
-       bt_dev_info(hdev, "QCA controller version 0x%08x", soc_ver);
        /* Setup patch / NVM configurations */
-       ret = qca_uart_setup(hdev, qca_baudrate, soc_type, soc_ver,
+       ret = qca_uart_setup(hdev, qca_baudrate, soc_type, ver,
                        firmware_name);
        if (!ret) {
-               set_bit(QCA_IBS_ENABLED, &qca->flags);
+               clear_bit(QCA_IBS_DISABLED, &qca->flags);
                qca_debugfs_init(hdev);
                hu->hdev->hw_error = qca_hw_error;
                hu->hdev->cmd_timeout = qca_cmd_timeout;
@@ -1816,7 +1820,7 @@ static void qca_power_shutdown(struct hci_uart *hu)
         * data in skb's.
         */
        spin_lock_irqsave(&qca->hci_ibs_lock, flags);
-       clear_bit(QCA_IBS_ENABLED, &qca->flags);
+       set_bit(QCA_IBS_DISABLED, &qca->flags);
        qca_flush(hu);
        spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
 
@@ -1833,6 +1837,8 @@ static void qca_power_shutdown(struct hci_uart *hu)
        } else if (qcadev->bt_en) {
                gpiod_set_value_cansleep(qcadev->bt_en, 0);
        }
+
+       set_bit(QCA_BT_OFF, &qca->flags);
 }
 
 static int qca_power_off(struct hci_dev *hdev)
@@ -2090,11 +2096,34 @@ static int __maybe_unused qca_suspend(struct device *dev)
        bool tx_pending = false;
        int ret = 0;
        u8 cmd;
+       u32 wait_timeout = 0;
 
        set_bit(QCA_SUSPENDING, &qca->flags);
 
-       /* Device is downloading patch or doesn't support in-band sleep. */
-       if (!test_bit(QCA_IBS_ENABLED, &qca->flags))
+       if (test_bit(QCA_BT_OFF, &qca->flags))
+               return 0;
+
+       if (test_bit(QCA_IBS_DISABLED, &qca->flags)) {
+               wait_timeout = test_bit(QCA_SSR_TRIGGERED, &qca->flags) ?
+                                       IBS_DISABLE_SSR_TIMEOUT_MS :
+                                       FW_DOWNLOAD_TIMEOUT_MS;
+
+               /* QCA_IBS_DISABLED flag is set to true, During FW download
+                * and during memory dump collection. It is reset to false,
+                * After FW download complete and after memory dump collections.
+                */
+               wait_on_bit_timeout(&qca->flags, QCA_IBS_DISABLED,
+                           TASK_UNINTERRUPTIBLE, msecs_to_jiffies(wait_timeout));
+
+               if (test_bit(QCA_IBS_DISABLED, &qca->flags)) {
+                       bt_dev_err(hu->hdev, "SSR or FW download time out");
+                       ret = -ETIMEDOUT;
+                       goto error;
+               }
+       }
+
+       /* After memory dump collection, Controller is powered off.*/
+       if (test_bit(QCA_BT_OFF, &qca->flags))
                return 0;
 
        cancel_work_sync(&qca->ws_awake_device);