From 317a5740b70568f71ecdcf0db1aefad2e4b74811 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 29 Jun 2020 16:55:21 -0500 Subject: [PATCH 1/3] net: ipa: rework ipa_aggr_granularity_val() The timer used for aggregation makes use of an internal 32 KHz clock. The granularity of the timer is programmed by a field whose value is computed by ipa_aggr_granularity_val(). Redefine the way that value is computed by using a new TIMER_FREQUENCY constant representing the underlying clock frequency. Add two BUILD_BUG_ON() calls to ensure the value used is valid. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_main.c | 5 +++++ drivers/net/ipa/ipa_reg.h | 17 ++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c index 76d5108b84039..27a869df3a4b9 100644 --- a/drivers/net/ipa/ipa_main.c +++ b/drivers/net/ipa/ipa_main.c @@ -674,6 +674,11 @@ static void ipa_validate_build(void) /* This is used as a divisor */ BUILD_BUG_ON(!IPA_AGGR_GRANULARITY); + + /* Aggregation granularity value can't be 0, and must fit */ + BUILD_BUG_ON(!ipa_aggr_granularity_val(IPA_AGGR_GRANULARITY)); + BUILD_BUG_ON(ipa_aggr_granularity_val(IPA_AGGR_GRANULARITY) > + field_max(AGGR_GRANULARITY)); #endif /* IPA_VALIDATE */ } diff --git a/drivers/net/ipa/ipa_reg.h b/drivers/net/ipa/ipa_reg.h index 0a688d8c1d7cf..7ae8015798aee 100644 --- a/drivers/net/ipa/ipa_reg.h +++ b/drivers/net/ipa/ipa_reg.h @@ -190,24 +190,23 @@ static inline u32 ipa_reg_bcr_val(enum ipa_version version) return 0x00000000; } - #define IPA_REG_LOCAL_PKT_PROC_CNTXT_BASE_OFFSET 0x000001e8 #define IPA_REG_AGGR_FORCE_CLOSE_OFFSET 0x000001ec /* ipa->available defines the valid bits in the AGGR_FORCE_CLOSE register */ +/* The internal inactivity timer clock is used for the aggregation timer */ +#define TIMER_FREQUENCY 32000 /* 32 KHz inactivity timer clock */ + #define IPA_REG_COUNTER_CFG_OFFSET 0x000001f0 #define AGGR_GRANULARITY GENMASK(8, 4) -/* Compute the value to use in the AGGR_GRANULARITY field representing - * the given number of microseconds (up to 1 millisecond). - * x = (32 * usec) / 1000 - 1 +/* Compute the value to use in the AGGR_GRANULARITY field representing the + * given number of microseconds. The value is one less than the number of + * timer ticks in the requested period. Zero not a valid granularity value. */ -static inline u32 ipa_aggr_granularity_val(u32 microseconds) +static inline u32 ipa_aggr_granularity_val(u32 usec) { - /* assert(microseconds >= 16); (?) */ - /* assert(microseconds <= 1015); */ - - return DIV_ROUND_CLOSEST(32 * microseconds, 1000) - 1; + return DIV_ROUND_CLOSEST(usec * TIMER_FREQUENCY, USEC_PER_SEC) - 1; } #define IPA_REG_TX_CFG_OFFSET 0x000001fc From 1d86652b13e8404ee42b6575d97ed228e92547d6 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 29 Jun 2020 16:55:22 -0500 Subject: [PATCH 2/3] net: ipa: reduce aggregation time limit Halve the time limit used when aggregation is enabled on an RX endpoint, to half a millisecond. Use DIV_ROUND_CLOSEST() to compute the value that represents the time period, to get better accuracy in the event the time limit is not an even multiple of the granularity. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_endpoint.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ipa/ipa_endpoint.c b/drivers/net/ipa/ipa_endpoint.c index 9f50d0d11704c..93449366d7d85 100644 --- a/drivers/net/ipa/ipa_endpoint.c +++ b/drivers/net/ipa/ipa_endpoint.c @@ -36,7 +36,7 @@ #define IPA_ENDPOINT_QMAP_METADATA_MASK 0x000000ff /* host byte order */ #define IPA_ENDPOINT_RESET_AGGR_RETRY_MAX 3 -#define IPA_AGGR_TIME_LIMIT_DEFAULT 1000 /* microseconds */ +#define IPA_AGGR_TIME_LIMIT_DEFAULT 500 /* microseconds */ /** enum ipa_status_opcode - status element opcode hardware values */ enum ipa_status_opcode { @@ -583,9 +583,11 @@ static void ipa_endpoint_init_aggr(struct ipa_endpoint *endpoint) val |= u32_encode_bits(IPA_GENERIC, AGGR_TYPE_FMASK); val |= u32_encode_bits(aggr_size, AGGR_BYTE_LIMIT_FMASK); + limit = IPA_AGGR_TIME_LIMIT_DEFAULT; - val |= u32_encode_bits(limit / IPA_AGGR_GRANULARITY, - AGGR_TIME_LIMIT_FMASK); + limit = DIV_ROUND_CLOSEST(limit, IPA_AGGR_GRANULARITY); + val |= u32_encode_bits(limit, AGGR_TIME_LIMIT_FMASK); + val |= u32_encode_bits(0, AGGR_PKT_LIMIT_FMASK); if (endpoint->data->rx.aggr_close_eof) val |= AGGR_SW_EOF_ACTIVE_FMASK; From 9e88cb5ff713bcacfe216c89d614eb505286ad6d Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 29 Jun 2020 16:55:23 -0500 Subject: [PATCH 3/3] net: ipa: reuse a local variable in ipa_endpoint_init_aggr() Reuse the "limit" local variable in ipa_endpoint_init_aggr() when setting the aggregation size limit. Simple cleanup. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_endpoint.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/ipa/ipa_endpoint.c b/drivers/net/ipa/ipa_endpoint.c index 93449366d7d85..2f56981b051ef 100644 --- a/drivers/net/ipa/ipa_endpoint.c +++ b/drivers/net/ipa/ipa_endpoint.c @@ -576,19 +576,20 @@ static void ipa_endpoint_init_aggr(struct ipa_endpoint *endpoint) if (endpoint->data->aggregation) { if (!endpoint->toward_ipa) { - u32 aggr_size = ipa_aggr_size_kb(IPA_RX_BUFFER_SIZE); u32 limit; val |= u32_encode_bits(IPA_ENABLE_AGGR, AGGR_EN_FMASK); val |= u32_encode_bits(IPA_GENERIC, AGGR_TYPE_FMASK); - val |= u32_encode_bits(aggr_size, - AGGR_BYTE_LIMIT_FMASK); + + limit = ipa_aggr_size_kb(IPA_RX_BUFFER_SIZE); + val |= u32_encode_bits(limit, AGGR_BYTE_LIMIT_FMASK); limit = IPA_AGGR_TIME_LIMIT_DEFAULT; limit = DIV_ROUND_CLOSEST(limit, IPA_AGGR_GRANULARITY); val |= u32_encode_bits(limit, AGGR_TIME_LIMIT_FMASK); - val |= u32_encode_bits(0, AGGR_PKT_LIMIT_FMASK); + /* AGGR_PKT_LIMIT is 0 (unlimited) */ + if (endpoint->data->rx.aggr_close_eof) val |= AGGR_SW_EOF_ACTIVE_FMASK; /* AGGR_HARD_BYTE_LIMIT_ENABLE is 0 */