Skip to content

Commit 15208f0

Browse files
marcanjannau
authored andcommitted
wifi: brcmfmac: Support exchanging power mailbox messages via commonring
Newer firmwares have switched from using the hardware mailbox to commonring messages for power mailbox data. Implement this, which makes D3 work on WiFi chipsets in Apple devices. This is only enabled on v6 or newer, iff BRCMF_PCIE_SHARED_USE_MAILBOX is not set in the flags. Signed-off-by: Hector Martin <marcan@marcan.st>
1 parent a5aa3be commit 15208f0

1 file changed

Lines changed: 55 additions & 20 deletions

File tree

  • drivers/net/wireless/broadcom/brcm80211/brcmfmac

drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ struct brcmf_pcie_shared_info {
371371
void *ringupd;
372372
dma_addr_t ringupd_dmahandle;
373373
u8 version;
374+
bool mb_via_ctl;
374375
};
375376

376377
#define BRCMF_OTP_MAX_PARAM_LEN 16
@@ -817,6 +818,19 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
817818
u32 i;
818819

819820
shared = &devinfo->shared;
821+
822+
if (shared->mb_via_ctl) {
823+
struct pci_dev *pdev = devinfo->pdev;
824+
struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
825+
int ret;
826+
827+
ret = brcmf_msgbuf_h2d_mb_write(bus->drvr, htod_mb_data);
828+
if (ret < 0)
829+
brcmf_err(bus, "Failed to send H2D mailbox data (%d)\n",
830+
ret);
831+
return ret;
832+
}
833+
820834
addr = shared->htod_mb_data_addr;
821835
cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
822836

@@ -844,8 +858,29 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
844858
return 0;
845859
}
846860

861+
static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo, u32 data)
862+
{
863+
brcmf_dbg(PCIE, "D2H_MB_DATA: 0x%04x\n", data);
864+
if (data & BRCMF_D2H_DEV_DS_ENTER_REQ) {
865+
brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP REQ\n");
866+
brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_DS_ACK);
867+
brcmf_dbg(PCIE, "D2H_MB_DATA: sent DEEP SLEEP ACK\n");
868+
}
869+
if (data & BRCMF_D2H_DEV_DS_EXIT_NOTE)
870+
brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n");
871+
if (data & BRCMF_D2H_DEV_D3_ACK) {
872+
brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n");
873+
devinfo->mbdata_completed = true;
874+
wake_up(&devinfo->mbdata_resp_wait);
875+
}
876+
if (data & BRCMF_D2H_DEV_FWHALT) {
877+
brcmf_dbg(PCIE, "D2H_MB_DATA: FW HALT\n");
878+
brcmf_fw_crashed(&devinfo->pdev->dev);
879+
}
880+
}
881+
847882

848-
static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)
883+
static void brcmf_pcie_poll_mb_data(struct brcmf_pciedev_info *devinfo)
849884
{
850885
struct brcmf_pcie_shared_info *shared;
851886
u32 addr;
@@ -860,23 +895,16 @@ static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)
860895

861896
brcmf_pcie_write_tcm32(devinfo, addr, 0);
862897

863-
brcmf_dbg(PCIE, "D2H_MB_DATA: 0x%04x\n", dtoh_mb_data);
864-
if (dtoh_mb_data & BRCMF_D2H_DEV_DS_ENTER_REQ) {
865-
brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP REQ\n");
866-
brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_DS_ACK);
867-
brcmf_dbg(PCIE, "D2H_MB_DATA: sent DEEP SLEEP ACK\n");
868-
}
869-
if (dtoh_mb_data & BRCMF_D2H_DEV_DS_EXIT_NOTE)
870-
brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n");
871-
if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) {
872-
brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n");
873-
devinfo->mbdata_completed = true;
874-
wake_up(&devinfo->mbdata_resp_wait);
875-
}
876-
if (dtoh_mb_data & BRCMF_D2H_DEV_FWHALT) {
877-
brcmf_dbg(PCIE, "D2H_MB_DATA: FW HALT\n");
878-
brcmf_fw_crashed(&devinfo->pdev->dev);
879-
}
898+
brcmf_pcie_handle_mb_data(devinfo, dtoh_mb_data);
899+
}
900+
901+
902+
static void brcmf_pcie_d2h_mb_rx(struct device *dev, u32 data)
903+
{
904+
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
905+
struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
906+
907+
brcmf_pcie_handle_mb_data(buspub->devinfo, data);
880908
}
881909

882910

@@ -1006,7 +1034,7 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
10061034
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint,
10071035
status);
10081036
if (status & devinfo->reginfo->int_fn0)
1009-
brcmf_pcie_handle_mb_data(devinfo);
1037+
brcmf_pcie_poll_mb_data(devinfo);
10101038
}
10111039
if (devinfo->have_msi || status & devinfo->reginfo->int_d2h_db) {
10121040
if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
@@ -1651,6 +1679,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
16511679
.get_blob = brcmf_pcie_get_blob,
16521680
.reset = brcmf_pcie_reset,
16531681
.debugfs_create = brcmf_pcie_debugfs_create,
1682+
.d2h_mb_rx = brcmf_pcie_d2h_mb_rx,
16541683
};
16551684

16561685

@@ -1741,6 +1770,10 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
17411770
shared->flags3 = brcmf_pcie_read_tcm32(devinfo, sharedram_addr +
17421771
BRCMF_SHARED_FLAGS3_OFFSET);
17431772

1773+
/* Check which mailbox mechanism to use */
1774+
if (!(shared->flags & BRCMF_PCIE_SHARED_USE_MAILBOX))
1775+
shared->mb_via_ctl = true;
1776+
17441777
/* Update host support flags */
17451778
host_cap = shared->version;
17461779
host_cap2 = 0;
@@ -2718,10 +2751,11 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
27182751
/* Check if device is still up and running, if so we are ready */
27192752
if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->intmask) != 0) {
27202753
brcmf_dbg(PCIE, "Try to wakeup device....\n");
2754+
/* Set the device up, so we can write the MB data message in ring mode */
2755+
devinfo->state = BRCMFMAC_PCIE_STATE_UP;
27212756
if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))
27222757
goto cleanup;
27232758
brcmf_dbg(PCIE, "Hot resume, continue....\n");
2724-
devinfo->state = BRCMFMAC_PCIE_STATE_UP;
27252759
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
27262760
brcmf_bus_change_state(bus, BRCMF_BUS_UP);
27272761
brcmf_pcie_intr_enable(devinfo);
@@ -2731,6 +2765,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
27312765
}
27322766

27332767
cleanup:
2768+
devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
27342769
brcmf_chip_detach(devinfo->ci);
27352770
devinfo->ci = NULL;
27362771
pdev = devinfo->pdev;

0 commit comments

Comments
 (0)