Skip to content

Commit 91eb196

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 e766c78 commit 91eb196

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
@@ -545,6 +545,19 @@ brcmf_pcie_write_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset,
545545
iowrite32(value, address);
546546
}
547547

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

549562
static u8
550563
brcmf_pcie_read_tcm8(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
@@ -769,14 +782,14 @@ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
769782
core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
770783
if (core->rev <= 13) {
771784
for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
772-
brcmf_pcie_write_reg32(devinfo,
785+
brcmf_pcie_write_pcie32(devinfo,
773786
BRCMF_PCIE_PCIE2REG_CONFIGADDR,
774787
cfg_offset[i]);
775-
val = brcmf_pcie_read_reg32(devinfo,
788+
val = brcmf_pcie_read_pcie32(devinfo,
776789
BRCMF_PCIE_PCIE2REG_CONFIGDATA);
777790
brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
778791
cfg_offset[i], val);
779-
brcmf_pcie_write_reg32(devinfo,
792+
brcmf_pcie_write_pcie32(devinfo,
780793
BRCMF_PCIE_PCIE2REG_CONFIGDATA,
781794
val);
782795
}
@@ -790,9 +803,9 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
790803

791804
/* BAR1 window may not be sized properly */
792805
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
793-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
794-
config = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
795-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
806+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
807+
config = brcmf_pcie_read_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
808+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
796809

797810
device_wakeup_enable(&devinfo->pdev->dev);
798811
}
@@ -1006,15 +1019,15 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,
10061019

10071020
static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
10081021
{
1009-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, 0);
1022+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxmask, 0);
10101023

10111024
devinfo->irq_ready = false;
10121025
}
10131026

10141027

10151028
static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
10161029
{
1017-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask,
1030+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxmask,
10181031
devinfo->reginfo->int_d2h_db |
10191032
devinfo->reginfo->int_fn0);
10201033

@@ -1025,17 +1038,17 @@ static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo)
10251038
{
10261039
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1) {
10271040
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_DAR)
1028-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1, 1);
1041+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1, 1);
10291042
else
1030-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
1043+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
10311044
}
10321045
}
10331046

10341047
static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg)
10351048
{
10361049
struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
10371050

1038-
if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint)) {
1051+
if (brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint)) {
10391052
brcmf_pcie_intr_disable(devinfo);
10401053
brcmf_dbg(PCIE, "Enter\n");
10411054
return IRQ_WAKE_THREAD;
@@ -1055,10 +1068,10 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
10551068
u32 status;
10561069

10571070
devinfo->in_irq = true;
1058-
status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
1071+
status = brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint);
10591072
brcmf_dbg(PCIE, "Enter %x\n", status);
10601073
if (status) {
1061-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint,
1074+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxint,
10621075
status);
10631076
if (status & devinfo->reginfo->int_fn0)
10641077
brcmf_pcie_poll_mb_data(devinfo);
@@ -1124,8 +1137,8 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
11241137
if (devinfo->in_irq)
11251138
brcmf_err(bus, "Still in IRQ (processing) !!!\n");
11261139

1127-
status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
1128-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, status);
1140+
status = brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint);
1141+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxint, status);
11291142

11301143
devinfo->irq_allocated = false;
11311144
}
@@ -1178,9 +1191,9 @@ static int brcmf_pcie_ring_mb_ring_bell(void *ctx)
11781191
brcmf_dbg(PCIE, "RING !\n");
11791192
/* Any arbitrary value will do, lets use 1 */
11801193
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_DAR)
1181-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0, 1);
1194+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0, 1);
11821195
else
1183-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
1196+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
11841197

11851198
return 0;
11861199
}
@@ -2175,9 +2188,9 @@ static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
21752188
else
21762189
reg = BRCMF_PCIE_PCIE2REG_MAILBOXINT;
21772190

2178-
val = brcmf_pcie_read_reg32(devinfo, reg);
2191+
val = brcmf_pcie_read_pcie32(devinfo, reg);
21792192
if (val != 0xffffffff)
2180-
brcmf_pcie_write_reg32(devinfo, reg, val);
2193+
brcmf_pcie_write_pcie32(devinfo, reg, val);
21812194

21822195
return 0;
21832196
}
@@ -2915,7 +2928,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
29152928
brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
29162929

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

0 commit comments

Comments
 (0)