From patchwork Wed Nov 24 19:44:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Elder X-Patchwork-Id: 12637657 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 84849C433FE for ; Wed, 24 Nov 2021 19:44:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229557AbhKXTre (ORCPT ); Wed, 24 Nov 2021 14:47:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36584 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235150AbhKXTrd (ORCPT ); Wed, 24 Nov 2021 14:47:33 -0500 Received: from mail-io1-xd2a.google.com (mail-io1-xd2a.google.com [IPv6:2607:f8b0:4864:20::d2a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A0FBC06173E for ; Wed, 24 Nov 2021 11:44:23 -0800 (PST) Received: by mail-io1-xd2a.google.com with SMTP id x10so4661376ioj.9 for ; Wed, 24 Nov 2021 11:44:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=r/sq+osswXVFeooo9nOfGZuqrilTERPbfSJVItpOsc8=; b=ZAwprTOp0FJmJtOESrlWSqdjW2DMJt0L+ZvBTbVhnC4TNq/z4gkPGH8uHuKkgpTxrs +brCsDwDDwcI7KWBtc+EpzpHYujIrBtdb1YQePRAJ6uSKF0xq0WdMso9EGS4ZCkvxyYu 2EipvOx+5CBc4hSJuOMCVyeMm/UZK5zvWsYDItYG7zmX9a9SdElypNVaWQvHVLqczql9 QBBMH5qhk+5SbXjusyRJNaO7/fCrthE9TJywDuhmV919vyXnONnDnWHMkTYaTn5A27PK DQRSRXiVbp+1TX5H5znPSFBM/KKxERcsSC1WSlVxaJyJwwg7u+tV+6HgV3oqIxNx/DD6 u8rA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=r/sq+osswXVFeooo9nOfGZuqrilTERPbfSJVItpOsc8=; b=467SdW9pzasf5f2K0hBdeOQL//de43wTGEGBpr6Oy0rM2UBslqReBvwIAgnvkVQa2b WRjf1r5eHADLA4qmPc8LE/yZizcjU9rOHK78Xl7s2nyF9YNWzgdkJ4vLBW6TfuDKarW5 b8357a022DsyfK/x2nVC8AfbLPTuonuK8rZFK4GzqxbM359vUruqCLJRPYc8+aUiRYUg RRuCsynh0FLnOu6UliZlgmqVEBp7kDll+4vbGhwhhPDO4gTkGdRQ+GY/WAn7jmEM0oz0 KwQO1ewQwypGs1cVbaw7W7R9HWDPLrYpGaIOk06qjGjVGqZBKZ8wyklSIFNxMcBVMh0R vljg== X-Gm-Message-State: AOAM530Q6eUjBrm2IUY5wRg4Z50KZlIA4l/2AENre9mxySaD5zCZEyMy oiCTnevyQc3hG39RlKWRsk7rfA== X-Google-Smtp-Source: ABdhPJwkd/DZevG8n91IJeK/VAmWkoyvdVdeJQS54FEgMeaUE75nbpKTsIv7qIP2YoI5+pOH4UxoZA== X-Received: by 2002:a05:6638:f83:: with SMTP id h3mr19660272jal.102.1637783062341; Wed, 24 Nov 2021 11:44:22 -0800 (PST) Received: from localhost.localdomain (c-73-185-129-58.hsd1.mn.comcast.net. [73.185.129.58]) by smtp.gmail.com with ESMTPSA id r14sm490145iov.14.2021.11.24.11.44.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Nov 2021 11:44:21 -0800 (PST) From: Alex Elder To: davem@davemloft.net, kuba@kernel.org Cc: pkurapat@codeaurora.org, avuyyuru@codeaurora.org, bjorn.andersson@linaro.org, cpratapa@codeaurora.org, subashab@codeaurora.org, evgreen@chromium.org, elder@kernel.org, netdev@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 1/2] net: ipa: introduce channel flow control Date: Wed, 24 Nov 2021 13:44:15 -0600 Message-Id: <20211124194416.707007-2-elder@linaro.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20211124194416.707007-1-elder@linaro.org> References: <20211124194416.707007-1-elder@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org One quirk for certain versions of IPA is that endpoint DELAY mode does not work properly. IPA DELAY mode prevents any packets from being delivered to the IPA core for processing on a TX endpoint. The AP uses DELAY mode when the modem crashes, to prevent modem TX endpoints from generating traffic during crash recovery. Without this, there is a chance the hardware will stall during recovery from a modem crash. To achieve a similar effect, a GSI FLOW_CONTROLLED channel state was created. A STARTED TX channel can be placed in FLOW_CONTROLLED state, which prevents the transfer of any more packets. A channel in FLOW_CONTROLLED state can be either returned to STARTED state, or can be transitioned to STOPPED state. Because this operates on GSI channels, two generic commands were added to allow the AP to control this state for modem channels (similar to the ALLOCATE and HALT channel commands). Previously the code assumed this quirk only applied to IPA v4.2. In fact, channel flow control (rather than endpoint DELAY mode) should be used for all versions *starting* with IPA v4.2. Signed-off-by: Alex Elder --- drivers/net/ipa/gsi.c | 52 ++++++++++++++++++++++++++-------- drivers/net/ipa/gsi.h | 10 +++++++ drivers/net/ipa/gsi_reg.h | 2 ++ drivers/net/ipa/ipa_endpoint.c | 50 +++++++++++++++++++------------- 4 files changed, 82 insertions(+), 32 deletions(-) diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c index a2fcdb1abdb96..5f9e9fb501e7f 100644 --- a/drivers/net/ipa/gsi.c +++ b/drivers/net/ipa/gsi.c @@ -1171,18 +1171,23 @@ static void gsi_isr_gp_int1(struct gsi *gsi) u32 result; u32 val; - /* This interrupt is used to handle completions of the two GENERIC - * GSI commands. We use these to allocate and halt channels on - * the modem's behalf due to a hardware quirk on IPA v4.2. Once - * allocated, the modem "owns" these channels, and as a result we - * have no way of knowing the channel's state at any given time. + /* This interrupt is used to handle completions of GENERIC GSI + * commands. We use these to allocate and halt channels on the + * modem's behalf due to a hardware quirk on IPA v4.2. The modem + * "owns" channels even when the AP allocates them, and have no + * way of knowing whether a modem channel's state has been changed. + * + * We also use GENERIC commands to enable/disable channel flow + * control for IPA v4.2+. * * It is recommended that we halt the modem channels we allocated * when shutting down, but it's possible the channel isn't running * at the time we issue the HALT command. We'll get an error in * that case, but it's harmless (the channel is already halted). + * Similarly, we could get an error back when updating flow control + * on a channel because it's not in the proper state. * - * For this reason, we silently ignore a CHANNEL_NOT_RUNNING error + * In either case, we silently ignore a CHANNEL_NOT_RUNNING error * if we receive it. */ val = ioread32(gsi->virt + GSI_CNTXT_SCRATCH_0_OFFSET); @@ -1648,6 +1653,10 @@ static void gsi_channel_teardown_one(struct gsi *gsi, u32 channel_id) gsi_evt_ring_de_alloc_command(gsi, evt_ring_id); } +/* We use generic commands only to operate on modem channels. We don't have + * the ability to determine channel state for a modem channel, so we simply + * issue the command and wait for it to complete. + */ static int gsi_generic_command(struct gsi *gsi, u32 channel_id, enum gsi_generic_cmd_opcode opcode) { @@ -1655,12 +1664,14 @@ static int gsi_generic_command(struct gsi *gsi, u32 channel_id, bool timeout; u32 val; - /* The error global interrupt type is always enabled (until we - * teardown), so we won't change that. A generic EE command - * completes with a GSI global interrupt of type GP_INT1. We - * only perform one generic command at a time (to allocate or - * halt a modem channel) and only from this function. So we - * enable the GP_INT1 IRQ type here while we're expecting it. + /* The error global interrupt type is always enabled (until we tear + * down), so we will keep it enabled. + * + * A generic EE command completes with a GSI global interrupt of + * type GP_INT1. We only perform one generic command at a time + * (to allocate, halt, or enable/disable flow control on a modem + * channel), and only from this function. So we enable the GP_INT1 + * IRQ type here, and disable it again after the command completes. */ val = BIT(ERROR_INT) | BIT(GP_INT1); iowrite32(val, gsi->virt + GSI_CNTXT_GLOB_IRQ_EN_OFFSET); @@ -1710,6 +1721,23 @@ static void gsi_modem_channel_halt(struct gsi *gsi, u32 channel_id) ret, channel_id); } +/* Enable or disable flow control for a modem GSI TX channel (IPA v4.2+) */ +void +gsi_modem_channel_flow_control(struct gsi *gsi, u32 channel_id, bool enable) +{ + u32 command; + int ret; + + command = enable ? GSI_GENERIC_ENABLE_FLOW_CONTROL + : GSI_GENERIC_DISABLE_FLOW_CONTROL; + + ret = gsi_generic_command(gsi, channel_id, command); + if (ret) + dev_err(gsi->dev, + "error %d %sabling mode channel %u flow control\n", + ret, enable ? "en" : "dis", channel_id); +} + /* Setup function for channels */ static int gsi_channel_setup(struct gsi *gsi) { diff --git a/drivers/net/ipa/gsi.h b/drivers/net/ipa/gsi.h index 88b80dc3db79f..41b3ab14c5124 100644 --- a/drivers/net/ipa/gsi.h +++ b/drivers/net/ipa/gsi.h @@ -101,6 +101,7 @@ enum gsi_channel_state { GSI_CHANNEL_STATE_STARTED = 0x2, GSI_CHANNEL_STATE_STOPPED = 0x3, GSI_CHANNEL_STATE_STOP_IN_PROC = 0x4, + GSI_CHANNEL_STATE_FLOW_CONTROLLED = 0x5, /* IPA v4.2+ */ GSI_CHANNEL_STATE_ERROR = 0xf, }; @@ -218,6 +219,15 @@ int gsi_channel_start(struct gsi *gsi, u32 channel_id); */ int gsi_channel_stop(struct gsi *gsi, u32 channel_id); +/** + * gsi_modem_channel_flow_control() - Set channel flow control state (IPA v4.2+) + * @gsi: GSI pointer returned by gsi_setup() + * @channel_id: Modem TX channel to control + * @enable: Whether to enable flow control (i.e., prevent flow) + */ +void gsi_modem_channel_flow_control(struct gsi *gsi, u32 channel_id, + bool enable); + /** * gsi_channel_reset() - Reset an allocated GSI channel * @gsi: GSI pointer diff --git a/drivers/net/ipa/gsi_reg.h b/drivers/net/ipa/gsi_reg.h index bf9593d9eaead..4ab23998b3485 100644 --- a/drivers/net/ipa/gsi_reg.h +++ b/drivers/net/ipa/gsi_reg.h @@ -318,6 +318,8 @@ enum gsi_evt_cmd_opcode { enum gsi_generic_cmd_opcode { GSI_GENERIC_HALT_CHANNEL = 0x1, GSI_GENERIC_ALLOCATE_CHANNEL = 0x2, + GSI_GENERIC_ENABLE_FLOW_CONTROL = 0x3, /* IPA v4.2+ */ + GSI_GENERIC_DISABLE_FLOW_CONTROL = 0x4, /* IPA v4.2+ */ }; /* The next register is present for IPA v3.5.1 and above */ diff --git a/drivers/net/ipa/ipa_endpoint.c b/drivers/net/ipa/ipa_endpoint.c index ef790fd0ab56a..d89347a88e50b 100644 --- a/drivers/net/ipa/ipa_endpoint.c +++ b/drivers/net/ipa/ipa_endpoint.c @@ -237,7 +237,8 @@ static struct gsi_trans *ipa_endpoint_trans_alloc(struct ipa_endpoint *endpoint, } /* suspend_delay represents suspend for RX, delay for TX endpoints. - * Note that suspend is not supported starting with IPA v4.0. + * Note that suspend is not supported starting with IPA v4.0, and + * delay mode should not be used starting with IPA v4.2. */ static bool ipa_endpoint_init_ctrl(struct ipa_endpoint *endpoint, bool suspend_delay) @@ -248,11 +249,8 @@ ipa_endpoint_init_ctrl(struct ipa_endpoint *endpoint, bool suspend_delay) u32 mask; u32 val; - /* Suspend is not supported for IPA v4.0+. Delay doesn't work - * correctly on IPA v4.2. - */ if (endpoint->toward_ipa) - WARN_ON(ipa->version == IPA_VERSION_4_2); + WARN_ON(ipa->version >= IPA_VERSION_4_2); else WARN_ON(ipa->version >= IPA_VERSION_4_0); @@ -270,15 +268,15 @@ ipa_endpoint_init_ctrl(struct ipa_endpoint *endpoint, bool suspend_delay) return state; } -/* We currently don't care what the previous state was for delay mode */ +/* We don't care what the previous state was for delay mode */ static void ipa_endpoint_program_delay(struct ipa_endpoint *endpoint, bool enable) { + /* Delay mode should not be used for IPA v4.2+ */ + WARN_ON(endpoint->ipa->version >= IPA_VERSION_4_2); WARN_ON(!endpoint->toward_ipa); - /* Delay mode doesn't work properly for IPA v4.2 */ - if (endpoint->ipa->version != IPA_VERSION_4_2) - (void)ipa_endpoint_init_ctrl(endpoint, enable); + (void)ipa_endpoint_init_ctrl(endpoint, enable); } static bool ipa_endpoint_aggr_active(struct ipa_endpoint *endpoint) @@ -355,26 +353,29 @@ ipa_endpoint_program_suspend(struct ipa_endpoint *endpoint, bool enable) return suspended; } -/* Enable or disable delay or suspend mode on all modem endpoints */ +/* Put all modem RX endpoints into suspend mode, and stop transmission + * on all modem TX endpoints. Prior to IPA v4.2, endpoint DELAY mode is + * used for TX endpoints; starting with IPA v4.2 we use GSI channel flow + * control instead. + */ void ipa_endpoint_modem_pause_all(struct ipa *ipa, bool enable) { u32 endpoint_id; - /* DELAY mode doesn't work correctly on IPA v4.2 */ - if (ipa->version == IPA_VERSION_4_2) - return; - for (endpoint_id = 0; endpoint_id < IPA_ENDPOINT_MAX; endpoint_id++) { struct ipa_endpoint *endpoint = &ipa->endpoint[endpoint_id]; if (endpoint->ee_id != GSI_EE_MODEM) continue; - /* Set TX delay mode or RX suspend mode */ - if (endpoint->toward_ipa) + if (!endpoint->toward_ipa) + (void)ipa_endpoint_program_suspend(endpoint, enable); + else if (ipa->version < IPA_VERSION_4_2) ipa_endpoint_program_delay(endpoint, enable); else - (void)ipa_endpoint_program_suspend(endpoint, enable); + gsi_modem_channel_flow_control(&ipa->gsi, + endpoint->channel_id, + enable); } } @@ -1519,10 +1520,19 @@ static void ipa_endpoint_reset(struct ipa_endpoint *endpoint) static void ipa_endpoint_program(struct ipa_endpoint *endpoint) { - if (endpoint->toward_ipa) - ipa_endpoint_program_delay(endpoint, false); - else + if (endpoint->toward_ipa) { + /* Newer versions of IPA use GSI channel flow control + * instead of endpoint DELAY mode to prevent sending data. + * Flow control is disabled for newly-allocated channels, + * and we can assume flow control is not (ever) enabled + * for AP TX channels. + */ + if (endpoint->ipa->version < IPA_VERSION_4_2) + ipa_endpoint_program_delay(endpoint, false); + } else { + /* Ensure suspend mode is off on all AP RX endpoints */ (void)ipa_endpoint_program_suspend(endpoint, false); + } ipa_endpoint_init_cfg(endpoint); ipa_endpoint_init_nat(endpoint); ipa_endpoint_init_hdr(endpoint); From patchwork Wed Nov 24 19:44:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Elder X-Patchwork-Id: 12637659 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AD86CC433F5 for ; Wed, 24 Nov 2021 19:44:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235878AbhKXTrg (ORCPT ); Wed, 24 Nov 2021 14:47:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36592 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235610AbhKXTre (ORCPT ); Wed, 24 Nov 2021 14:47:34 -0500 Received: from mail-io1-xd32.google.com (mail-io1-xd32.google.com [IPv6:2607:f8b0:4864:20::d32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 83C86C061574 for ; Wed, 24 Nov 2021 11:44:24 -0800 (PST) Received: by mail-io1-xd32.google.com with SMTP id f9so4629966ioo.11 for ; Wed, 24 Nov 2021 11:44:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9+1wmLMR32a4owb7dmiLLzwYsR7GITdvUE8vjTvuilE=; b=W9Wsncv65+Y3CmoeAbhZYtPAmBFUAnhs9JZy2aq+yOyfzrBfTfBGYf89XsdwCV4Fdc TM0XqH+T4oVJks86UJIwZS0vxGcrHu6qqWg5CyZ58pUq+Rv1DfGXKYbpIpX85F+vgdkV tVl6XoSVEeJEekdCKf4rTkUsw8bW0zEn7veEyeLzB+ndpYC7ZooXSn/Cpp3HboXiqhb+ 3hpHzFvMIowiSU7Lkmhumlx3ZSCw4a8IFTv4ssNSh7cV2mz7HXjSLajnUtFZ1WkrIWah rHu2DMxbhgBCjtd17YDjowYWq/JvNrpYeCklyJJP1cp/JsG3WdEOGPwbeQbx5DjPtt7X nm1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9+1wmLMR32a4owb7dmiLLzwYsR7GITdvUE8vjTvuilE=; b=P9HkMGnlnq/+ktl/CTur1ao1WsHYIVR6m82+QcXJTvUUNUqeyrf6hscKK+OrQiyA4y S1x7RVDyjckpE9itUgmxfc23O4LSBjn5GRzPLFQyYtZYU0pN4LP4UOKJ8y+Ag2lBl966 stqlTtefynhJvwZudUllgrJ6ez54vEwmTwfVb3138b+aqIGcVcQVaHhXo7jNQORGWzzV BIWIm0pb9mf1gHJACDr9a86+C6hfwtkb4ibl4eJWPioLJvVe2MviNGThxgu6C/qWCyjr AzQ98V74NgOgT3l+yJxcIjIlTqYus2StwDSyZMxwmdSl58owvC5T7Mfn21BO1DryP5gS v2Pw== X-Gm-Message-State: AOAM5320IBJfsT4NdhLv0V3uuGkx7Zcyk+S4+vjJmPiRIayVcVsA7npJ bPdBZcK94OX8fk0bcy1BdYTqLw== X-Google-Smtp-Source: ABdhPJzPyTIl2t/oL3DjN5/Lhw+wTdL2jGh8m7uzJGY603AFVNlHPu0JZoBNTAXesEg3q0f5NEvjWQ== X-Received: by 2002:a6b:7306:: with SMTP id e6mr17042524ioh.25.1637783063826; Wed, 24 Nov 2021 11:44:23 -0800 (PST) Received: from localhost.localdomain (c-73-185-129-58.hsd1.mn.comcast.net. [73.185.129.58]) by smtp.gmail.com with ESMTPSA id r14sm490145iov.14.2021.11.24.11.44.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Nov 2021 11:44:23 -0800 (PST) From: Alex Elder To: davem@davemloft.net, kuba@kernel.org Cc: pkurapat@codeaurora.org, avuyyuru@codeaurora.org, bjorn.andersson@linaro.org, cpratapa@codeaurora.org, subashab@codeaurora.org, evgreen@chromium.org, elder@kernel.org, netdev@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 2/2] net: ipa: support enhanced channel flow control Date: Wed, 24 Nov 2021 13:44:16 -0600 Message-Id: <20211124194416.707007-3-elder@linaro.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20211124194416.707007-1-elder@linaro.org> References: <20211124194416.707007-1-elder@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org IPA v4.2 introduced GSI channel flow control, used instead of IPA endpoint DELAY mode to prevent a TX channel from injecting packets into the IPA core. It used a new FLOW_CONTROLLED channel state which could be entered using GSI generic commands. IPA v4.11 extended the channel flow control model. Rather than having a distinct FLOW_CONTROLLED channel state, each channel has a "flow control" property that can be enabled or not--independent of the channel state. The AP (or modem) can modify this property using the same GSI generic commands as before. The AP only uses channel flow control on modem TX channels, and only when recovering from a modem crash. The AP has no way to discover the state of a modem channel, so the fact that (starting with IPA v4.11) flow control no longer uses a distinct channel state is invisible to the AP. So enhanced flow control generally does not change the way AP uses flow control. There are a few small differences, however: - There is a notion of "primary" or "secondary" flow control, and when enabling or disabling flow control that must be specified in a new field in the GSI generic command register. For now, we always specify 0 (meaning "primary"). - When disabling flow control, it's possible a request will need to be retried. We retry up to 5 times in this case. - Another new generic command allows the current flow control state to be queried. We do not use this. Other than the need for retries, the code essentially works the same way as before. Signed-off-by: Alex Elder --- drivers/net/ipa/gsi.c | 20 ++++++++++++++++---- drivers/net/ipa/gsi.h | 2 +- drivers/net/ipa/gsi_reg.h | 2 ++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c index 5f9e9fb501e7f..1125926367b2c 100644 --- a/drivers/net/ipa/gsi.c +++ b/drivers/net/ipa/gsi.c @@ -93,6 +93,7 @@ #define GSI_CHANNEL_STOP_RETRIES 10 #define GSI_CHANNEL_MODEM_HALT_RETRIES 10 +#define GSI_CHANNEL_MODEM_FLOW_RETRIES 5 /* disable flow control only */ #define GSI_MHI_EVENT_ID_START 10 /* 1st reserved event id */ #define GSI_MHI_EVENT_ID_END 16 /* Last reserved event id */ @@ -1658,7 +1659,8 @@ static void gsi_channel_teardown_one(struct gsi *gsi, u32 channel_id) * issue the command and wait for it to complete. */ static int gsi_generic_command(struct gsi *gsi, u32 channel_id, - enum gsi_generic_cmd_opcode opcode) + enum gsi_generic_cmd_opcode opcode, + u8 params) { struct completion *completion = &gsi->completion; bool timeout; @@ -1685,6 +1687,7 @@ static int gsi_generic_command(struct gsi *gsi, u32 channel_id, val = u32_encode_bits(opcode, GENERIC_OPCODE_FMASK); val |= u32_encode_bits(channel_id, GENERIC_CHID_FMASK); val |= u32_encode_bits(GSI_EE_MODEM, GENERIC_EE_FMASK); + val |= u32_encode_bits(params, GENERIC_PARAMS_FMASK); timeout = !gsi_command(gsi, GSI_GENERIC_CMD_OFFSET, val, completion); @@ -1703,7 +1706,7 @@ static int gsi_generic_command(struct gsi *gsi, u32 channel_id, static int gsi_modem_channel_alloc(struct gsi *gsi, u32 channel_id) { return gsi_generic_command(gsi, channel_id, - GSI_GENERIC_ALLOCATE_CHANNEL); + GSI_GENERIC_ALLOCATE_CHANNEL, 0); } static void gsi_modem_channel_halt(struct gsi *gsi, u32 channel_id) @@ -1713,7 +1716,7 @@ static void gsi_modem_channel_halt(struct gsi *gsi, u32 channel_id) do ret = gsi_generic_command(gsi, channel_id, - GSI_GENERIC_HALT_CHANNEL); + GSI_GENERIC_HALT_CHANNEL, 0); while (ret == -EAGAIN && retries--); if (ret) @@ -1725,13 +1728,22 @@ static void gsi_modem_channel_halt(struct gsi *gsi, u32 channel_id) void gsi_modem_channel_flow_control(struct gsi *gsi, u32 channel_id, bool enable) { + u32 retries = 0; u32 command; int ret; command = enable ? GSI_GENERIC_ENABLE_FLOW_CONTROL : GSI_GENERIC_DISABLE_FLOW_CONTROL; + /* Disabling flow control on IPA v4.11+ can return -EAGAIN if enable + * is underway. In this case we need to retry the command. + */ + if (!enable && gsi->version >= IPA_VERSION_4_11) + retries = GSI_CHANNEL_MODEM_FLOW_RETRIES; + + do + ret = gsi_generic_command(gsi, channel_id, command, 0); + while (ret == -EAGAIN && retries--); - ret = gsi_generic_command(gsi, channel_id, command); if (ret) dev_err(gsi->dev, "error %d %sabling mode channel %u flow control\n", diff --git a/drivers/net/ipa/gsi.h b/drivers/net/ipa/gsi.h index 41b3ab14c5124..5370a282a9f57 100644 --- a/drivers/net/ipa/gsi.h +++ b/drivers/net/ipa/gsi.h @@ -101,7 +101,7 @@ enum gsi_channel_state { GSI_CHANNEL_STATE_STARTED = 0x2, GSI_CHANNEL_STATE_STOPPED = 0x3, GSI_CHANNEL_STATE_STOP_IN_PROC = 0x4, - GSI_CHANNEL_STATE_FLOW_CONTROLLED = 0x5, /* IPA v4.2+ */ + GSI_CHANNEL_STATE_FLOW_CONTROLLED = 0x5, /* IPA v4.2-v4.9 */ GSI_CHANNEL_STATE_ERROR = 0xf, }; diff --git a/drivers/net/ipa/gsi_reg.h b/drivers/net/ipa/gsi_reg.h index 4ab23998b3485..8906f4381032e 100644 --- a/drivers/net/ipa/gsi_reg.h +++ b/drivers/net/ipa/gsi_reg.h @@ -313,6 +313,7 @@ enum gsi_evt_cmd_opcode { #define GENERIC_OPCODE_FMASK GENMASK(4, 0) #define GENERIC_CHID_FMASK GENMASK(9, 5) #define GENERIC_EE_FMASK GENMASK(13, 10) +#define GENERIC_PARAMS_FMASK GENMASK(31, 24) /* IPA v4.11+ */ /** enum gsi_generic_cmd_opcode - GENERIC_OPCODE field values in GENERIC_CMD */ enum gsi_generic_cmd_opcode { @@ -320,6 +321,7 @@ enum gsi_generic_cmd_opcode { GSI_GENERIC_ALLOCATE_CHANNEL = 0x2, GSI_GENERIC_ENABLE_FLOW_CONTROL = 0x3, /* IPA v4.2+ */ GSI_GENERIC_DISABLE_FLOW_CONTROL = 0x4, /* IPA v4.2+ */ + GSI_GENERIC_QUERY_FLOW_CONTROL = 0x5, /* IPA v4.11+ */ }; /* The next register is present for IPA v3.5.1 and above */