From 6182567d90eb0e3b9105cdd9c415569f2cd13925 Mon Sep 17 00:00:00 2001
From: Owen Huang <Owen.Huang@infineon.com>
Date: Sun, 25 Dec 2022 21:06:12 -0600
Subject: [PATCH 215/296] non-upstream: btsdio: enable export api for F3
 transferring buffer

1. enable export api ifx_bus_send_buf for F3 transferring buffer
2. add argument function number (fn) to separate F2/F3 flow
3. function 3 use sdio_writesb to a FIFO of a SDIO function


Signed-off-by: Owen Huang <Owen.Huang@infineon.com>


---
 .../broadcom/brcm80211/brcmfmac/bcmsdh.c      | 47 +++++++++++++++----
 .../brcm80211/brcmfmac/bt_shared_sdio_ifx.c   |  3 +-
 .../broadcom/brcm80211/brcmfmac/sdio.c        |  2 +-
 .../broadcom/brcm80211/brcmfmac/sdio.h        |  3 +-
 4 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 925cc0f8a40c..0f0c2b6b085e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -328,7 +328,12 @@ static int brcmf_sdiod_skbuff_write(struct brcmf_sdio_dev *sdiodev,
 	req_sz = skb->len + 3;
 	req_sz &= (uint)~3;
 
-	err = sdio_memcpy_toio(func, addr, ((u8 *)(skb->data)), req_sz);
+	if (func->num == SDIO_FUNC_1 || func->num == SDIO_FUNC_2)
+		err = sdio_memcpy_toio(func, addr, ((u8 *)(skb->data)), req_sz);
+	else if (func->num == SDIO_FUNC_3)
+		err = sdio_writesb(func, addr, ((u8 *)(skb->data)), req_sz);
+	else
+		return -EINVAL;
 
 	if (err == -ENOMEDIUM)
 		brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
@@ -626,11 +631,35 @@ int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
 	return err;
 }
 
-int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
+int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 fn,
+			 u8 *buf, uint nbytes)
 {
-	struct sk_buff *mypkt;
-	u32 addr = sdiodev->cc_core->base;
-	int err;
+	struct sk_buff *mypkt = NULL;
+	struct sdio_func *func = NULL;
+	u32 base_addr = 0;
+	u32 send_addr = 0;
+	int err = 0;
+
+	if (fn == 2) {
+		/* F2 is only DMA. HW ignore the address field in the cmd53 /cmd52. */
+		base_addr = sdiodev->cc_core->base;
+		send_addr = base_addr & SBSDIO_SB_OFT_ADDR_MASK;
+		send_addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+		func = sdiodev->func2;
+	} else if (fn == 3) {
+		/* F3 has registers and DMA. A DMA access is identified using the
+		 * address value 0x0. If the address field has any other value, it
+		 * won't be considered as F3 packet transfer. If the address corresponds
+		 * to a valid F3 register address, driver will get proper response,
+		 * otherwise driver will get error response.
+		 */
+		base_addr = 0;
+		send_addr = 0;
+		func = sdiodev->func3;
+	} else {
+		brcmf_err("invalid function number: %d\n", fn);
+		return -EINVAL;
+	}
 
 	mypkt = brcmu_pkt_buf_get_skb(nbytes);
 
@@ -642,14 +671,14 @@ int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
 
 	memcpy(mypkt->data, buf, nbytes);
 
-	err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+	err = brcmf_sdiod_set_backplane_window(sdiodev, base_addr);
 	if (err)
 		goto out;
 
-	addr &= SBSDIO_SB_OFT_ADDR_MASK;
-	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+	err = brcmf_sdiod_skbuff_write(sdiodev, func, send_addr, mypkt);
 
-	err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr, mypkt);
+	brcmf_dbg(DATA, "F%d, base addr: 0x%x, send addr: 0x%x, size: %d, err: %d\n",
+		  fn, base_addr, send_addr, mypkt->len, err);
 out:
 	brcmu_pkt_buf_free_skb(mypkt);
 
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.c
index 28cad10e79c9..0d50f626f2c9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bt_shared_sdio_ifx.c
@@ -765,8 +765,7 @@ int inf_bus_send_buf(struct brcmf_bus *bus_if, u8 *buf, u32 nbytes)
 	sdiodev = bus_if->bus_priv.sdio;
 
 	sdio_claim_host(sdiodev->func1);
-	// wait for next commit for Tx
-	//err = brcmf_sdiod_send_buf(sdiodev, SDIO_FUNC_3, buf, nbytes);
+	err = brcmf_sdiod_send_buf(sdiodev, SDIO_FUNC_3, buf, nbytes);
 	sdio_release_host(sdiodev->func1);
 
 	brcmf_dbg(DATA, "F3 send nbytes: %d, err: %d\n", nbytes, err);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 1218d2ad66db..3a99975f739e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -2818,7 +2818,7 @@ static int brcmf_sdio_tx_ctrlframe(struct brcmf_sdio *bus, u8 *frame, u16 len)
 			   frame, min_t(u16, len, 16), "TxHdr:\n");
 
 	do {
-		ret = brcmf_sdiod_send_buf(bus->sdiodev, frame, len);
+		ret = brcmf_sdiod_send_buf(bus->sdiodev, SDIO_FUNC_2, frame, len);
 
 		if (ret < 0)
 			brcmf_sdio_txfail(bus);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index 6faaeddc98a4..fa86cf932c51 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -398,7 +398,8 @@ void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data,
  */
 int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,
 			 struct sk_buff_head *pktq);
-int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes);
+int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 fn,
+			 u8 *buf, uint nbytes);
 
 int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, u8 fn,
 			 struct sk_buff *pkt);
-- 
2.25.1

