Since the introduction of PTP support in iavf, commit 7c01dbfc8a1c
("iavf: periodically cache PHC time"), the periodic PTP clock caching
task always provides a pending admin queue command, causing
iavf_process_aq_command() to always return success and permanently
preventing the stats fallback path from executing, which results in VF
statistics remaining at zero despite traffic flowing.
Fix this by making the stats request unconditional when the adapter is in
the running state, rather than relying on it as a fallback when no other
admin queue commands were processed.
Making the stats request unconditional exposes a separate, preexisting
gap: iavf_virtchnl_send_ptp_cmd() sends VIRTCHNL_OP_1588_PTP_GET_TIME
without setting adapter->current_op. A GET_STATS request can now follow
it in the same watchdog pass, and if the PTP reply arrives first,
iavf_virtchnl_completion() unconditionally clears adapter->current_op,
dropping the completion tracking for the still-outstanding GET_STATS
reply. Fix this by setting current_op around the PTP send, matching
every other virtchnl command sender.
Fixes: 7c01dbfc8a1c ("iavf: periodically cache PHC time")
Fixes: 52e3beac764d ("iavf: add support for indirect access to PHC time")
Reviewed-by: Aleksandr Loktionov <[email protected]>
Signed-off-by: Tomasz Lichwala <[email protected]>
---
v2:
- Set adapter->current_op around the PTP command send in
iavf_virtchnl_send_ptp_cmd(), so a GET_STATS request issued right
after it in the same watchdog pass no longer loses its completion
tracking when the PTP reply lands first (found by Sashiko auto
review on v1).
v1:
https://lore.kernel.org/netdev/[email protected]/
drivers/net/ethernet/intel/iavf/iavf_main.c | 14 ++++----------
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 2 ++
2 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c
b/drivers/net/ethernet/intel/iavf/iavf_main.c
index c7f69a904058..2cd01081ad85 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -2932,18 +2932,12 @@ static int iavf_watchdog_step(struct iavf_adapter
*adapter)
iavf_send_api_ver(adapter);
}
} else {
- int ret = iavf_process_aq_command(adapter);
-
- /* An error will be returned if no commands were
- * processed; use this opportunity to update stats
- * if the error isn't -ENOTSUPP
- */
- if (ret && ret != -EOPNOTSUPP &&
- adapter->state == __IAVF_RUNNING)
- iavf_request_stats(adapter);
+ iavf_process_aq_command(adapter);
}
- if (adapter->state == __IAVF_RUNNING)
+ if (adapter->state == __IAVF_RUNNING) {
+ iavf_request_stats(adapter);
iavf_detect_recover_hung(&adapter->vsi);
+ }
break;
case __IAVF_REMOVE:
default:
diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
index 680a28a739bf..acd1ed61af3a 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
@@ -1537,6 +1537,7 @@ void iavf_virtchnl_send_ptp_cmd(struct iavf_adapter
*adapter)
goto out_unlock;
}
+ adapter->current_op = cmd->v_opcode;
err = iavf_send_pf_msg(adapter, cmd->v_opcode, cmd->msg, cmd->msglen);
if (!err) {
/* Command was sent without errors, so we can remove it from
@@ -1546,6 +1547,7 @@ void iavf_virtchnl_send_ptp_cmd(struct iavf_adapter
*adapter)
kfree(cmd);
} else {
/* We failed to send the command, try again next cycle */
+ adapter->current_op = VIRTCHNL_OP_UNKNOWN;
pci_err(adapter->pdev, "Failed to send PTP command %d\n",
cmd->v_opcode);
}
--
2.54.0