Skip to content

Commit dd25cfa

Browse files
committed
Merge branch 'net-ipa-remaining-ipa-v5-0-support'
Alex Elder says: ==================== net: ipa: remaining IPA v5.0 support This series includes almost all remaining IPA code changes required to support IPA v5.0. IPA register definitions and configuration data for IPA v5.0 will be sent later (soon). Note that the GSI register definitions still require work. GSI for IPA v5.0 supports up to 256 (rather than 32) channels, and this changes the way GSI register offsets are calculated. A few GSI register fields also change. The first patch in this series increases the number of IPA endpoints supported by the driver, from 32 to 36. The next updates the width of the destination field for the IP_PACKET_INIT immediate command so it can represent up to 256 endpoints rather than just 32. The next adds a few definitions of some IPA registers and fields that are first available in IPA v5.0. The next two patches update the code that handles router and filter table caches. Previously these were referred to as "hashed" tables, and the IPv4 and IPv6 tables are now combined into one "unified" table. The sixth and seventh patches add support for a new pulse generator, which allows time periods to be specified with a wider range of clock resolution. And the last patch just defines two new memory regions that were not previously used. ==================== Link: https://lore.kernel.org/r/20230130210158.4126129-1-elder@linaro.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 71af6a2 + 5157d6b commit dd25cfa

File tree

8 files changed

+192
-90
lines changed

8 files changed

+192
-90
lines changed

drivers/net/ipa/ipa_cmd.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0
22

33
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
4-
* Copyright (C) 2019-2022 Linaro Ltd.
4+
* Copyright (C) 2019-2023 Linaro Ltd.
55
*/
66

77
#include <linux/types.h>
@@ -94,11 +94,11 @@ struct ipa_cmd_register_write {
9494
/* IPA_CMD_IP_PACKET_INIT */
9595

9696
struct ipa_cmd_ip_packet_init {
97-
u8 dest_endpoint;
97+
u8 dest_endpoint; /* Full 8 bits used for IPA v5.0+ */
9898
u8 reserved[7];
9999
};
100100

101-
/* Field masks for ipa_cmd_ip_packet_init dest_endpoint field */
101+
/* Field mask for ipa_cmd_ip_packet_init dest_endpoint field (unused v5.0+) */
102102
#define IPA_PACKET_INIT_DEST_ENDPOINT_FMASK GENMASK(4, 0)
103103

104104
/* IPA_CMD_DMA_SHARED_MEM */
@@ -157,9 +157,14 @@ static void ipa_cmd_validate_build(void)
157157
BUILD_BUG_ON(field_max(IP_FLTRT_FLAGS_HASH_ADDR_FMASK) !=
158158
field_max(IP_FLTRT_FLAGS_NHASH_ADDR_FMASK));
159159

160-
/* Valid endpoint numbers must fit in the IP packet init command */
161-
BUILD_BUG_ON(field_max(IPA_PACKET_INIT_DEST_ENDPOINT_FMASK) <
162-
IPA_ENDPOINT_MAX - 1);
160+
/* Prior to IPA v5.0, we supported no more than 32 endpoints,
161+
* and this was reflected in some 5-bit fields that held
162+
* endpoint numbers. Starting with IPA v5.0, the widths of
163+
* these fields were extended to 8 bits, meaning up to 256
164+
* endpoints. If the driver claims to support more than
165+
* that it's an error.
166+
*/
167+
BUILD_BUG_ON(IPA_ENDPOINT_MAX - 1 > U8_MAX);
163168
}
164169

165170
/* Validate a memory region holding a table */
@@ -290,7 +295,11 @@ static bool ipa_cmd_register_write_valid(struct ipa *ipa)
290295
* offset will fit in a register write IPA immediate command.
291296
*/
292297
if (ipa_table_hash_support(ipa)) {
293-
reg = ipa_reg(ipa, FILT_ROUT_HASH_FLUSH);
298+
if (ipa->version < IPA_VERSION_5_0)
299+
reg = ipa_reg(ipa, FILT_ROUT_HASH_FLUSH);
300+
else
301+
reg = ipa_reg(ipa, FILT_ROUT_CACHE_FLUSH);
302+
294303
offset = ipa_reg_offset(reg);
295304
name = "filter/route hash flush";
296305
if (!ipa_cmd_register_write_offset_valid(ipa, name, offset))
@@ -486,8 +495,13 @@ static void ipa_cmd_ip_packet_init_add(struct gsi_trans *trans, u8 endpoint_id)
486495
cmd_payload = ipa_cmd_payload_alloc(ipa, &payload_addr);
487496
payload = &cmd_payload->ip_packet_init;
488497

489-
payload->dest_endpoint = u8_encode_bits(endpoint_id,
490-
IPA_PACKET_INIT_DEST_ENDPOINT_FMASK);
498+
if (ipa->version < IPA_VERSION_5_0) {
499+
payload->dest_endpoint =
500+
u8_encode_bits(endpoint_id,
501+
IPA_PACKET_INIT_DEST_ENDPOINT_FMASK);
502+
} else {
503+
payload->dest_endpoint = endpoint_id;
504+
}
491505

492506
gsi_trans_cmd_add(trans, payload, sizeof(*payload), payload_addr,
493507
opcode);

drivers/net/ipa/ipa_endpoint.c

Lines changed: 61 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0
22

33
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
4-
* Copyright (C) 2019-2022 Linaro Ltd.
4+
* Copyright (C) 2019-2023 Linaro Ltd.
55
*/
66

77
#include <linux/types.h>
@@ -922,64 +922,72 @@ static void ipa_endpoint_init_mode(struct ipa_endpoint *endpoint)
922922
iowrite32(val, ipa->reg_virt + offset);
923923
}
924924

