From: Anton Vorontsov - uccf should be set to NULL to not double-free memory on subsequent calls; - ind_hash_q and group_hash_q lists should be initialized in the probe() function, instead of struct_init() (called by open()), otherwise there will be an oops if ucc_geth_driver removed prior 'ifconfig ethX up'; - add unregister_netdev(); - reorder geth_remove() steps. Signed-off-by: Anton Vorontsov Signed-off-by: Andrew Morton --- drivers/net/ucc_geth.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff -puN drivers/net/ucc_geth.c~ucc_geth-fix-module-removal drivers/net/ucc_geth.c --- a/drivers/net/ucc_geth.c~ucc_geth-fix-module-removal +++ a/drivers/net/ucc_geth.c @@ -2084,8 +2084,10 @@ static void ucc_geth_memclean(struct ucc if (!ugeth) return; - if (ugeth->uccf) + if (ugeth->uccf) { ucc_fast_free(ugeth->uccf); + ugeth->uccf = NULL; + } if (ugeth->p_thread_data_tx) { qe_muram_free(ugeth->thread_dat_tx_offset); @@ -2305,10 +2307,6 @@ static int ucc_struct_init(struct ucc_ge ug_info = ugeth->ug_info; uf_info = &ug_info->uf_info; - /* Create CQs for hash tables */ - INIT_LIST_HEAD(&ugeth->group_hash_q); - INIT_LIST_HEAD(&ugeth->ind_hash_q); - if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) || (uf_info->bd_mem_part == MEM_PART_MURAM))) { if (netif_msg_probe(ugeth)) @@ -3943,6 +3941,10 @@ static int ucc_geth_probe(struct of_devi ugeth = netdev_priv(dev); spin_lock_init(&ugeth->lock); + /* Create CQs for hash tables */ + INIT_LIST_HEAD(&ugeth->group_hash_q); + INIT_LIST_HEAD(&ugeth->ind_hash_q); + dev_set_drvdata(device, dev); /* Set the dev->base_addr to the gfar reg region */ @@ -3993,9 +3995,10 @@ static int ucc_geth_remove(struct of_dev struct net_device *dev = dev_get_drvdata(device); struct ucc_geth_private *ugeth = netdev_priv(dev); - dev_set_drvdata(device, NULL); - ucc_geth_memclean(ugeth); + unregister_netdev(dev); free_netdev(dev); + ucc_geth_memclean(ugeth); + dev_set_drvdata(device, NULL); return 0; } _