diff --git a/drivers/net/ipa/ipa_endpoint.c b/drivers/net/ipa/ipa_endpoint.c index 9f50d0d11704c..2f56981b051ef 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 { @@ -576,17 +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; - val |= u32_encode_bits(limit / IPA_AGGR_GRANULARITY, - AGGR_TIME_LIMIT_FMASK); - val |= u32_encode_bits(0, AGGR_PKT_LIMIT_FMASK); + limit = DIV_ROUND_CLOSEST(limit, IPA_AGGR_GRANULARITY); + val |= u32_encode_bits(limit, AGGR_TIME_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 */ 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