diff options
author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2008-02-01 08:22:48 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-02-03 07:25:58 -0500 |
commit | 80a9fad8e89a23c31bab9c228a88a391c4f8d698 (patch) | |
tree | 2c6d22ee53f9fca8a6b0fadc422178397eb7a07e /drivers/net/ucc_geth.c | |
parent | f67c6275185216b47ee50c8c122adee3c562bce7 (diff) |
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 <avorontsov@ru.mvista.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ucc_geth.c')
-rw-r--r-- | drivers/net/ucc_geth.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 4ffd8739f8b7..e41da4670d0b 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) | |||
2084 | if (!ugeth) | 2084 | if (!ugeth) |
2085 | return; | 2085 | return; |
2086 | 2086 | ||
2087 | if (ugeth->uccf) | 2087 | if (ugeth->uccf) { |
2088 | ucc_fast_free(ugeth->uccf); | 2088 | ucc_fast_free(ugeth->uccf); |
2089 | ugeth->uccf = NULL; | ||
2090 | } | ||
2089 | 2091 | ||
2090 | if (ugeth->p_thread_data_tx) { | 2092 | if (ugeth->p_thread_data_tx) { |
2091 | qe_muram_free(ugeth->thread_dat_tx_offset); | 2093 | qe_muram_free(ugeth->thread_dat_tx_offset); |
@@ -2305,10 +2307,6 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth) | |||
2305 | ug_info = ugeth->ug_info; | 2307 | ug_info = ugeth->ug_info; |
2306 | uf_info = &ug_info->uf_info; | 2308 | uf_info = &ug_info->uf_info; |
2307 | 2309 | ||
2308 | /* Create CQs for hash tables */ | ||
2309 | INIT_LIST_HEAD(&ugeth->group_hash_q); | ||
2310 | INIT_LIST_HEAD(&ugeth->ind_hash_q); | ||
2311 | |||
2312 | if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) || | 2310 | if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) || |
2313 | (uf_info->bd_mem_part == MEM_PART_MURAM))) { | 2311 | (uf_info->bd_mem_part == MEM_PART_MURAM))) { |
2314 | if (netif_msg_probe(ugeth)) | 2312 | if (netif_msg_probe(ugeth)) |
@@ -3990,6 +3988,10 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
3990 | ugeth = netdev_priv(dev); | 3988 | ugeth = netdev_priv(dev); |
3991 | spin_lock_init(&ugeth->lock); | 3989 | spin_lock_init(&ugeth->lock); |
3992 | 3990 | ||
3991 | /* Create CQs for hash tables */ | ||
3992 | INIT_LIST_HEAD(&ugeth->group_hash_q); | ||
3993 | INIT_LIST_HEAD(&ugeth->ind_hash_q); | ||
3994 | |||
3993 | dev_set_drvdata(device, dev); | 3995 | dev_set_drvdata(device, dev); |
3994 | 3996 | ||
3995 | /* Set the dev->base_addr to the gfar reg region */ | 3997 | /* Set the dev->base_addr to the gfar reg region */ |
@@ -4040,9 +4042,10 @@ static int ucc_geth_remove(struct of_device* ofdev) | |||
4040 | struct net_device *dev = dev_get_drvdata(device); | 4042 | struct net_device *dev = dev_get_drvdata(device); |
4041 | struct ucc_geth_private *ugeth = netdev_priv(dev); | 4043 | struct ucc_geth_private *ugeth = netdev_priv(dev); |
4042 | 4044 | ||
4043 | dev_set_drvdata(device, NULL); | 4045 | unregister_netdev(dev); |
4044 | ucc_geth_memclean(ugeth); | ||
4045 | free_netdev(dev); | 4046 | free_netdev(dev); |
4047 | ucc_geth_memclean(ugeth); | ||
4048 | dev_set_drvdata(device, NULL); | ||
4046 | 4049 | ||
4047 | return 0; | 4050 | return 0; |
4048 | } | 4051 | } |