diff options
author | Mark-yw Chen <mark-yw.chen@mediatek.com> | 2021-10-19 05:30:19 +0800 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2021-10-25 15:36:23 +0200 |
commit | 10fe40e1d70a6a6e5210281cebb124d87c41581b (patch) | |
tree | ddc8a321ed348e9b75e5d34db67eba0f63a22b25 | |
parent | 184ea403ccfc1ba04b75908de4eace979ce2ce4e (diff) |
Bluetooth: btmtksdio: transmit packet according to status TX_EMPTY
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>
-rw-r--r-- | drivers/bluetooth/btmtksdio.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index f816a7cb0a74..3266c5d83cae 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -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; |