925-
/* For IPA v4.5+, times are expressed using Qtime. The AP uses one of two
926-
* pulse generators (0 and 1) to measure elapsed time. In ipa_qtime_config()
927-
* they're configured to have granularity 100 usec and 1 msec, respectively.
928-
*
929-
* The return value is the positive or negative Qtime value to use to
930-
* express the (microsecond) time provided. A positive return value
931-
* means pulse generator 0 can be used; otherwise use pulse generator 1.
925+
/* For IPA v4.5+, times are expressed using Qtime. A time is represented
926+
* at one of several available granularities, which are configured in
927+
* ipa_qtime_config(). Three (or, starting with IPA v5.0, four) pulse
928+
* generators are set up with different "tick" periods. A Qtime value
929+
* encodes a tick count along with an indication of a pulse generator
930+
* (which has a fixed tick period). Two pulse generators are always
931+
* available to the AP; a third is available starting with IPA v5.0.
932+
* This function determines which pulse generator most accurately
933+
* represents the time period provided, and returns the tick count to
934+
* use to represent that time.
932935
*/
933-
static int ipa_qtime_val(u32 microseconds, u32 max)
934-
{
935-
u32 val;
936-
937-
/* Use 100 microsecond granularity if possible */
938-
val = DIV_ROUND_CLOSEST(microseconds, 100);
939-
if (val <= max)
940-
return (int)val;
941-
942-
/* Have to use pulse generator 1 (millisecond granularity) */
943-
val = DIV_ROUND_CLOSEST(microseconds, 1000);
944-
WARN_ON(val > max);
936+
static u32
937+
ipa_qtime_val(struct ipa *ipa, u32 microseconds, u32 max, u32 *select)
938+
{
939+
u32 which = 0;
940+
u32 ticks;
941+
942+
/* Pulse generator 0 has 100 microsecond granularity */
943+
ticks = DIV_ROUND_CLOSEST(microseconds, 100);
944+
if (ticks <= max)
945+
goto out;
946+
947+
/* Pulse generator 1 has millisecond granularity */
948+
which = 1;
949+
ticks = DIV_ROUND_CLOSEST(microseconds, 1000);
950+
if (ticks <= max)
951+
goto out;
952+
953+
if (ipa->version >= IPA_VERSION_5_0) {
954+
/* Pulse generator 2 has 10 millisecond granularity */
955+
which = 2;
956+
ticks = DIV_ROUND_CLOSEST(microseconds, 100);
957+
}
958+
WARN_ON(ticks > max);
959+
out:
960+
*select = which;
945961

946-
return (int)-val;
962+
return ticks;
947963
}
948964

949965
/* Encode the aggregation timer limit (microseconds) based on IPA version */
950966
static u32 aggr_time_limit_encode(struct ipa *ipa, const struct ipa_reg *reg,
951967
u32 microseconds)
952968
{
969+
u32 ticks;
953970
u32 max;
954-
u32 val;
955971

956972
if (!microseconds)
957973
return 0; /* Nothing to compute if time limit is 0 */
958974

959975
max = ipa_reg_field_max(reg, TIME_LIMIT);
960976
if (ipa->version >= IPA_VERSION_4_5) {
961-
u32 gran_sel;
962-
int ret;
963-
964-
/* Compute the Qtime limit value to use */
965-
ret = ipa_qtime_val(microseconds, max);
966-
if (ret < 0) {
967-
val = -ret;
968-
gran_sel = ipa_reg_bit(reg, AGGR_GRAN_SEL);
969-
} else {
970-
val = ret;
971-
gran_sel = 0;
972-
}
977+
u32 select;
978+
979+
ticks = ipa_qtime_val(ipa, microseconds, max, &select);
973980

974-
return gran_sel | ipa_reg_encode(reg, TIME_LIMIT, val);
981+
return ipa_reg_encode(reg, AGGR_GRAN_SEL, select) |
982+
ipa_reg_encode(reg, TIME_LIMIT, ticks);
975983
}
976984

977985
/* We program aggregation granularity in ipa_hardware_config() */
978-
val = DIV_ROUND_CLOSEST(microseconds, IPA_AGGR_GRANULARITY);
979-
WARN(val > max, "aggr_time_limit too large (%u > %u usec)\n",
986+
ticks = DIV_ROUND_CLOSEST(microseconds, IPA_AGGR_GRANULARITY);
987+
WARN(ticks > max, "aggr_time_limit too large (%u > %u usec)\n",
980988
microseconds, max * IPA_AGGR_GRANULARITY);
981989

982-
return ipa_reg_encode(reg, TIME_LIMIT, val);
990+
return ipa_reg_encode(reg, TIME_LIMIT, ticks);
983991
}
984992

985993
static void ipa_endpoint_init_aggr(struct ipa_endpoint *endpoint)
@@ -1050,20 +1058,13 @@ static u32 hol_block_timer_encode(struct ipa *ipa, const struct ipa_reg *reg,
10501058

10511059
if (ipa->version >= IPA_VERSION_4_5) {
10521060
u32 max = ipa_reg_field_max(reg, TIMER_LIMIT);
1053-
u32 gran_sel;
1054-
int ret;
1055-
1056-
/* Compute the Qtime limit value to use */
1057-
ret = ipa_qtime_val(microseconds, max);
1058-
if (ret < 0) {
1059-
val = -ret;
1060-
gran_sel = ipa_reg_bit(reg, TIMER_GRAN_SEL);
1061-
} else {
1062-
val = ret;
1063-
gran_sel = 0;
1064-
}
1061+
u32 select;
1062+
u32 ticks;
10651063

1066-
return gran_sel | ipa_reg_encode(reg, TIMER_LIMIT, val);
1064+
ticks = ipa_qtime_val(ipa, microseconds, max, &select);
1065+
1066+
return ipa_reg_encode(reg, TIMER_GRAN_SEL, 1) |
1067+
ipa_reg_encode(reg, TIMER_LIMIT, ticks);
10671068
}
10681069

10691070
/* Use 64 bit arithmetic to avoid overflow */
@@ -1986,6 +1987,7 @@ int ipa_endpoint_config(struct ipa *ipa)
19861987
struct device *dev = &ipa->pdev->dev;
19871988
const struct ipa_reg *reg;
19881989
u32 endpoint_id;
1990+
u32 hw_limit;
19891991
u32 tx_count;
19901992
u32 rx_count;
19911993
u32 rx_base;
@@ -2031,6 +2033,14 @@ int ipa_endpoint_config(struct ipa *ipa)
20312033
return -EINVAL;
20322034
}
20332035

2036+
/* Until IPA v5.0, the max endpoint ID was 32 */
2037+
hw_limit = ipa->version < IPA_VERSION_5_0 ? 32 : U8_MAX + 1;
2038+
if (limit > hw_limit) {
2039+
dev_err(dev, "unexpected endpoint count, %u > %u\n",
2040+
limit, hw_limit);
2041+
return -EINVAL;
2042+
}
2043+
20342044
/* Allocate and initialize the available endpoint bitmap */
20352045
ipa->available = bitmap_zalloc(limit, GFP_KERNEL);
20362046
if (!ipa->available)

drivers/net/ipa/ipa_endpoint.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
22

33
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
4-
* Copyright (C) 2019-2022 Linaro Ltd.
4+
* Copyright (C) 2019-2023 Linaro Ltd.
55
*/
66
#ifndef _IPA_ENDPOINT_H_
77
#define _IPA_ENDPOINT_H_
@@ -38,7 +38,7 @@ enum ipa_endpoint_name {
3838
IPA_ENDPOINT_COUNT, /* Number of names (not an index) */
3939
};
4040

41-
#define IPA_ENDPOINT_MAX 32 /* Max supported by driver */
41+
#define IPA_ENDPOINT_MAX 36 /* Max supported by driver */
4242

4343
/**
4444
* struct ipa_endpoint_tx - Endpoint configuration for TX endpoints

drivers/net/ipa/ipa_main.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0
22

33
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
4-
* Copyright (C) 2018-2022 Linaro Ltd.
4+
* Copyright (C) 2018-2023 Linaro Ltd.
55
*/
66

77
#include <linux/types.h>
@@ -390,7 +390,12 @@ static void ipa_qtime_config(struct ipa *ipa)
390390
reg = ipa_reg(ipa, TIMERS_PULSE_GRAN_CFG);
391391
val = ipa_reg_encode(reg, PULSE_GRAN_0, IPA_GRAN_100_US);
392392
val |= ipa_reg_encode(reg, PULSE_GRAN_1, IPA_GRAN_1_MS);
393-
val |= ipa_reg_encode(reg, PULSE_GRAN_2, IPA_GRAN_1_MS);
393+
if (ipa->version >= IPA_VERSION_5_0) {
394+
val |= ipa_reg_encode(reg, PULSE_GRAN_2, IPA_GRAN_10_MS);
395+
val |= ipa_reg_encode(reg, PULSE_GRAN_3, IPA_GRAN_10_MS);
396+
} else {
397+
val |= ipa_reg_encode(reg, PULSE_GRAN_2, IPA_GRAN_1_MS);
398+
}
394399

395400
iowrite32(val, ipa->reg_virt + ipa_reg_offset(reg));
396401

@@ -432,6 +437,11 @@ static void ipa_hardware_config_hashing(struct ipa *ipa)
432437
{
433438
const struct ipa_reg *reg;
434439

440+
/* Other than IPA v4.2, all versions enable "hashing". Starting
441+
* with IPA v5.0, the filter and router tables are implemented
442+
* differently, but the default configuration enables this feature
443+
* (now referred to as "cacheing"), so there's nothing to do here.
444+
*/
435445
if (ipa->version != IPA_VERSION_4_2)
436446
return;
437447

drivers/net/ipa/ipa_mem.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0
22

33
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
4-
* Copyright (C) 2019-2022 Linaro Ltd.
4+
* Copyright (C) 2019-2023 Linaro Ltd.
55
*/
66

77
#include <linux/types.h>
@@ -163,6 +163,12 @@ static bool ipa_mem_id_valid(struct ipa *ipa, enum ipa_mem_id mem_id)
163163
return false;
164164
break;
165165

166+
case IPA_MEM_AP_V4_FILTER:
167+
case IPA_MEM_AP_V6_FILTER:
168+
if (version != IPA_VERSION_5_0)
169+
return false;
170+
break;
171+
166172
case IPA_MEM_NAT_TABLE:
167173
case IPA_MEM_STATS_FILTER_ROUTE:
168174
if (version < IPA_VERSION_4_5)

drivers/net/ipa/ipa_mem.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
22

33
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
4-
* Copyright (C) 2019-2021 Linaro Ltd.
4+
* Copyright (C) 2019-2023 Linaro Ltd.
55
*/
66
#ifndef _IPA_MEM_H_
77
#define _IPA_MEM_H_
@@ -62,13 +62,15 @@ enum ipa_mem_id {
6262
IPA_MEM_PDN_CONFIG, /* 0/2 canaries (IPA v4.0+) */
6363
IPA_MEM_STATS_QUOTA_MODEM, /* 2/4 canaries (IPA v4.0+) */
6464
IPA_MEM_STATS_QUOTA_AP, /* 0 canaries, optional (IPA v4.0+) */
65-
IPA_MEM_STATS_TETHERING, /* 0 canaries (IPA v4.0+) */
65+
IPA_MEM_STATS_TETHERING, /* 0 canaries, optional (IPA v4.0+) */
6666
IPA_MEM_STATS_DROP, /* 0 canaries, optional (IPA v4.0+) */
67-
/* The next 5 filter and route statistics regions are optional */
67+
/* The next 7 filter and route statistics regions are optional */
6868
IPA_MEM_STATS_V4_FILTER, /* 0 canaries (IPA v4.0-v4.2) */
6969
IPA_MEM_STATS_V6_FILTER, /* 0 canaries (IPA v4.0-v4.2) */
7070
IPA_MEM_STATS_V4_ROUTE, /* 0 canaries (IPA v4.0-v4.2) */
7171
IPA_MEM_STATS_V6_ROUTE, /* 0 canaries (IPA v4.0-v4.2) */
72+
IPA_MEM_AP_V4_FILTER, /* 2 canaries (IPA v5.0) */
73+
IPA_MEM_AP_V6_FILTER, /* 0 canaries (IPA v5.0) */
7274
IPA_MEM_STATS_FILTER_ROUTE, /* 0 canaries (IPA v4.5+) */
7375
IPA_MEM_NAT_TABLE, /* 4 canaries, optional (IPA v4.5+) */
7476
IPA_MEM_END_MARKER, /* 1 canary (not a real region) */

0 commit comments

Comments
 (0)