Skip to content

Commit

Permalink
Merge branch 'ipa-cleanups'
Browse files Browse the repository at this point in the history
Alex Elder says:

====================
net: ipa: some more cleanup

Version 3 of this series uses dev_err_probe() in the second patch,
as suggested by Heiner Kallweit.

Version 2 was sent to ensure the series was based on current
net-next/master, and added copyright updates to files touched.

The original introduction is below.

This is another fairly innocuous set of cleanup patches.

The first was motivated by a bug found that would affect IPA v4.5.
It maintain a new GSI address pointer; one is the "raw" (original
mapped) address, and the other will have been adjusted if necessary
for use on newer platforms.

The second just quiets some unnecessary noise during early probe.

The third fixes some errors that show up when IPA_VALIDATION is
enabled.

The last two just create helper functions to improve readability.

====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 13, 2021
2 parents 21cc70c + 6170b6d commit 4b47ad0
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 54 deletions.
50 changes: 26 additions & 24 deletions drivers/net/ipa/gsi.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0

/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2018-2020 Linaro Ltd.
* Copyright (C) 2018-2021 Linaro Ltd.
*/

#include <linux/types.h>
Expand Down Expand Up @@ -175,6 +175,12 @@ static u32 gsi_channel_id(struct gsi_channel *channel)
return channel - &channel->gsi->channel[0];
}

/* An initialized channel has a non-null GSI pointer */
static bool gsi_channel_initialized(struct gsi_channel *channel)
{
return !!channel->gsi;
}

/* Update the GSI IRQ type register with the cached value */
static void gsi_irq_type_update(struct gsi *gsi, u32 val)
{
Expand All @@ -195,8 +201,6 @@ static void gsi_irq_type_disable(struct gsi *gsi, enum gsi_irq_type_id type_id)
/* Turn off all GSI interrupts initially */
static void gsi_irq_setup(struct gsi *gsi)
{
u32 adjust;

/* Disable all interrupt types */
gsi_irq_type_update(gsi, 0);

Expand All @@ -206,10 +210,9 @@ static void gsi_irq_setup(struct gsi *gsi)
iowrite32(0, gsi->virt + GSI_CNTXT_GLOB_IRQ_EN_OFFSET);
iowrite32(0, gsi->virt + GSI_CNTXT_SRC_IEOB_IRQ_MSK_OFFSET);

/* Reverse the offset adjustment for inter-EE register offsets */
adjust = gsi->version < IPA_VERSION_4_5 ? 0 : GSI_EE_REG_ADJUST;
iowrite32(0, gsi->virt + adjust + GSI_INTER_EE_SRC_CH_IRQ_OFFSET);
iowrite32(0, gsi->virt + adjust + GSI_INTER_EE_SRC_EV_CH_IRQ_OFFSET);
/* The inter-EE registers are in the non-adjusted address range */
iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_CH_IRQ_OFFSET);
iowrite32(0, gsi->virt_raw + GSI_INTER_EE_SRC_EV_CH_IRQ_OFFSET);

iowrite32(0, gsi->virt + GSI_CNTXT_GSI_IRQ_EN_OFFSET);
}
Expand Down Expand Up @@ -1641,8 +1644,8 @@ static int gsi_channel_setup_one(struct gsi *gsi, u32 channel_id)
u32 evt_ring_id = channel->evt_ring_id;
int ret;

if (!channel->gsi)
return 0; /* Ignore uninitialized channels */
if (!gsi_channel_initialized(channel))
return 0;

ret = gsi_evt_ring_alloc_command(gsi, evt_ring_id);
if (ret)
Expand Down Expand Up @@ -1678,8 +1681,8 @@ static void gsi_channel_teardown_one(struct gsi *gsi, u32 channel_id)
struct gsi_channel *channel = &gsi->channel[channel_id];
u32 evt_ring_id = channel->evt_ring_id;

if (!channel->gsi)
return; /* Ignore uninitialized channels */
if (!gsi_channel_initialized(channel))
return;

netif_napi_del(&channel->napi);

