spin_unlock_bh(&nn->reconfig_lock);
 }
 
-/**
- * nfp_net_reconfig() - Reconfigure the firmware
- * @nn:      NFP Net device to reconfigure
- * @update:  The value for the update field in the BAR config
- *
- * Write the update word to the BAR and ping the reconfig queue.  The
- * poll until the firmware has acknowledged the update by zeroing the
- * update word.
- *
- * Return: Negative errno on error, 0 on success
- */
-int nfp_net_reconfig(struct nfp_net *nn, u32 update)
+static void nfp_net_reconfig_sync_enter(struct nfp_net *nn)
 {
        bool cancelled_timer = false;
        u32 pre_posted_requests;
-       int ret;
 
        spin_lock_bh(&nn->reconfig_lock);
 
        nn->reconfig_sync_present = true;
 
        if (nn->reconfig_timer_active) {
-               del_timer(&nn->reconfig_timer);
                nn->reconfig_timer_active = false;
                cancelled_timer = true;
        }
 
        spin_unlock_bh(&nn->reconfig_lock);
 
-       if (cancelled_timer)
+       if (cancelled_timer) {
+               del_timer_sync(&nn->reconfig_timer);
                nfp_net_reconfig_wait(nn, nn->reconfig_timer.expires);
+       }
 
        /* Run the posted reconfigs which were issued before we started */
        if (pre_posted_requests) {
                nfp_net_reconfig_start(nn, pre_posted_requests);
                nfp_net_reconfig_wait(nn, jiffies + HZ * NFP_NET_POLL_TIMEOUT);
        }
+}
+
+static void nfp_net_reconfig_wait_posted(struct nfp_net *nn)
+{
+       nfp_net_reconfig_sync_enter(nn);
+
+       spin_lock_bh(&nn->reconfig_lock);
+       nn->reconfig_sync_present = false;
+       spin_unlock_bh(&nn->reconfig_lock);
+}
+
+/**
+ * nfp_net_reconfig() - Reconfigure the firmware
+ * @nn:      NFP Net device to reconfigure
+ * @update:  The value for the update field in the BAR config
+ *
+ * Write the update word to the BAR and ping the reconfig queue.  The
+ * poll until the firmware has acknowledged the update by zeroing the
+ * update word.
+ *
+ * Return: Negative errno on error, 0 on success
+ */
+int nfp_net_reconfig(struct nfp_net *nn, u32 update)
+{
+       int ret;
+
+       nfp_net_reconfig_sync_enter(nn);
 
        nfp_net_reconfig_start(nn, update);
        ret = nfp_net_reconfig_wait(nn, jiffies + HZ * NFP_NET_POLL_TIMEOUT);
  */
 void nfp_net_free(struct nfp_net *nn)
 {
+       WARN_ON(timer_pending(&nn->reconfig_timer) || nn->reconfig_posted);
        if (nn->dp.netdev)
                free_netdev(nn->dp.netdev);
        else
                return;
 
        unregister_netdev(nn->dp.netdev);
+       nfp_net_reconfig_wait_posted(nn);
 }