From ab510e9c6ee7a92820efe35466efc730236e4aca Mon Sep 17 00:00:00 2001 From: Owen Huang 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 --- .../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