Skip to content

Commit 35c6c38

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 e094a80 commit 35c6c38

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
@@ -550,6 +550,19 @@ brcmf_pcie_write_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset,
550550
iowrite32(value, address);
551551
}
552552

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

554567
static u8
555568
brcmf_pcie_read_tcm8(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
@@ -774,14 +787,14 @@ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
774787
core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
775788
if (core->rev <= 13) {
776789
for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
777-
brcmf_pcie_write_reg32(devinfo,
790+
brcmf_pcie_write_pcie32(devinfo,
778791
BRCMF_PCIE_PCIE2REG_CONFIGADDR,
779792
cfg_offset[i]);
780-
val = brcmf_pcie_read_reg32(devinfo,
793+
val = brcmf_pcie_read_pcie32(devinfo,
781794
BRCMF_PCIE_PCIE2REG_CONFIGDATA);
782795
brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
783796
cfg_offset[i], val);
784-
brcmf_pcie_write_reg32(devinfo,
797+
brcmf_pcie_write_pcie32(devinfo,
785798
BRCMF_PCIE_PCIE2REG_CONFIGDATA,
786799
val);
787800
}
@@ -795,9 +808,9 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
795808

796809
/* BAR1 window may not be sized properly */
797810
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
798-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
799-
config = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
800-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
811+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
812+
config = brcmf_pcie_read_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
813+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
801814

802815
device_wakeup_enable(&devinfo->pdev->dev);
803816
}
@@ -1011,15 +1024,15 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,
10111024

10121025
static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
10131026
{
1014-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, 0);
1027+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxmask, 0);
10151028

10161029
devinfo->irq_ready = false;
10171030
}
10181031

10191032

10201033
static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
10211034
{
1022-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask,
1035+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxmask,
10231036
devinfo->reginfo->int_d2h_db |
10241037
devinfo->reginfo->int_fn0);
10251038

@@ -1030,17 +1043,17 @@ static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo)
10301043
{
10311044
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1) {
10321045
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_DAR)
1033-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1, 1);
1046+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1, 1);
10341047
else
1035-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
1048+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
10361049
}
10371050
}
10381051

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

1043-
if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint)) {
1056+
if (brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint)) {
10441057
brcmf_pcie_intr_disable(devinfo);
10451058
brcmf_dbg(PCIE, "Enter\n");
10461059
return IRQ_WAKE_THREAD;
@@ -1060,10 +1073,10 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
10601073
u32 status;
10611074

10621075
devinfo->in_irq = true;
1063-
status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
1076+
status = brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint);
10641077
brcmf_dbg(PCIE, "Enter %x\n", status);
10651078
if (status) {
1066-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint,
1079+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxint,
10671080
status);
10681081
if (status & devinfo->reginfo->int_fn0)
10691082
brcmf_pcie_poll_mb_data(devinfo);
@@ -1129,8 +1142,8 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
11291142
if (devinfo->in_irq)
11301143
brcmf_err(bus, "Still in IRQ (processing) !!!\n");
11311144

1132-
status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
1133-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, status);
1145+
status = brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint);
1146+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxint, status);
11341147

11351148
devinfo->irq_allocated = false;
11361149
}
@@ -1183,9 +1196,9 @@ static int brcmf_pcie_ring_mb_ring_bell(void *ctx)
11831196
brcmf_dbg(PCIE, "RING !\n");
11841197
/* Any arbitrary value will do, lets use 1 */
11851198
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_DAR)
1186-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0, 1);
1199+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0, 1);
11871200
else
1188-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
1201+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
11891202

11901203
return 0;
11911204
}
@@ -2180,9 +2193,9 @@ static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
21802193
else
21812194
reg = BRCMF_PCIE_PCIE2REG_MAILBOXINT;
21822195

2183-
val = brcmf_pcie_read_reg32(devinfo, reg);
2196+
val = brcmf_pcie_read_pcie32(devinfo, reg);
21842197
if (val != 0xffffffff)
2185-
brcmf_pcie_write_reg32(devinfo, reg, val);
2198+
brcmf_pcie_write_pcie32(devinfo, reg, val);
21862199

21872200
return 0;
21882201
}
@@ -2920,7 +2933,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
29202933
brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
29212934

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

0 commit comments

Comments
 (0)