Skip to content

Commit 41c1947

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 bdaac94 commit 41c1947

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)
@@ -776,14 +789,14 @@ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
776789
core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
777790
if (core->rev <= 13) {
778791
for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
779-
brcmf_pcie_write_reg32(devinfo,
792+
brcmf_pcie_write_pcie32(devinfo,
780793
BRCMF_PCIE_PCIE2REG_CONFIGADDR,
781794
cfg_offset[i]);
782-
val = brcmf_pcie_read_reg32(devinfo,
795+
val = brcmf_pcie_read_pcie32(devinfo,
783796
BRCMF_PCIE_PCIE2REG_CONFIGDATA);
784797
brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
785798
cfg_offset[i], val);
786-
brcmf_pcie_write_reg32(devinfo,
799+
brcmf_pcie_write_pcie32(devinfo,
787800
BRCMF_PCIE_PCIE2REG_CONFIGDATA,
788801
val);
789802
}
@@ -797,9 +810,9 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
797810

798811
/* BAR1 window may not be sized properly */
799812
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
800-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
801-
config = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
802-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
813+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
814+
config = brcmf_pcie_read_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
815+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
803816

804817
device_wakeup_enable(&devinfo->pdev->dev);
805818
}
@@ -1013,15 +1026,15 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,
10131026

10141027
static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
10151028
{
1016-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, 0);
1029+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxmask, 0);
10171030

10181031
devinfo->irq_ready = false;
10191032
}
10201033

10211034

10221035
static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
10231036
{
1024-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask,
1037+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxmask,
10251038
devinfo->reginfo->int_d2h_db |
10261039
devinfo->reginfo->int_fn0);
10271040

@@ -1032,17 +1045,17 @@ static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo)
10321045
{
10331046
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1) {
10341047
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_DAR)
1035-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1, 1);
1048+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1, 1);
10361049
else
1037-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
1050+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
10381051
}
10391052
}
10401053

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

1045-
if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint)) {
1058+
if (brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint)) {
10461059
brcmf_pcie_intr_disable(devinfo);
10471060
brcmf_dbg(PCIE, "Enter\n");
10481061
return IRQ_WAKE_THREAD;
@@ -1062,10 +1075,10 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
10621075
u32 status;
10631076

10641077
devinfo->in_irq = true;
1065-
status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
1078+
status = brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint);
10661079
brcmf_dbg(PCIE, "Enter %x\n", status);
10671080
if (status) {
1068-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint,
1081+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxint,
10691082
status);
10701083
if (status & devinfo->reginfo->int_fn0)
10711084
brcmf_pcie_poll_mb_data(devinfo);
@@ -1131,8 +1144,8 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
11311144
if (devinfo->in_irq)
11321145
brcmf_err(bus, "Still in IRQ (processing) !!!\n");
11331146

1134-
status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
1135-
brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, status);
1147+
status = brcmf_pcie_read_pcie32(devinfo, devinfo->reginfo->mailboxint);
1148+
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxint, status);
11361149

11371150
devinfo->irq_allocated = false;
11381151
}
@@ -1185,9 +1198,9 @@ static int brcmf_pcie_ring_mb_ring_bell(void *ctx)
11851198
brcmf_dbg(PCIE, "RING !\n");
11861199
/* Any arbitrary value will do, lets use 1 */
11871200
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_DAR)
1188-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0, 1);
1201+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0, 1);
11891202
else
1190-
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
1203+
brcmf_pcie_write_pcie32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
11911204

11921205
return 0;
11931206
}
@@ -2182,9 +2195,9 @@ static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
21822195
else
21832196
reg = BRCMF_PCIE_PCIE2REG_MAILBOXINT;
21842197

2185-
val = brcmf_pcie_read_reg32(devinfo, reg);
2198+
val = brcmf_pcie_read_pcie32(devinfo, reg);
21862199
if (val != 0xffffffff)
2187-
brcmf_pcie_write_reg32(devinfo, reg, val);
2200+
brcmf_pcie_write_pcie32(devinfo, reg, val);
21882201

21892202
return 0;
21902203
}
@@ -2967,7 +2980,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
29672980
brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
29682981

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

0 commit comments

Comments
 (0)