+static void bnxt_dev_cleanup(struct bnxt *bp)
+{
+ bnxt_set_hwrm_link_config(bp, false);
+ bp->link_info.link_up = 0;
+ if (bp->dev_stopped == 0)
+ bnxt_dev_stop_op(bp->eth_dev);
+
+ bnxt_uninit_resources(bp, true);
+}
+
+static int bnxt_restore_filters(struct bnxt *bp)
+{
+ struct rte_eth_dev *dev = bp->eth_dev;
+ int ret = 0;
+
+ if (dev->data->all_multicast)
+ ret = bnxt_allmulticast_enable_op(dev);
+ if (dev->data->promiscuous)
+ ret = bnxt_promiscuous_enable_op(dev);
+
+ /* TODO restore other filters as well */
+ return ret;
+}
+
+static void bnxt_dev_recover(void *arg)
+{
+ struct bnxt *bp = arg;
+ int timeout = bp->fw_reset_max_msecs;
+ int rc = 0;
+
+ do {
+ rc = bnxt_hwrm_ver_get(bp);
+ if (rc == 0)
+ break;
+ rte_delay_ms(BNXT_FW_READY_WAIT_INTERVAL);
+ timeout -= BNXT_FW_READY_WAIT_INTERVAL;
+ } while (rc && timeout);
+
+ if (rc) {
+ PMD_DRV_LOG(ERR, "FW is not Ready after reset\n");
+ goto err;
+ }
+
+ rc = bnxt_init_resources(bp, true);
+ if (rc) {
+ PMD_DRV_LOG(ERR,
+ "Failed to initialize resources after reset\n");
+ goto err;
+ }
+ /* clear reset flag as the device is initialized now */
+ bp->flags &= ~BNXT_FLAG_FW_RESET;
+
+ rc = bnxt_dev_start_op(bp->eth_dev);
+ if (rc) {
+ PMD_DRV_LOG(ERR, "Failed to start port after reset\n");
+ goto err;
+ }
+
+ rc = bnxt_restore_filters(bp);
+ if (rc)
+ goto err;
+
+ PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
+ return;
+err:
+ bp->flags |= BNXT_FLAG_FATAL_ERROR;
+ bnxt_uninit_resources(bp, false);
+ PMD_DRV_LOG(ERR, "Failed to recover from FW reset\n");
+}
+
+void bnxt_dev_reset_and_resume(void *arg)
+{
+ struct bnxt *bp = arg;
+ int rc;
+
+ bnxt_dev_cleanup(bp);
+
+ rc = rte_eal_alarm_set(US_PER_MS * bp->fw_reset_min_msecs,
+ bnxt_dev_recover, (void *)bp);
+ if (rc)
+ PMD_DRV_LOG(ERR, "Error setting recovery alarm");
+}
+