Bluetooth: btmtksdio: transmit packet according to status TX_EMPTY
authorMark-yw Chen <mark-yw.chen@mediatek.com>
Mon, 18 Oct 2021 21:30:19 +0000 (05:30 +0800)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 25 Oct 2021 13:36:23 +0000 (15:36 +0200)
Each packet should be sent out until the device emits the TX_EMPTY signal
to the host, that is firmware people suggested to add to meet the actual
firmware behavior and that is compatible among all the devices.

Co-developed-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Mark-yw Chen <mark-yw.chen@mediatek.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
drivers/bluetooth/btmtksdio.c

index f816a7c..3266c5d 100644 (file)
@@ -103,6 +103,7 @@ struct btmtksdio_dev {
        struct work_struct txrx_work;
        unsigned long tx_state;
        struct sk_buff_head txq;
+       bool hw_tx_ready;
 
        struct sk_buff *evt_skb;
 
@@ -229,6 +230,7 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,
        sdio_hdr->reserved = cpu_to_le16(0);
        sdio_hdr->bt_type = hci_skb_pkt_type(skb);
 
+       bdev->hw_tx_ready = false;
        err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data,
                           round_up(skb->len, MTK_SDIO_BLOCK_SIZE));
        if (err < 0)
@@ -417,15 +419,6 @@ static void btmtksdio_txrx_work(struct work_struct *work)
        /* Disable interrupt */
        sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
 
-       while ((skb = skb_dequeue(&bdev->txq))) {
-               err = btmtksdio_tx_packet(bdev, skb);
-               if (err < 0) {
-                       bdev->hdev->stat.err_tx++;
-                       skb_queue_head(&bdev->txq, skb);
-                       break;
-               }
-       }
-
        txrx_timeout = jiffies + 5 * HZ;
 
        do {
@@ -446,10 +439,21 @@ static void btmtksdio_txrx_work(struct work_struct *work)
                        bt_dev_dbg(bdev->hdev, "Get fw own back");
 
                if (int_status & TX_EMPTY)
-                       schedule_work(&bdev->txrx_work);
+                       bdev->hw_tx_ready = true;
                else if (unlikely(int_status & TX_FIFO_OVERFLOW))
                        bt_dev_warn(bdev->hdev, "Tx fifo overflow");
 
+               if (bdev->hw_tx_ready) {
+                       skb = skb_dequeue(&bdev->txq);
+                       if (skb) {
+                               err = btmtksdio_tx_packet(bdev, skb);
+                               if (err < 0) {
+                                       bdev->hdev->stat.err_tx++;
+                                       skb_queue_head(&bdev->txq, skb);
+                               }
+                       }
+               }
+
                if (int_status & RX_DONE_INT) {
                        rx_size = sdio_readl(bdev->func, MTK_REG_CRPLR, NULL);
                        rx_size = (rx_size & RX_PKT_LEN) >> 16;
@@ -642,6 +646,7 @@ static int btmtksdio_setup(struct hci_dev *hdev)
        u8 param = 0x1;
 
        calltime = ktime_get();
+       bdev->hw_tx_ready = true;
 
        /* Query whether the firmware is already download */
        wmt_params.op = BTMTK_WMT_SEMAPHORE;