From ab510e9c6ee7a92820efe35466efc730236e4aca Mon Sep 17 00:00:00 2001
From: Owen Huang <Owen.Huang@infineon.com>
Date: Sun, 25 Dec 2022 20:12:03 -0600
Subject: [PATCH 212/296] non-upstream: btsdio: enable export api for F3
 receiving buffer

1. enable export api ifx_bus_recv_buf for F3 receiving buffer
2. add parameter function number (fn) to separate F2/F3 flow


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        |  6 +--
 .../broadcom/brcm80211/brcmfmac/sdio.h        |  6 ++-
 4 files changed, 43 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index bed1a4802e51..925cc0f8a40c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -302,6 +302,7 @@ static int brcmf_sdiod_skbuff_read(struct brcmf_sdio_dev *sdiodev,
 					 req_sz);
 		break;
 	case SDIO_FUNC_2:
+	case SDIO_FUNC_3:
 		err = sdio_readsb(func, ((u8 *)(skb->data)), addr, req_sz);
 		break;
 	default:
@@ -520,10 +521,11 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev,
 	return ret;
 }
 
-int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
+int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 fn,
+			 u8 *buf, uint nbytes)
 {
-	struct sk_buff *mypkt;
-	int err;
+	struct sk_buff *mypkt = NULL;
+	int err = 0;
 
 	mypkt = brcmu_pkt_buf_get_skb(nbytes);
 	if (!mypkt) {
@@ -532,7 +534,7 @@ int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
 		return -EIO;
 	}
 
-	err = brcmf_sdiod_recv_pkt(sdiodev, mypkt);
+	err = brcmf_sdiod_recv_pkt(sdiodev, fn, mypkt);
 	if (!err)
 		memcpy(buf, mypkt->data, nbytes);
 
@@ -540,22 +542,43 @@ int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
 	return err;
 }
 
-int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt)
+int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, u8 fn,
+			 struct sk_buff *pkt)
 {
-	u32 addr = sdiodev->cc_core->base;
+	struct sdio_func *func = NULL;
+	u32 base_addr = 0;
+	u32 recv_addr = 0;
 	int err = 0;
 
-	brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len);
+	if (fn == SDIO_FUNC_2) {
+		/* F2 is only DMA. HW ignore the address field in the cmd53 /cmd52. */
+		base_addr = sdiodev->cc_core->base;
+		recv_addr = base_addr & SBSDIO_SB_OFT_ADDR_MASK;
+		recv_addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+		func = sdiodev->func2;
+	} else if (fn == SDIO_FUNC_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;
+		recv_addr = 0;
+		func = sdiodev->func3;
+	} else {
+		brcmf_err("invalid function number: %d\n", fn);
+		return -EINVAL;
+	}
 
-	err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+	err = brcmf_sdiod_set_backplane_window(sdiodev, base_addr);
 	if (err)
 		goto done;
 
-	addr &= SBSDIO_SB_OFT_ADDR_MASK;
-	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-	err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr, pkt);
+	err = brcmf_sdiod_skbuff_read(sdiodev, func, recv_addr, pkt);
 
+	brcmf_dbg(DATA, "F%d, base addr: 0x%x, recv addr: 0x%x, size: %d, err: %d\n",
+		  fn, base_addr, recv_addr, pkt->len, err);
 done:
 	return err;
 }
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 98d9e418c001..28cad10e79c9 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
@@ -738,8 +738,7 @@ int inf_bus_recv_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 Rx
-	//err = brcmf_sdiod_recv_buf(sdiodev, SDIO_FUNC_3, buf, nbytes);
+	err = brcmf_sdiod_recv_buf(sdiodev, SDIO_FUNC_3, buf, nbytes);
 	sdio_release_host(sdiodev->func1);
 
 	brcmf_dbg(DATA, "F3 receive 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 fcaf8eadecce..1c32a3dc7804 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -2110,7 +2110,7 @@ brcmf_sdio_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
 	}
 
 	/* Read remain of frame body */
-	sdret = brcmf_sdiod_recv_buf(bus->sdiodev, rbuf, rdlen);
+	sdret = brcmf_sdiod_recv_buf(bus->sdiodev, SDIO_FUNC_2, rbuf, rdlen);
 	bus->sdcnt.f2rxdata++;
 
 	/* Control frame failures need retransmission */
@@ -2196,7 +2196,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 		/* read header first for unknown frame length */
 		sdio_claim_host(bus->sdiodev->func1);
 		if (!rd->len) {
-			ret = brcmf_sdiod_recv_buf(bus->sdiodev,
+			ret = brcmf_sdiod_recv_buf(bus->sdiodev, SDIO_FUNC_2,
 						   bus->rxhdr, BRCMF_FIRSTREAD);
 			bus->sdcnt.f2rxhdrs++;
 			if (ret < 0) {
@@ -2253,7 +2253,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
 		skb_pull(pkt, head_read);
 		pkt_align(pkt, rd->len_left, bus->head_align);
 
-		ret = brcmf_sdiod_recv_pkt(bus->sdiodev, pkt);
+		ret = brcmf_sdiod_recv_pkt(bus->sdiodev, SDIO_FUNC_2, pkt);
 		bus->sdcnt.f2rxdata++;
 		sdio_release_host(bus->sdiodev->func1);
 
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index 639bc23958b6..6faaeddc98a4 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -400,8 +400,10 @@ 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_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt);
-int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes);
+int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, u8 fn,
+			 struct sk_buff *pkt);
+int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 fn,
+			 u8 *buf, uint nbytes);
 int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
 			   struct sk_buff_head *pktq, uint totlen);
 
-- 
2.25.1

