Skip to content

Commit 8f3fd8f

Browse files
marcanjannau
authored andcommitted
wifi: brcmfmac: pcie: Access pcie core registers via dedicated window
Currently the pcie code multiplexes all register accesses through a single window. This isn't very efficient, and it creates race conditions when we access registers from multiple paths (e.g. in the interrupt handler). Since the chip has a dedicated window for the PCIe core registers, we can use that instead, avoid all the gratuitous window switching, and fix the IRQ race issues. Signed-off-by: Hector Martin <marcan@marcan.st>
1 parent 3efe848 commit 8f3fd8f

1 file changed

Lines changed: 33 additions & 20 deletions

File tree

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

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

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,19 @@ brcmf_pcie_write_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset,
548548
iowrite32(value, address);
549549
}
550550

551+
static u32
552+
brcmf_pcie_read_pcie32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
553+
{
554+
return brcmf_pcie_read_reg32(devinfo, 0x2000 + reg_offset);
555+
}
556+
557+
558+
static void
559+
brcmf_pcie_write_pcie32(struct brcmf_pciedev_info *devinfo, u32 reg_offset,
560+
u32 value)
561+
{
562+
brcmf_pcie_write_reg32(devinfo, 0x2000 + reg_offset, value);
563+
}
551564

552565
static u8
553566
brcmf_pcie_read_tcm8(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
@@ -772,14 +785,14 @@ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
772785
core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
773786
if (core->rev <= 13) {
774787
for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
775-
brcmf_pcie_write_reg32(devinfo,
788+
brcmf_pcie_write_pcie32(devinfo,
776789
BRCMF_PCIE_PCIE2REG_CONFIGADDR,
777790
cfg_offset[i]);
778-
val = brcmf_pcie_read_reg32(devinfo,
791+
val = brcmf_pcie_read_pcie32(devinfo,
779792
BRCMF_PCIE_PCIE2REG_CONFIGDATA);
780793
brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
781794
cfg_offset[i], val);
782-
brcmf_pcie_write_reg32(devinfo,
795+
brcmf_pcie_write_pcie32(devinfo,
783796
BRCMF_PCIE_PCIE2REG_CONFIGDATA,
784797
val);
785798
}
@@ -793,9 +806,9 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
793806

794807
/* BAR1 window may not be sized properly */
795808
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
796-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
797-
config = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
798-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
809+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
810+
config = brcmf_pcie_read_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
811+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
799812

800813
device_wakeup_enable(&devinfo->pdev->dev);
801814
}
@@ -1009,15 +1022,15 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,
10091022

10101023
static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
10111024
{
1012-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, 0);
1025+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxmask, 0);
10131026

10141027
devinfo->irq_ready = false;
10151028
}
10161029

10171030

10181031
static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
10191032
{
1020-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask,
1033+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxmask,
10211034
devinfo->reginfo->int_d2h_db |
10221035
devinfo->reginfo->int_fn0);
10231036

@@ -1028,17 +1041,17 @@ static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo)
10281041
{
10291042
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1) {
10301043
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_DAR)
1031-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1, 1);
1044+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1, 1);
10321045
else
1033-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
1046+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
10341047
}
10351048
}
10361049

10371050
static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg)
10381051
{
10391052
struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
10401053

1041-
if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint)) {
1054+
if (brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint)) {
10421055
brcmf_pcie_intr_disable(devinfo);
10431056
brcmf_dbg(PCIE, "Enter\n");
10441057
return IRQ_WAKE_THREAD;
@@ -1058,10 +1071,10 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
10581071
u32 status;
10591072

10601073
devinfo->in_irq = true;
1061-
status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
1074+
status = brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint);
10621075
brcmf_dbg(PCIE, "Enter %x\n", status);
10631076
if (status) {
1064-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint,
1077+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxint,
10651078
status);
10661079
if (status & devinfo->reginfo->int_fn0)
10671080
brcmf_pcie_poll_mb_data(devinfo);
@@ -1127,8 +1140,8 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
11271140
if (devinfo->in_irq)
11281141
brcmf_err(bus, "Still in IRQ (processing) !!!\n");
11291142

1130-
status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
1131-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, status);
1143+
status = brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint);
1144+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxint, status);
11321145

11331146
devinfo->irq_allocated = false;
11341147
}
@@ -1181,9 +1194,9 @@ static int brcmf_pcie_ring_mb_ring_bell(void *ctx)
11811194
brcmf_dbg(PCIE, "RING !\n");
11821195
/* Any arbitrary value will do, lets use 1 */
11831196
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_DAR)
1184-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0, 1);
1197+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0, 1);
11851198
else
1186-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
1199+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
11871200

11881201
return 0;
11891202
}
@@ -2178,9 +2191,9 @@ static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
21782191
else
21792192
reg = BRCMF_PCIE_PCIE2REG_MAILBOXINT;
21802193

2181-
val = brcmf_pcie_read_reg32(devinfo, reg);
2194+
val = brcmf_pcie_read_pcie32(devinfo, reg);
21822195
if (val != 0xffffffff)
2183-
brcmf_pcie_write_reg32(devinfo, reg, val);
2196+
brcmf_pcie_write_pcie32(devinfo, reg, val);
21842197

21852198
return 0;
21862199
}
@@ -2954,7 +2967,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
29542967
brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
29552968

29562969
/* Check if device is still up and running, if so we are ready */
2957-
if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->intmask) != 0) {
2970+
if (brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->intmask) != 0) {
29582971
brcmf_dbg(PCIE, "Try to wakeup device....\n");
29592972
/* Set the device up, so we can write the MB data message in ring mode */
29602973
devinfo->state = BRCMFMAC_PCIE_STATE_UP;

0 commit comments

Comments
 (0)