--- x/drivers/net/netdevsim/netdev.c +++ y/drivers/net/netdevsim/netdev.c @@ -709,10 +709,14 @@ static struct nsim_rq *nsim_queue_alloc( static void nsim_queue_free(struct net_device *dev, struct nsim_rq *rq) { + struct netdevsim *ns = netdev_priv(dev); + hrtimer_cancel(&rq->napi_timer); - local_bh_disable(); - dev_dstats_rx_dropped_add(dev, rq->skb_queue.qlen); - local_bh_enable(); + if (ns->registed) { + local_bh_disable(); + dev_dstats_rx_dropped_add(dev, rq->skb_queue.qlen); + local_bh_enable(); + } skb_queue_purge_reason(&rq->skb_queue, SKB_DROP_REASON_QUEUE_PURGE); kfree(rq); } @@ -981,6 +985,7 @@ err_free_prev: while (i--) kfree(ns->rq[i]); kfree(ns->rq); + ns->rq = NULL; return -ENOMEM; } @@ -989,6 +994,8 @@ static void nsim_queue_uninit(struct net struct net_device *dev = ns->netdev; int i; + if (!ns->rq) + return; for (i = 0; i < dev->num_rx_queues; i++) nsim_queue_free(dev, ns->rq[i]); @@ -1001,6 +1008,7 @@ static int nsim_init_netdevsim(struct ne struct mock_phc *phc; int err; + ns->registed = 0; phc = mock_phc_create(&ns->nsim_bus_dev->dev); if (IS_ERR(phc)) return PTR_ERR(phc); @@ -1038,6 +1046,7 @@ static int nsim_init_netdevsim(struct ne &ns->nn)) ns->nb.notifier_call = NULL; } + ns->registed = 1; return 0; --- x/drivers/net/netdevsim/netdevsim.h +++ y/drivers/net/netdevsim/netdevsim.h @@ -106,6 +106,7 @@ struct netdevsim { struct mock_phc *phc; struct nsim_rq **rq; + int registed; int rq_reset_mode; struct nsim_bus_dev *nsim_bus_dev; --- x/net/ipv4/udp_tunnel_nic.c +++ y/net/ipv4/udp_tunnel_nic.c @@ -733,7 +733,8 @@ static void udp_tunnel_nic_device_sync_w struct udp_tunnel_nic *utn = container_of(work, struct udp_tunnel_nic, work); - rtnl_lock(); + if (!rtnl_trylock()) + return; mutex_lock(&utn->lock); utn->work_pending = 0; @@ -782,6 +783,8 @@ static void udp_tunnel_nic_free(struct u for (i = 0; i < utn->n_tables; i++) kfree(utn->entries[i]); + disable_work(&utn->work); + cancel_work_sync(&utn->work); kfree(utn); }