struct ib_device                ibdev;
        struct list_head                list;
        unsigned long                   flags;
-#define BNXT_RE_FLAG_NETDEV_REGISTERED 0
-#define BNXT_RE_FLAG_IBDEV_REGISTERED  1
-#define BNXT_RE_FLAG_GOT_MSIX          2
-#define BNXT_RE_FLAG_RCFW_CHANNEL_EN   8
-#define BNXT_RE_FLAG_QOS_WORK_REG      16
+#define BNXT_RE_FLAG_NETDEV_REGISTERED         0
+#define BNXT_RE_FLAG_IBDEV_REGISTERED          1
+#define BNXT_RE_FLAG_GOT_MSIX                  2
+#define BNXT_RE_FLAG_HAVE_L2_REF               3
+#define BNXT_RE_FLAG_RCFW_CHANNEL_EN           4
+#define BNXT_RE_FLAG_QOS_WORK_REG              5
+#define BNXT_RE_FLAG_TASK_IN_PROG              6
        struct net_device               *netdev;
        unsigned int                    version, major, minor;
        struct bnxt_en_dev              *en_dev;
 
        default:
                break;
        }
+       smp_mb__before_atomic();
+       clear_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags);
        kfree(re_work);
 }
 
                break;
 
        case NETDEV_UNREGISTER:
+               /* netdev notifier will call NETDEV_UNREGISTER again later since
+                * we are still holding the reference to the netdev
+                */
+               if (test_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags))
+                       goto exit;
                bnxt_re_ib_unreg(rdev, false);
                bnxt_re_remove_one(rdev);
                bnxt_re_dev_unreg(rdev);
                        re_work->vlan_dev = (real_dev == netdev ?
                                             NULL : netdev);
                        INIT_WORK(&re_work->work, bnxt_re_task);
+                       set_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags);
                        queue_work(bnxt_re_wq, &re_work->work);
                }
        }