If a reset event is received from the PF early in the init cycle, the
iavf state machine could hang for about 25 seconds. For example:
# echo 1 > /sys/class/net/enp175s0np0/device/sriov_numvfs && \
ip link set dev enp175s0np0 vf 0 mac <new_mac>
the log shows:
[532.770534] ice 0000:af:00.0: Enabling 1 VFs
[532.880439] iavf 0000:af:01.0: enabling device (0000 -> 0002)
[532.880983] ice 0000:af:00.0: Enabling 1 VFs with 17 vectors and 16 queues
per VF
[532.916547] ice 0000:af:00.0 enp175s0np0: Setting MAC 00:60:2f:20:3f:28 on
VF 0. VF driver will be reinitialized
[553.464990] iavf 0000:af:01.0: Failed to communicate with PF; waiting
before retry
[558.903000] iavf 0000:af:01.0: Hardware came out of reset. Attempting
reinit.
[558.984816] iavf 0000:af:01.0: Multiqueue Enabled: Queue pair count = 16
This happens because reset events are ignored in the early states where
the misc irq vector is not initialized yet and communicating with the PF
is through polling the AQ buffer. Fix by scanning the received OP
codes for a reset event and scheduling the reset task if a reset event
is received.
Fixes: 5eae00c57f5e ("i40evf: main driver core")
Reviewed-by: Tony Nguyen <[email protected]>
Signed-off-by: Ahmed Zaki <[email protected]>
---
.../net/ethernet/intel/iavf/iavf_virtchnl.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
index 22f2df7c460b..9d8a5d3adcee 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
@@ -76,6 +76,24 @@ iavf_poll_virtchnl_msg(struct iavf_hw *hw, struct
iavf_arq_event_info *event,
return iavf_status_to_errno(status);
received_op =
(enum virtchnl_ops)le32_to_cpu(event->desc.cookie_high);
+
+ if (received_op == VIRTCHNL_OP_EVENT) {
+ struct iavf_adapter *adapter = hw->back;
+ struct virtchnl_pf_event *vpe =
+ (struct virtchnl_pf_event *)event->msg_buf;
+
+ if (vpe->event != VIRTCHNL_EVENT_RESET_IMPENDING)
+ continue;
+
+ dev_info(&adapter->pdev->dev, "Reset indication
received from the PF\n");
+ if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) {
+ dev_info(&adapter->pdev->dev, "Scheduling reset
task\n");
+ iavf_schedule_reset(adapter,
+ IAVF_FLAG_RESET_PENDING);
+ }
+ return -EIO;
+ }
+
if (op_to_poll == received_op)
break;
}
--
2.34.1