Expand Down Expand Up @@ -1773,8 +1776,8 @@ static int gsi_channel_setup(struct gsi *gsi)
while (channel_id < GSI_CHANNEL_COUNT_MAX) {
struct gsi_channel *channel = &gsi->channel[channel_id++];

if (!channel->gsi)
continue; /* Ignore uninitialized channels */
if (!gsi_channel_initialized(channel))
continue;

ret = -EINVAL;
dev_err(gsi->dev, "channel %u not supported by hardware\n",
Expand Down Expand Up @@ -2092,8 +2095,8 @@ static int gsi_channel_init_one(struct gsi *gsi,
/* Inverse of gsi_channel_init_one() */
static void gsi_channel_exit_one(struct gsi_channel *channel)
{
if (!channel->gsi)
return; /* Ignore uninitialized channels */
if (!gsi_channel_initialized(channel))
return;

if (channel->command)
ipa_cmd_pool_exit(channel);
Expand Down Expand Up @@ -2181,9 +2184,8 @@ int gsi_init(struct gsi *gsi, struct platform_device *pdev,
gsi->dev = dev;
gsi->version = version;

/* The GSI layer performs NAPI on all endpoints. NAPI requires a
* network device structure, but the GSI layer does not have one,
* so we must create a dummy network device for this purpose.
/* GSI uses NAPI on all channels. Create a dummy network device
* for the channel NAPI contexts to be associated with.
*/
init_dummy_netdev(&gsi->dummy_dev);

Expand All @@ -2208,13 +2210,13 @@ int gsi_init(struct gsi *gsi, struct platform_device *pdev,
return -EINVAL;
}

gsi->virt = ioremap(res->start, size);
if (!gsi->virt) {
gsi->virt_raw = ioremap(res->start, size);
if (!gsi->virt_raw) {
dev_err(dev, "unable to remap \"gsi\" memory\n");
return -ENOMEM;
}
/* Adjust register range pointer downward for newer IPA versions */
gsi->virt -= adjust;
/* Most registers are accessed using an adjusted register range */
gsi->virt = gsi->virt_raw - adjust;

init_completion(&gsi->completion);

Expand All @@ -2233,7 +2235,7 @@ int gsi_init(struct gsi *gsi, struct platform_device *pdev,
err_irq_exit:
gsi_irq_exit(gsi);
err_iounmap:
iounmap(gsi->virt);
iounmap(gsi->virt_raw);

return ret;
}
Expand All @@ -2244,7 +2246,7 @@ void gsi_exit(struct gsi *gsi)
mutex_destroy(&gsi->mutex);
gsi_channel_exit(gsi);
gsi_irq_exit(gsi);
iounmap(gsi->virt);
iounmap(gsi->virt_raw);
}

/* The maximum number of outstanding TREs on a channel. This limits
Expand Down
5 changes: 3 additions & 2 deletions drivers/net/ipa/gsi.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */

/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2018-2020 Linaro Ltd.
* Copyright (C) 2018-2021 Linaro Ltd.
*/
#ifndef _GSI_H_
#define _GSI_H_
Expand Down Expand Up @@ -149,7 +149,8 @@ struct gsi {
struct device *dev; /* Same as IPA device */
enum ipa_version version;
struct net_device dummy_dev; /* needed for NAPI */
void __iomem *virt;
void __iomem *virt_raw; /* I/O mapped address range */
void __iomem *virt; /* Adjusted for most registers */
u32 irq;
u32 channel_count;
u32 evt_ring_count;
Expand Down
21 changes: 13 additions & 8 deletions drivers/net/ipa/gsi_reg.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */

/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2018-2020 Linaro Ltd.
* Copyright (C) 2018-2021 Linaro Ltd.
*/
#ifndef _GSI_REG_H_
#define _GSI_REG_H_
Expand Down Expand Up @@ -38,17 +38,21 @@
* (though the actual limit is hardware-dependent).
*/

/* GSI EE registers as a group are shifted downward by a fixed
* constant amount for IPA versions 4.5 and beyond. This applies
* to all GSI registers we use *except* the ones that disable
* inter-EE interrupts for channels and event channels.
/* GSI EE registers as a group are shifted downward by a fixed constant amount
* for IPA versions 4.5 and beyond. This applies to all GSI registers we use
* *except* the ones that disable inter-EE interrupts for channels and event
* channels.
*
* We handle this by adjusting the pointer to the mapped GSI memory
* region downward. Then in the one place we use them (gsi_irq_setup())
* we undo that adjustment for the inter-EE interrupt registers.
* The "raw" (not adjusted) GSI register range is mapped, and a pointer to
* the mapped range is held in gsi->virt_raw. The inter-EE interrupt
* registers are accessed using that pointer.
*
* Most registers are accessed using gsi->virt, which is a copy of the "raw"
* pointer, adjusted downward by the fixed amount.
*/
#define GSI_EE_REG_ADJUST 0x0000d000 /* IPA v4.5+ */

/* The two inter-EE IRQ register offsets are relative to gsi->virt_raw */
#define GSI_INTER_EE_SRC_CH_IRQ_OFFSET \
GSI_INTER_EE_N_SRC_CH_IRQ_OFFSET(GSI_EE_AP)
#define GSI_INTER_EE_N_SRC_CH_IRQ_OFFSET(ee) \
Expand All @@ -59,6 +63,7 @@
#define GSI_INTER_EE_N_SRC_EV_CH_IRQ_OFFSET(ee) \
(0x0000c01c + 0x1000 * (ee))

/* All other register offsets are relative to gsi->virt */
#define GSI_CH_C_CNTXT_0_OFFSET(ch) \
GSI_EE_N_CH_C_CNTXT_0_OFFSET((ch), GSI_EE_AP)
#define GSI_EE_N_CH_C_CNTXT_0_OFFSET(ch, ee) \
Expand Down
9 changes: 5 additions & 4 deletions drivers/net/ipa/ipa_clock.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0

/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2018-2020 Linaro Ltd.
* Copyright (C) 2018-2021 Linaro Ltd.
*/

#include <linux/refcount.h>
Expand Down Expand Up @@ -68,8 +68,8 @@ static int ipa_interconnect_init_one(struct device *dev,
if (IS_ERR(path)) {
int ret = PTR_ERR(path);

dev_err(dev, "error %d getting %s interconnect\n", ret,
data->name);
dev_err_probe(dev, ret, "error getting %s interconnect\n",
data->name);

return ret;
}
Expand Down Expand Up @@ -281,7 +281,8 @@ ipa_clock_init(struct device *dev, const struct ipa_clock_data *data)

clk = clk_get(dev, "core");
if (IS_ERR(clk)) {
dev_err(dev, "error %ld getting core clock\n", PTR_ERR(clk));
dev_err_probe(dev, PTR_ERR(clk), "error getting core clock\n");

return ERR_CAST(clk);
}

Expand Down
32 changes: 24 additions & 8 deletions drivers/net/ipa/ipa_cmd.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0

/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2019-2020 Linaro Ltd.
* Copyright (C) 2019-2021 Linaro Ltd.
*/

#include <linux/types.h>
Expand Down Expand Up @@ -244,11 +244,15 @@ static bool ipa_cmd_register_write_offset_valid(struct ipa *ipa,
if (ipa->version != IPA_VERSION_3_5_1)
bit_count += hweight32(REGISTER_WRITE_FLAGS_OFFSET_HIGH_FMASK);
BUILD_BUG_ON(bit_count > 32);
offset_max = ~0 >> (32 - bit_count);
offset_max = ~0U >> (32 - bit_count);

/* Make sure the offset can be represented by the field(s)
* that holds it. Also make sure the offset is not outside
* the overall IPA memory range.
*/
if (offset > offset_max || ipa->mem_offset > offset_max - offset) {
dev_err(dev, "%s offset too large 0x%04x + 0x%04x > 0x%04x)\n",
ipa->mem_offset + offset, offset_max);
name, ipa->mem_offset, offset, offset_max);
return false;
}

Expand All @@ -261,12 +265,24 @@ static bool ipa_cmd_register_write_valid(struct ipa *ipa)
const char *name;
u32 offset;

offset = ipa_reg_filt_rout_hash_flush_offset(ipa->version);
name = "filter/route hash flush";
if (!ipa_cmd_register_write_offset_valid(ipa, name, offset))
return false;
/* If hashed tables are supported, ensure the hash flush register
* offset will fit in a register write IPA immediate command.
*/
if (ipa_table_hash_support(ipa)) {
offset = ipa_reg_filt_rout_hash_flush_offset(ipa->version);
name = "filter/route hash flush";
if (!ipa_cmd_register_write_offset_valid(ipa, name, offset))
return false;
}

offset = IPA_REG_ENDP_STATUS_N_OFFSET(IPA_ENDPOINT_COUNT);
/* Each endpoint can have a status endpoint associated with it,
* and this is recorded in an endpoint register. If the modem
* crashes, we reset the status endpoint for all modem endpoints
* using a register write IPA immediate command. Make sure the
* worst case (highest endpoint number) offset of that endpoint
* fits in the register write command field(s) that must hold it.
*/
offset = IPA_REG_ENDP_STATUS_N_OFFSET(IPA_ENDPOINT_COUNT - 1);
name = "maximal endpoint status";
if (!ipa_cmd_register_write_offset_valid(ipa, name, offset))
return false;
Expand Down
16 changes: 9 additions & 7 deletions drivers/net/ipa/ipa_table.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0

/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2018-2020 Linaro Ltd.
* Copyright (C) 2018-2021 Linaro Ltd.
*/

#include <linux/types.h>
Expand Down Expand Up @@ -239,6 +239,11 @@ static void ipa_table_validate_build(void)

#endif /* !IPA_VALIDATE */

bool ipa_table_hash_support(struct ipa *ipa)
{
return ipa->version != IPA_VERSION_4_2;
}

/* Zero entry count means no table, so just return a 0 address */
static dma_addr_t ipa_table_addr(struct ipa *ipa, bool filter_mask, u16 count)
{
Expand Down Expand Up @@ -412,8 +417,7 @@ int ipa_table_hash_flush(struct ipa *ipa)
struct gsi_trans *trans;
u32 val;

/* IPA version 4.2 does not support hashed tables */
if (ipa->version == IPA_VERSION_4_2)
if (!ipa_table_hash_support(ipa))
return 0;

trans = ipa_cmd_trans_alloc(ipa, 1);
Expand Down Expand Up @@ -531,8 +535,7 @@ static void ipa_filter_config(struct ipa *ipa, bool modem)
enum gsi_ee_id ee_id = modem ? GSI_EE_MODEM : GSI_EE_AP;
u32 ep_mask = ipa->filter_map;

/* IPA version 4.2 has no hashed route tables */
if (ipa->version == IPA_VERSION_4_2)
if (!ipa_table_hash_support(ipa))
return;

while (ep_mask) {
Expand Down Expand Up @@ -582,8 +585,7 @@ static void ipa_route_config(struct ipa *ipa, bool modem)
{
u32 route_id;

/* IPA version 4.2 has no hashed route tables */
if (ipa->version == IPA_VERSION_4_2)
if (!ipa_table_hash_support(ipa))
return;

for (route_id = 0; route_id < IPA_ROUTE_COUNT_MAX; route_id++)
Expand Down
8 changes: 7 additions & 1 deletion drivers/net/ipa/ipa_table.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */

/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2019-2020 Linaro Ltd.
* Copyright (C) 2019-2021 Linaro Ltd.
*/
#ifndef _IPA_TABLE_H_
#define _IPA_TABLE_H_
Expand Down Expand Up @@ -51,6 +51,12 @@ static inline bool ipa_filter_map_valid(struct ipa *ipa, u32 filter_mask)

#endif /* !IPA_VALIDATE */

/**
* ipa_table_hash_support() - Return true if hashed tables are supported
* @ipa: IPA pointer
*/
bool ipa_table_hash_support(struct ipa *ipa);

/**
* ipa_table_reset() - Reset filter and route tables entries to "none"
* @ipa: IPA pointer
Expand Down

0 comments on commit 4b47ad0

Please sign in to comment.