summaryrefslogtreecommitdiffstats
path: root/drivers/net/ipa/ipa_endpoint.c
diff options
context:
space:
mode:
authorAlex Elder <elder@linaro.org>2021-01-26 19:57:01 +0100
committerJakub Kicinski <kuba@kernel.org>2021-01-29 05:23:26 +0100
commit51c48ce264f85919b263a38e4defa50b80928877 (patch)
treeac49e225ff6bf8d415c2aeab331f00e8b19c1fcf /drivers/net/ipa/ipa_endpoint.c
parentnet: ipa: drop packet if status has valid tag (diff)
downloadlinux-51c48ce264f85919b263a38e4defa50b80928877.tar.xz
linux-51c48ce264f85919b263a38e4defa50b80928877.zip
net: ipa: signal when tag transfer completes
There are times, such as when the modem crashes, when we issue commands to clear the IPA hardware pipeline. These commands include a data transfer command that delivers a small packet directly to the default (AP<-LAN RX) endpoint. The places that do this wait for the transactions that contain these commands to complete, but the pipeline can't be assumed clear until the sent packet has been *received*. The small transfer will be delivered with a status structure, and that status will indicate its tag is valid. This is the only place we send a tagged packet, so we use the tag to determine when the pipeline clear packet has arrived. Add a completion to the IPA structure to to be used to signal the receipt of a pipeline clear packet. Create a new function ipa_cmd_pipeline_clear_wait() that will wait for that completion. Reinitialize the completion whenever pipeline clear commands are added to a transaction. Extend ipa_endpoint_status_tag() to check whether a packet whose status contains a valid tag was sent from the AP->command TX endpoint, and if so, signal the new IPA completion. Have all callers of ipa_cmd_pipeline_clear_add() wait for the pipeline clear indication after the transaction that clears the pipeline has completed. Signed-off-by: Alex Elder <elder@linaro.org> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/ipa/ipa_endpoint.c')
-rw-r--r--drivers/net/ipa/ipa_endpoint.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/net/ipa/ipa_endpoint.c b/drivers/net/ipa/ipa_endpoint.c
index 68970a3baa47..8313220d41e7 100644
--- a/drivers/net/ipa/ipa_endpoint.c
+++ b/drivers/net/ipa/ipa_endpoint.c
@@ -436,6 +436,8 @@ int ipa_endpoint_modem_exception_reset_all(struct ipa *ipa)
/* XXX This should have a 1 second timeout */
gsi_trans_commit_wait(trans);
+ ipa_cmd_pipeline_clear_wait(ipa);
+
return 0;
}
@@ -1178,7 +1180,30 @@ static bool ipa_endpoint_status_skip(struct ipa_endpoint *endpoint,
static bool ipa_endpoint_status_tag(struct ipa_endpoint *endpoint,
const struct ipa_status *status)
{
- return !!le16_get_bits(status->mask, IPA_STATUS_MASK_TAG_VALID_FMASK);
+ struct ipa_endpoint *command_endpoint;
+ struct ipa *ipa = endpoint->ipa;
+ u32 endpoint_id;
+
+ if (!le16_get_bits(status->mask, IPA_STATUS_MASK_TAG_VALID_FMASK))
+ return false; /* No valid tag */
+
+ /* The status contains a valid tag. We know the packet was sent to
+ * this endpoint (already verified by ipa_endpoint_status_skip()).
+ * If the packet came from the AP->command TX endpoint we know
+ * this packet was sent as part of the pipeline clear process.
+ */
+ endpoint_id = u8_get_bits(status->endp_src_idx,
+ IPA_STATUS_SRC_IDX_FMASK);
+ command_endpoint = ipa->name_map[IPA_ENDPOINT_AP_COMMAND_TX];
+ if (endpoint_id == command_endpoint->endpoint_id) {
+ complete(&ipa->completion);
+ } else {
+ dev_err(&ipa->pdev->dev,
+ "unexpected tagged packet from endpoint %u\n",
+ endpoint_id);
+ }
+
+ return true;
}
/* Return whether the status indicates the packet should be dropped */