From: Anton Vorontsov Date: Fri, 1 Feb 2008 13:22:48 +0000 (+0300) Subject: ucc_geth: fix module removal X-Git-Tag: v2.6.25-rc1~1065^2~64 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80a9fad8e89a23c31bab9c228a88a391c4f8d698;p=linux-2.6 ucc_geth: fix module removal - 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: Jeff Garzik Signed-off-by: David S. Miller --- diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 4ffd8739f8..e41da4670d 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -2084,8 +2084,10 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth) 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_geth_private *ugeth) 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)) @@ -3990,6 +3988,10 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma 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 */ @@ -4040,9 +4042,10 @@ static int ucc_geth_remove(struct of_device* ofdev) 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; }