From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7E4244A341C; Fri, 25 Sep 2026 13:43:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790343824; cv=none; b=Gz7bgtXcsKh7YICG65TRTYIiN88syiVJ4qlhxFap7N2N7Seivv+gLARhu+ddSNRnpv9XlJfVeOaQu0aU5K3CI1ahB72CfN+/L7wxsiaXwym6rpO5gXYTIsTpW9qGZTYo387GnyICiKNW6dkgV07gdw48LARK0JWP3CQ+RJaRhmo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790343824; c=relaxed/simple; bh=Yuo5e9PGWpNKJHpO35TqM7RmNslEgkB8LiYQvZe9iow=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tKF2xWvuCOZq9hSkegfRwmLUPmye6ouLODTxNnQoVjqoSJvsJslKU0ZD4UUUvkHre5ildHQn84hfjm/m7weXzai3WyaQPuac1uMDr50GOAVGrgvaRNXxgl37jP44sFN/76iwn+I9PRXkGolbwIp5+RAYksF5ZDKmqSzrcaWTMh8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Bf07TP1/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Bf07TP1/" Received: by smtp.kernel.org (Postfix) with ESMTPS id 47C93C2BCFD; Fri, 25 Sep 2026 13:43:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1790343824; bh=Yuo5e9PGWpNKJHpO35TqM7RmNslEgkB8LiYQvZe9iow=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Bf07TP1/8j9LcnPJ/2q8EFfGitqeWg13x/DMvQXOmRqzva6Bgps7K8b6D61A79Lv5 XAlPrsPFWS/hsyIoq8VLY08GCf+Kg1movmuHayYoUVhCGPVZaHZAVBU7Bc+/iCrjsF +PkK3S0nAfYoegvYnWssfXLoA/L/JUna6cNbgeczzeroGbu4/Mpt1j0cdo9TMcL6yu PDgPoM4nJdhiiRI0DDBENhVu0TrI101GxT1NqcoD+K2lcPptuKMIdyPYs7FYj2bSbG 3L5gn2Q00XQFsqo8aC5S5+u0JYkQ59hLlUJfdloo0of0TRDIZxRMZe/a5CshQaLt14 NuHPuEX2x440g== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 36149C98324; Fri, 25 Sep 2026 13:43:44 +0000 (UTC) From: Michael Reeves via B4 Relay Date: Fri, 25 Sep 2026 23:43:39 +1000 Subject: [PATCH 04/13] wifi: brcmfmac: Support newer PCIe core startup and interrupts Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260925-brcm4388-submit-v1-4-b5cbc2cde2fb@gmail.com> References: <20260925-brcm4388-submit-v1-0-b5cbc2cde2fb@gmail.com> In-Reply-To: <20260925-brcm4388-submit-v1-0-b5cbc2cde2fb@gmail.com> To: Arend van Spriel , Pieter-Paul Giesberts , "Franky Lin (Zhenhui)" , Mathy Vanhoef , Kalle Valo , Kees Cook , "Gustavo A. R. Silva" Cc: linux-wireless@vger.kernel.org, brcm80211@lists.linux.dev, brcm80211-dev-list.pdl@broadcom.com, asahi@lists.linux.dev, Hector Martin , Daniel Berlin , Janne Grunau , linux-kernel@vger.kernel.org, Hante Meuleman , linux-hardening@vger.kernel.org, Michael Reeves X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1790343821; l=17963; i=michael.reeves077@gmail.com; s=fedora-20260918; h=from:subject:message-id; bh=E/prAI2R9CIil2fKNQi3uv1awn/puICy85QcRIXRhDE=; b=uxFJ96GLYPTbqNNSiMmmmYbencVhfzDsb3EG5b9SkWUOtPhrij/d1rziXbINJeFF/Ut/2Z3cf URQry7gW+PABcBkmXAnKoBbTXaaoWNLYmyS2aEDviFF1YhQAtisYba7 X-Developer-Key: i=michael.reeves077@gmail.com; a=ed25519; pk=VJ0TvyQ9TvfzYZa908YSE9kpkjFLLD5luv0bERu+boc= X-Endpoint-Received: by B4 Relay for michael.reeves077@gmail.com/fedora-20260918 with auth_id=1035 X-Original-From: Michael Reeves Reply-To: michael.reeves077@gmail.com From: Hector Martin Newer Broadcom chips, such as BCM4388, require changes to PCIe register access, watchdog reset, and RAM size detection. PCIe core revision 64 and higher uses a different BAR0 register window. ChipCommon revision 65 and higher requires a different watchdog reset sequence. Update register access and reset for these revisions. Decode the SYSMEM bank counts according to the core revision and exclude ROM banks from RAM size calculation. Disable all detected D11 cores during CA7 setup and select H2D doorbells based on the firmware DAR flag. In MSI mode, firmware can clear the mailbox interrupt status before the host reads it. Requiring a nonzero status can therefore discard valid interrupts. Process ring events without that requirement when MSI is enabled. Use release/acquire ordering on irq_ready to publish the initialized rings before the interrupt thread accesses them. Signed-off-by: Hector Martin Co-developed-by: Michael Reeves Signed-off-by: Michael Reeves --- .../wireless/broadcom/brcm80211/brcmfmac/chip.c | 35 +++- .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 197 ++++++++++++++++----- .../broadcom/brcm80211/include/chipcommon.h | 5 + 3 files changed, 183 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 4adc0d0e42..253ab45c33 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -162,6 +162,15 @@ struct sbconfig { #define SRCI_SRBSZ_SHIFT 0 #define SR_BSZ_BASE 14 +#define SYSMEM_SRCI_ROMNB_MASK 0x3e0 +#define SYSMEM_SRCI_ROMNB_SHIFT 5 +#define SYSMEM_SRCI_SRNB_MASK 0x1f +#define SYSMEM_SRCI_SRNB_SHIFT 0 +#define SYSMEM_SRCI_NEW_ROMNB_MASK 0xff000000 +#define SYSMEM_SRCI_NEW_ROMNB_SHIFT 24 +#define SYSMEM_SRCI_NEW_SRNB_MASK 0x00ff0000 +#define SYSMEM_SRCI_NEW_SRNB_SHIFT 16 + struct sbsocramregs { u32 coreinfo; u32 bwalloc; @@ -659,6 +668,7 @@ static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem) u32 memsize = 0; u32 coreinfo; u32 idx; + u32 nrb; u32 nb; u32 banksize; @@ -666,10 +676,20 @@ static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem) brcmf_chip_resetcore(&sysmem->pub, 0, 0, 0); coreinfo = brcmf_chip_core_read32(sysmem, SYSMEMREGOFFS(coreinfo)); - nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; + if (sysmem->pub.rev >= 12) { + nrb = (coreinfo & SYSMEM_SRCI_NEW_ROMNB_MASK) >> + SYSMEM_SRCI_NEW_ROMNB_SHIFT; + nb = (coreinfo & SYSMEM_SRCI_NEW_SRNB_MASK) >> + SYSMEM_SRCI_NEW_SRNB_SHIFT; + } else { + nrb = (coreinfo & SYSMEM_SRCI_ROMNB_MASK) >> + SYSMEM_SRCI_ROMNB_SHIFT; + nb = (coreinfo & SYSMEM_SRCI_SRNB_MASK) >> + SYSMEM_SRCI_SRNB_SHIFT; + } for (idx = 0; idx < nb; idx++) { - brcmf_chip_socram_banksize(sysmem, idx, &banksize); + brcmf_chip_socram_banksize(sysmem, idx + nrb, &banksize); memsize += banksize; } @@ -1353,14 +1373,15 @@ static inline void brcmf_chip_ca7_set_passive(struct brcmf_chip_priv *chip) { struct brcmf_core *core; + int i; brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CA7); - core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); - brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET | - D11_BCMA_IOCTL_PHYCLOCKEN, - D11_BCMA_IOCTL_PHYCLOCKEN, - D11_BCMA_IOCTL_PHYCLOCKEN); + /* Leave all D11 cores disabled for the firmware to enable. */ + for (i = 0; (core = brcmf_chip_get_d11core(&chip->pub, i)); i++) + brcmf_chip_coredisable(core, D11_BCMA_IOCTL_PHYRESET | + D11_BCMA_IOCTL_PHYCLOCKEN, + D11_BCMA_IOCTL_PHYCLOCKEN); } static bool brcmf_chip_ca7_set_active(struct brcmf_chip_priv *chip, u32 rstvec) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 5d84526c96..5917ee5fd7 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -220,6 +220,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { #define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000 #define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000 #define BRCMF_PCIE_SHARED_HOSTRDY_DB1 0x10000000 +#define BRCMF_PCIE_SHARED_DAR 0x80000000 + #define BRCMF_PCIE_FLAGS_HTOD_SPLIT 0x4000 #define BRCMF_PCIE_FLAGS_DTOH_SPLIT 0x8000 @@ -280,6 +282,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { #define BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1 0x248 #define BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG 0x4E0 #define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG 0x4F4 +#define BRCMF_PCIE_CFGREG_TLCNTRL_5 0x814 #define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB 3 /* Magic number at a magic location to find RAM size */ @@ -346,6 +349,8 @@ struct brcmf_pciedev_info { wait_queue_head_t mbdata_resp_wait; bool mbdata_completed; bool irq_allocated; + bool irq_ready; + bool have_msi; bool wowl_enabled; u8 dma_idx_sz; void *idxbuf; @@ -432,8 +437,6 @@ struct brcmf_pcie_reginfo { u32 intmask; u32 mailboxint; u32 mailboxmask; - u32 h2d_mailbox_0; - u32 h2d_mailbox_1; u32 int_d2h_db; u32 int_fn0; }; @@ -442,8 +445,6 @@ static const struct brcmf_pcie_reginfo brcmf_reginfo_default = { .intmask = BRCMF_PCIE_PCIE2REG_INTMASK, .mailboxint = BRCMF_PCIE_PCIE2REG_MAILBOXINT, .mailboxmask = BRCMF_PCIE_PCIE2REG_MAILBOXMASK, - .h2d_mailbox_0 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, - .h2d_mailbox_1 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, .int_d2h_db = BRCMF_PCIE_MB_INT_D2H_DB, .int_fn0 = BRCMF_PCIE_MB_INT_FN0, }; @@ -452,8 +453,6 @@ static const struct brcmf_pcie_reginfo brcmf_reginfo_64 = { .intmask = BRCMF_PCIE_64_PCIE2REG_INTMASK, .mailboxint = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT, .mailboxmask = BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK, - .h2d_mailbox_0 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0, - .h2d_mailbox_1 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1, .int_d2h_db = BRCMF_PCIE_64_MB_INT_D2H_DB, .int_fn0 = 0, }; @@ -492,6 +491,46 @@ brcmf_pcie_write_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset, iowrite32(value, address); } +static bool +brcmf_pcie_use_pcie2_bar0_window(struct brcmf_pciedev_info *devinfo) +{ + struct brcmf_core *core; + + if (!devinfo->ci) + return false; + + core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2); + return core && core->rev >= 64; +} + +static u32 +brcmf_pcie_pcie2_reg_offset(struct brcmf_pciedev_info *devinfo, + u32 reg_offset) +{ + if (brcmf_pcie_use_pcie2_bar0_window(devinfo)) + return BRCMF_PCIE_BARO_PCIE_ENUM_OFFSET + reg_offset; + + return reg_offset; +} + +static u32 +brcmf_pcie_read_pcie32(struct brcmf_pciedev_info *devinfo, u32 reg_offset) +{ + return brcmf_pcie_read_reg32(devinfo, + brcmf_pcie_pcie2_reg_offset(devinfo, + reg_offset)); +} + +static void +brcmf_pcie_write_pcie32(struct brcmf_pciedev_info *devinfo, u32 reg_offset, + u32 value) +{ + brcmf_pcie_write_reg32(devinfo, + brcmf_pcie_pcie2_reg_offset(devinfo, + reg_offset), + value); +} + static u8 brcmf_pcie_read_tcm8(struct brcmf_pciedev_info *devinfo, u32 mem_offset) @@ -685,8 +724,29 @@ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo) /* Watchdog reset */ brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON); - WRITECC32(devinfo, watchdog, 4); - msleep(100); + core = brcmf_chip_get_chipcommon(devinfo->ci); + if (core->rev >= 65) { + u32 mask = CC_WD_SSRESET_PCIE_F0_EN; + + core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2); + if (core->rev < 66) + mask |= CC_WD_SSRESET_PCIE_ALL_FN_EN; + + val = READCC32(devinfo, watchdog); + val &= ~CC_WD_ENABLE_MASK; + val |= mask; + WRITECC32(devinfo, watchdog, val); + val &= ~CC_WD_COUNTER_MASK; + val |= 4; + WRITECC32(devinfo, watchdog, val); + fsleep(10000); + val = READCC32(devinfo, intstatus); + val |= mask; + WRITECC32(devinfo, intstatus, val); + } else { + WRITECC32(devinfo, watchdog, 4); + msleep(100); + } /* Restore ASPM */ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); @@ -696,16 +756,13 @@ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo) core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2); if (core->rev <= 13) { for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) { - brcmf_pcie_write_reg32(devinfo, - BRCMF_PCIE_PCIE2REG_CONFIGADDR, - cfg_offset[i]); - val = brcmf_pcie_read_reg32(devinfo, - BRCMF_PCIE_PCIE2REG_CONFIGDATA); + brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, + cfg_offset[i]); + val = brcmf_pcie_read_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA); brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n", cfg_offset[i], val); - brcmf_pcie_write_reg32(devinfo, - BRCMF_PCIE_PCIE2REG_CONFIGDATA, - val); + brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, + val); } } } @@ -717,9 +774,12 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo) /* BAR1 window may not be sized properly */ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0); - config = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config); + brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, + 0x4e0); + config = brcmf_pcie_read_pcie32(devinfo, + BRCMF_PCIE_PCIE2REG_CONFIGDATA); + brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, + config); device_wakeup_enable(&devinfo->pdev->dev); } @@ -738,6 +798,21 @@ static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo) brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA, 0); } + if (brcmf_pcie_use_pcie2_bar0_window(devinfo)) { + brcmf_pcie_write_pcie32(devinfo, + devinfo->reginfo->mailboxmask, 0); + brcmf_pcie_write_pcie32(devinfo, + devinfo->reginfo->mailboxint, + 0xffffffff); + pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_INTMASK, + 0); + brcmf_pcie_write_pcie32(devinfo, + BRCMF_PCIE_PCIE2REG_CONFIGADDR, + BRCMF_PCIE_CFGREG_TLCNTRL_5); + brcmf_pcie_write_pcie32(devinfo, + BRCMF_PCIE_PCIE2REG_CONFIGDATA, + 0xffffffff); + } return 0; } @@ -906,33 +981,48 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo, static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo) { - brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, 0); + WRITE_ONCE(devinfo->irq_ready, false); + brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxmask, 0); } static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo) { - brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, - devinfo->reginfo->int_d2h_db | - devinfo->reginfo->int_fn0); + u32 mask = devinfo->reginfo->int_d2h_db | devinfo->reginfo->int_fn0; + + /* Publish initialized rings before accepting firmware MSIs. */ + smp_store_release(&devinfo->irq_ready, true); + brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxmask, mask); } static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo) { - if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1) - brcmf_pcie_write_reg32(devinfo, - devinfo->reginfo->h2d_mailbox_1, 1); + u32 reg; + + if (!(devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1)) + return; + + reg = devinfo->shared.flags & BRCMF_PCIE_SHARED_DAR ? + BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1 : + BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1; + brcmf_pcie_write_pcie32(devinfo, reg, 1); } static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg) { struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg; - if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint)) { - brcmf_pcie_intr_disable(devinfo); + if (brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint)) { + brcmf_pcie_write_pcie32(devinfo, + devinfo->reginfo->mailboxmask, 0); brcmf_dbg(PCIE, "Enter\n"); return IRQ_WAKE_THREAD; } + + /* mailboxint is cleared by the firmware in MSI mode */ + if (devinfo->have_msi) + return IRQ_WAKE_THREAD; + return IRQ_NONE; } @@ -942,23 +1032,28 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg) struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg; u32 status; + /* Pair with ring publication in brcmf_pcie_intr_enable(). */ + if (!smp_load_acquire(&devinfo->irq_ready)) + return IRQ_HANDLED; + devinfo->in_irq = true; - status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint); + status = brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint); brcmf_dbg(PCIE, "Enter %x\n", status); if (status) { - brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, - status); + brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxint, status); if (status & devinfo->reginfo->int_fn0) brcmf_pcie_handle_mb_data(devinfo); - if (status & devinfo->reginfo->int_d2h_db) { - if (devinfo->state == BRCMFMAC_PCIE_STATE_UP) - brcmf_proto_msgbuf_rx_trigger( - &devinfo->pdev->dev); - } + } + if (devinfo->have_msi || status & devinfo->reginfo->int_d2h_db) { + if (devinfo->state == BRCMFMAC_PCIE_STATE_UP) + brcmf_proto_msgbuf_rx_trigger(&devinfo->pdev->dev); } brcmf_pcie_bus_console_read(devinfo, false); - if (devinfo->state == BRCMFMAC_PCIE_STATE_UP) - brcmf_pcie_intr_enable(devinfo); + if (devinfo->state == BRCMFMAC_PCIE_STATE_UP && + READ_ONCE(devinfo->irq_ready)) + brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxmask, + devinfo->reginfo->int_d2h_db | + devinfo->reginfo->int_fn0); devinfo->in_irq = false; return IRQ_HANDLED; } @@ -973,11 +1068,13 @@ static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo) brcmf_dbg(PCIE, "Enter\n"); - pci_enable_msi(pdev); + devinfo->have_msi = pci_enable_msi(pdev) >= 0; if (request_threaded_irq(pdev->irq, brcmf_pcie_quick_check_isr, brcmf_pcie_isr_thread, IRQF_SHARED, "brcmf_pcie_intr", devinfo)) { - pci_disable_msi(pdev); + if (devinfo->have_msi) + pci_disable_msi(pdev); + devinfo->have_msi = false; brcmf_err(bus, "Failed to request IRQ %d\n", pdev->irq); return -EIO; } @@ -998,7 +1095,9 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo) brcmf_pcie_intr_disable(devinfo); free_irq(pdev->irq, devinfo); - pci_disable_msi(pdev); + if (devinfo->have_msi) + pci_disable_msi(pdev); + devinfo->have_msi = false; msleep(50); count = 0; @@ -1009,8 +1108,8 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo) if (devinfo->in_irq) brcmf_err(bus, "Still in IRQ (processing) !!!\n"); - status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint); - brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, status); + status = brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint); + brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxint, status); devinfo->irq_allocated = false; } @@ -1056,13 +1155,17 @@ static int brcmf_pcie_ring_mb_ring_bell(void *ctx) { struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx; struct brcmf_pciedev_info *devinfo = ring->devinfo; + u32 reg; if (devinfo->state != BRCMFMAC_PCIE_STATE_UP) return -EIO; brcmf_dbg(PCIE, "RING !\n"); + reg = devinfo->shared.flags & BRCMF_PCIE_SHARED_DAR ? + BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0 : + BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0; /* Any arbitrary value will do, lets use 1 */ - brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->h2d_mailbox_0, 1); + brcmf_pcie_write_pcie32(devinfo, reg, 1); return 0; } @@ -1892,9 +1995,9 @@ static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip) else reg = BRCMF_PCIE_PCIE2REG_MAILBOXINT; - val = brcmf_pcie_read_reg32(devinfo, reg); + val = brcmf_pcie_read_pcie32(devinfo, reg); if (val != 0xffffffff) - brcmf_pcie_write_reg32(devinfo, reg, val); + brcmf_pcie_write_pcie32(devinfo, reg, val); return 0; } @@ -2676,7 +2779,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev) brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus); /* Check if device is still up and running, if so we are ready */ - if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->intmask) != 0) { + if (brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->intmask) != 0) { brcmf_dbg(PCIE, "Try to wakeup device....\n"); if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM)) goto cleanup; diff --git a/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h b/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h index 0340bba968..641eff6b19 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h @@ -302,6 +302,11 @@ struct chipcregs { #define PMU_RCTL_LOGIC_DISABLE_MASK (1 << 27) +#define CC_WD_SSRESET_PCIE_F0_EN 0x10000000 +#define CC_WD_SSRESET_PCIE_ALL_FN_EN 0x80000000 +#define CC_WD_COUNTER_MASK 0x0fffffff +#define CC_WD_ENABLE_MASK 0xf0000000 + /* * Maximum delay for the PMU state transition in us. * This is an upper bound intended for spinwaits etc. -- 2.55.0