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>
This commit is contained in:
committed by
Marcel Holtmann
parent
184ea403cc
commit
10fe40e1d7
@@ -103,6 +103,7 @@ struct btmtksdio_dev {
|
|||||||
struct work_struct txrx_work;
|
struct work_struct txrx_work;
|
||||||
unsigned long tx_state;
|
unsigned long tx_state;
|
||||||
struct sk_buff_head txq;
|
struct sk_buff_head txq;
|
||||||
|
bool hw_tx_ready;
|
||||||
|
|
||||||
struct sk_buff *evt_skb;
|
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->reserved = cpu_to_le16(0);
|
||||||
sdio_hdr->bt_type = hci_skb_pkt_type(skb);
|
sdio_hdr->bt_type = hci_skb_pkt_type(skb);
|
||||||
|
|
||||||
|
bdev->hw_tx_ready = false;
|
||||||
err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data,
|
err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data,
|
||||||
round_up(skb->len, MTK_SDIO_BLOCK_SIZE));
|
round_up(skb->len, MTK_SDIO_BLOCK_SIZE));
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@@ -417,15 +419,6 @@ static void btmtksdio_txrx_work(struct work_struct *work)
|
|||||||
/* Disable interrupt */
|
/* Disable interrupt */
|
||||||
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
|
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;
|
txrx_timeout = jiffies + 5 * HZ;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -446,10 +439,21 @@ static void btmtksdio_txrx_work(struct work_struct *work)
|
|||||||
bt_dev_dbg(bdev->hdev, "Get fw own back");
|
bt_dev_dbg(bdev->hdev, "Get fw own back");
|
||||||
|
|
||||||
if (int_status & TX_EMPTY)
|
if (int_status & TX_EMPTY)
|
||||||
schedule_work(&bdev->txrx_work);
|
bdev->hw_tx_ready = true;
|
||||||
else if (unlikely(int_status & TX_FIFO_OVERFLOW))
|
else if (unlikely(int_status & TX_FIFO_OVERFLOW))
|
||||||
bt_dev_warn(bdev->hdev, "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) {
|
if (int_status & RX_DONE_INT) {
|
||||||
rx_size = sdio_readl(bdev->func, MTK_REG_CRPLR, NULL);
|
rx_size = sdio_readl(bdev->func, MTK_REG_CRPLR, NULL);
|
||||||
rx_size = (rx_size & RX_PKT_LEN) >> 16;
|
rx_size = (rx_size & RX_PKT_LEN) >> 16;
|
||||||
@@ -642,6 +646,7 @@ static int btmtksdio_setup(struct hci_dev *hdev)
|
|||||||
u8 param = 0x1;
|
u8 param = 0x1;
|
||||||
|
|
||||||
calltime = ktime_get();
|
calltime = ktime_get();
|
||||||
|
bdev->hw_tx_ready = true;
|
||||||
|
|
||||||
/* Query whether the firmware is already download */
|
/* Query whether the firmware is already download */
|
||||||
wmt_params.op = BTMTK_WMT_SEMAPHORE;
|
wmt_params.op = BTMTK_WMT_SEMAPHORE;
|
||||||
|
Reference in New Issue
Block a user