diff options
author | Alex Elder <elder@linaro.org> | 2020-11-05 12:13:59 -0600 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2020-11-07 15:39:16 -0800 |
commit | 97eb94c8c79059966cedd66312e004c6070033f6 (patch) | |
tree | 96082a083a1567f7010e4881674a4fb389eba2cc /drivers | |
parent | f9b28804ab50eb951c50f4c5afec77ab0435309a (diff) |
net: ipa: disable all GSI interrupt types initially
Introduce gsi_irq_setup() and gsi_irq_teardown() to disable all
GSI interrupts when first setting up GSI hardware, and to clean
things up when we're done.
Re-enable all GSI interrupt types in gsi_irq_enable(), but do
so only after each of the type-specific interrupt masks has
been configured. Similarly, disable all interrupt types in
gsi_irq_disable()--first--before zeroing out the type-specific
masks.
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ipa/gsi.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c index da5204268df2..669d7496f8bd 100644 --- a/drivers/net/ipa/gsi.c +++ b/drivers/net/ipa/gsi.c @@ -230,6 +230,18 @@ static u32 gsi_channel_id(struct gsi_channel *channel) return channel - &channel->gsi->channel[0]; } +/* Turn off all GSI interrupts initially */ +static void gsi_irq_setup(struct gsi *gsi) +{ + iowrite32(0, gsi->virt + GSI_CNTXT_TYPE_IRQ_MSK_OFFSET); +} + +/* Turn off all GSI interrupts when we're all done */ +static void gsi_irq_teardown(struct gsi *gsi) +{ + iowrite32(0, gsi->virt + GSI_CNTXT_TYPE_IRQ_MSK_OFFSET); +} + static void gsi_irq_ieob_enable(struct gsi *gsi, u32 evt_ring_id) { u32 val; @@ -253,14 +265,6 @@ static void gsi_irq_enable(struct gsi *gsi) { u32 val; - val = BIT(GSI_CH_CTRL); - val |= BIT(GSI_EV_CTRL); - val |= BIT(GSI_GLOB_EE); - val |= BIT(GSI_IEOB); - /* We don't use inter-EE channel or event control interrupts */ - val |= BIT(GSI_GENERAL); - iowrite32(val, gsi->virt + GSI_CNTXT_TYPE_IRQ_MSK_OFFSET); - val = GENMASK(gsi->channel_count - 1, 0); iowrite32(val, gsi->virt + GSI_CNTXT_SRC_CH_IRQ_MSK_OFFSET); @@ -276,17 +280,27 @@ static void gsi_irq_enable(struct gsi *gsi) /* Never enable GSI_BREAK_POINT */ val = GSI_CNTXT_GSI_IRQ_ALL & ~BREAK_POINT_FMASK; iowrite32(val, gsi->virt + GSI_CNTXT_GSI_IRQ_EN_OFFSET); + + /* Finally enable the interrupt types we use */ + val = BIT(GSI_CH_CTRL); + val |= BIT(GSI_EV_CTRL); + val |= BIT(GSI_GLOB_EE); + val |= BIT(GSI_IEOB); + /* We don't use inter-EE channel or event interrupts */ + val |= BIT(GSI_GENERAL); + iowrite32(val, gsi->virt + GSI_CNTXT_TYPE_IRQ_MSK_OFFSET); } /* Disable all GSI_interrupt types */ static void gsi_irq_disable(struct gsi *gsi) { + iowrite32(0, gsi->virt + GSI_CNTXT_TYPE_IRQ_MSK_OFFSET); + iowrite32(0, gsi->virt + GSI_CNTXT_GSI_IRQ_EN_OFFSET); iowrite32(0, gsi->virt + GSI_CNTXT_GLOB_IRQ_EN_OFFSET); iowrite32(0, gsi->virt + GSI_CNTXT_SRC_IEOB_IRQ_MSK_OFFSET); iowrite32(0, gsi->virt + GSI_CNTXT_SRC_EV_CH_IRQ_MSK_OFFSET); iowrite32(0, gsi->virt + GSI_CNTXT_SRC_CH_IRQ_MSK_OFFSET); - iowrite32(0, gsi->virt + GSI_CNTXT_TYPE_IRQ_MSK_OFFSET); } /* Return the virtual address associated with a ring index */ @@ -1683,6 +1697,7 @@ int gsi_setup(struct gsi *gsi) { struct device *dev = gsi->dev; u32 val; + int ret; /* Here is where we first touch the GSI hardware */ val = ioread32(gsi->virt + GSI_GSI_STATUS_OFFSET); @@ -1691,6 +1706,8 @@ int gsi_setup(struct gsi *gsi) return -EIO; } + gsi_irq_setup(gsi); + val = ioread32(gsi->virt + GSI_GSI_HW_PARAM_2_OFFSET); gsi->channel_count = u32_get_bits(val, NUM_CH_PER_EE_FMASK); @@ -1723,13 +1740,18 @@ int gsi_setup(struct gsi *gsi) /* Writing 1 indicates IRQ interrupts; 0 would be MSI */ iowrite32(1, gsi->virt + GSI_CNTXT_INTSET_OFFSET); - return gsi_channel_setup(gsi); + ret = gsi_channel_setup(gsi); + if (ret) + gsi_irq_teardown(gsi); + + return ret; } /* Inverse of gsi_setup() */ void gsi_teardown(struct gsi *gsi) { gsi_channel_teardown(gsi); + gsi_irq_teardown(gsi); } /* Initialize a channel's event ring */ |