Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: ipa: support a third pulse register

The AP has third pulse generator available starting with IPA v5.0.
Redefine ipa_qtime_val() to support that possibility. Pass the IPA
pointer as an argument so the version can be determined. And stop
using the sign of the returned tick count to indicate which of two
pulse generators to use.

Instead, have the caller provide the address of a variable that will
hold the selected pulse generator for the Qtime value. And for
version 5.0, check whether the third pulse generator best represents
the time period.

Add code in ipa_qtime_config() to configure the fourth pulse
generator for IPA v5.0+; in that case configure both the third and
fourth pulse generators to use 10 msec granularity.

Consistently use "ticks" for local variables that represent a tick
count.

Signed-off-by: Alex Elder <elder@linaro.org>
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Alex Elder and committed by
Jakub Kicinski
2cdbcbfd 32079a4a

+52 -46
+46 -45
drivers/net/ipa/ipa_endpoint.c
··· 922 922 iowrite32(val, ipa->reg_virt + offset); 923 923 } 924 924 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. 932 935 */ 933 - static int ipa_qtime_val(u32 microseconds, u32 max) 936 + static u32 937 + ipa_qtime_val(struct ipa *ipa, u32 microseconds, u32 max, u32 *select) 934 938 { 935 - u32 val; 939 + u32 which = 0; 940 + u32 ticks; 936 941 937 - /* Use 100 microsecond granularity if possible */ 938 - val = DIV_ROUND_CLOSEST(microseconds, 100); 939 - if (val <= max) 940 - return (int)val; 942 + /* Pulse generator 0 has 100 microsecond granularity */ 943 + ticks = DIV_ROUND_CLOSEST(microseconds, 100); 944 + if (ticks <= max) 945 + goto out; 941 946 942 - /* Have to use pulse generator 1 (millisecond granularity) */ 943 - val = DIV_ROUND_CLOSEST(microseconds, 1000); 944 - WARN_ON(val > max); 947 + /* Pulse generator 1 has millisecond granularity */ 948 + which = 1; 949 + ticks = DIV_ROUND_CLOSEST(microseconds, 1000); 950 + if (ticks <= max) 951 + goto out; 945 952 946 - return (int)-val; 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; 961 + 962 + return ticks; 947 963 } 948 964 949 965 /* Encode the aggregation timer limit (microseconds) based on IPA version */ 950 966 static u32 aggr_time_limit_encode(struct ipa *ipa, const struct ipa_reg *reg, 951 967 u32 microseconds) 952 968 { 969 + u32 ticks; 953 970 u32 max; 954 - u32 val; 955 971 956 972 if (!microseconds) 957 973 return 0; /* Nothing to compute if time limit is 0 */ 958 974 959 975 max = ipa_reg_field_max(reg, TIME_LIMIT); 960 976 if (ipa->version >= IPA_VERSION_4_5) { 961 - u32 gran_sel; 962 - int ret; 977 + u32 select; 963 978 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_encode(reg, AGGR_GRAN_SEL, 1); 969 - } else { 970 - val = ret; 971 - gran_sel = 0; 972 - } 979 + ticks = ipa_qtime_val(ipa, microseconds, max, &select); 973 980 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); 975 983 } 976 984 977 985 /* 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", 980 988 microseconds, max * IPA_AGGR_GRANULARITY); 981 989 982 - return ipa_reg_encode(reg, TIME_LIMIT, val); 990 + return ipa_reg_encode(reg, TIME_LIMIT, ticks); 983 991 } 984 992 985 993 static void ipa_endpoint_init_aggr(struct ipa_endpoint *endpoint) ··· 1058 1050 1059 1051 if (ipa->version >= IPA_VERSION_4_5) { 1060 1052 u32 max = ipa_reg_field_max(reg, TIMER_LIMIT); 1061 - u32 gran_sel; 1062 - int ret; 1053 + u32 select; 1054 + u32 ticks; 1063 1055 1064 - /* Compute the Qtime limit value to use */ 1065 - ret = ipa_qtime_val(microseconds, max); 1066 - if (ret < 0) { 1067 - val = -ret; 1068 - gran_sel = ipa_reg_encode(reg, TIMER_GRAN_SEL, 1); 1069 - } else { 1070 - val = ret; 1071 - gran_sel = 0; 1072 - } 1056 + ticks = ipa_qtime_val(ipa, microseconds, max, &select); 1073 1057 1074 - return gran_sel | ipa_reg_encode(reg, TIMER_LIMIT, val); 1058 + return ipa_reg_encode(reg, TIMER_GRAN_SEL, 1) | 1059 + ipa_reg_encode(reg, TIMER_LIMIT, ticks); 1075 1060 } 1076 1061 1077 1062 /* Use 64 bit arithmetic to avoid overflow */
+6 -1
drivers/net/ipa/ipa_main.c
··· 390 390 reg = ipa_reg(ipa, TIMERS_PULSE_GRAN_CFG); 391 391 val = ipa_reg_encode(reg, PULSE_GRAN_0, IPA_GRAN_100_US); 392 392 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 + } 394 399 395 400 iowrite32(val, ipa->reg_virt + ipa_reg_offset(reg)); 396 401