@@ -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;