diff options
Diffstat (limited to 'drivers/net/wireless/wavelan_cs.c')
-rw-r--r-- | drivers/net/wireless/wavelan_cs.c | 189 |
1 files changed, 72 insertions, 117 deletions
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 98122f3a4bc2..f7724eb2fa7e 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c | |||
@@ -1005,7 +1005,7 @@ static inline void | |||
1005 | wv_82593_reconfig(struct net_device * dev) | 1005 | wv_82593_reconfig(struct net_device * dev) |
1006 | { | 1006 | { |
1007 | net_local * lp = netdev_priv(dev); | 1007 | net_local * lp = netdev_priv(dev); |
1008 | dev_link_t * link = lp->link; | 1008 | struct pcmcia_device * link = lp->link; |
1009 | unsigned long flags; | 1009 | unsigned long flags; |
1010 | 1010 | ||
1011 | /* Arm the flag, will be cleard in wv_82593_config() */ | 1011 | /* Arm the flag, will be cleard in wv_82593_config() */ |
@@ -3744,16 +3744,16 @@ wv_pcmcia_reset(struct net_device * dev) | |||
3744 | { | 3744 | { |
3745 | int i; | 3745 | int i; |
3746 | conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 }; | 3746 | conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 }; |
3747 | dev_link_t * link = ((net_local *)netdev_priv(dev))->link; | 3747 | struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link; |
3748 | 3748 | ||
3749 | #ifdef DEBUG_CONFIG_TRACE | 3749 | #ifdef DEBUG_CONFIG_TRACE |
3750 | printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name); | 3750 | printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name); |
3751 | #endif | 3751 | #endif |
3752 | 3752 | ||
3753 | i = pcmcia_access_configuration_register(link->handle, ®); | 3753 | i = pcmcia_access_configuration_register(link, ®); |
3754 | if(i != CS_SUCCESS) | 3754 | if(i != CS_SUCCESS) |
3755 | { | 3755 | { |
3756 | cs_error(link->handle, AccessConfigurationRegister, i); | 3756 | cs_error(link, AccessConfigurationRegister, i); |
3757 | return FALSE; | 3757 | return FALSE; |
3758 | } | 3758 | } |
3759 | 3759 | ||
@@ -3764,19 +3764,19 @@ wv_pcmcia_reset(struct net_device * dev) | |||
3764 | 3764 | ||
3765 | reg.Action = CS_WRITE; | 3765 | reg.Action = CS_WRITE; |
3766 | reg.Value = reg.Value | COR_SW_RESET; | 3766 | reg.Value = reg.Value | COR_SW_RESET; |
3767 | i = pcmcia_access_configuration_register(link->handle, ®); | 3767 | i = pcmcia_access_configuration_register(link, ®); |
3768 | if(i != CS_SUCCESS) | 3768 | if(i != CS_SUCCESS) |
3769 | { | 3769 | { |
3770 | cs_error(link->handle, AccessConfigurationRegister, i); | 3770 | cs_error(link, AccessConfigurationRegister, i); |
3771 | return FALSE; | 3771 | return FALSE; |
3772 | } | 3772 | } |
3773 | 3773 | ||
3774 | reg.Action = CS_WRITE; | 3774 | reg.Action = CS_WRITE; |
3775 | reg.Value = COR_LEVEL_IRQ | COR_CONFIG; | 3775 | reg.Value = COR_LEVEL_IRQ | COR_CONFIG; |
3776 | i = pcmcia_access_configuration_register(link->handle, ®); | 3776 | i = pcmcia_access_configuration_register(link, ®); |
3777 | if(i != CS_SUCCESS) | 3777 | if(i != CS_SUCCESS) |
3778 | { | 3778 | { |
3779 | cs_error(link->handle, AccessConfigurationRegister, i); | 3779 | cs_error(link, AccessConfigurationRegister, i); |
3780 | return FALSE; | 3780 | return FALSE; |
3781 | } | 3781 | } |
3782 | 3782 | ||
@@ -3940,9 +3940,8 @@ wv_hw_reset(struct net_device * dev) | |||
3940 | * (called by wavelan_event()) | 3940 | * (called by wavelan_event()) |
3941 | */ | 3941 | */ |
3942 | static inline int | 3942 | static inline int |
3943 | wv_pcmcia_config(dev_link_t * link) | 3943 | wv_pcmcia_config(struct pcmcia_device * link) |
3944 | { | 3944 | { |
3945 | client_handle_t handle = link->handle; | ||
3946 | tuple_t tuple; | 3945 | tuple_t tuple; |
3947 | cisparse_t parse; | 3946 | cisparse_t parse; |
3948 | struct net_device * dev = (struct net_device *) link->priv; | 3947 | struct net_device * dev = (struct net_device *) link->priv; |
@@ -3965,16 +3964,16 @@ wv_pcmcia_config(dev_link_t * link) | |||
3965 | { | 3964 | { |
3966 | tuple.Attributes = 0; | 3965 | tuple.Attributes = 0; |
3967 | tuple.DesiredTuple = CISTPL_CONFIG; | 3966 | tuple.DesiredTuple = CISTPL_CONFIG; |
3968 | i = pcmcia_get_first_tuple(handle, &tuple); | 3967 | i = pcmcia_get_first_tuple(link, &tuple); |
3969 | if(i != CS_SUCCESS) | 3968 | if(i != CS_SUCCESS) |
3970 | break; | 3969 | break; |
3971 | tuple.TupleData = (cisdata_t *)buf; | 3970 | tuple.TupleData = (cisdata_t *)buf; |
3972 | tuple.TupleDataMax = 64; | 3971 | tuple.TupleDataMax = 64; |
3973 | tuple.TupleOffset = 0; | 3972 | tuple.TupleOffset = 0; |
3974 | i = pcmcia_get_tuple_data(handle, &tuple); | 3973 | i = pcmcia_get_tuple_data(link, &tuple); |
3975 | if(i != CS_SUCCESS) | 3974 | if(i != CS_SUCCESS) |
3976 | break; | 3975 | break; |
3977 | i = pcmcia_parse_tuple(handle, &tuple, &parse); | 3976 | i = pcmcia_parse_tuple(link, &tuple, &parse); |
3978 | if(i != CS_SUCCESS) | 3977 | if(i != CS_SUCCESS) |
3979 | break; | 3978 | break; |
3980 | link->conf.ConfigBase = parse.config.base; | 3979 | link->conf.ConfigBase = parse.config.base; |
@@ -3983,19 +3982,16 @@ wv_pcmcia_config(dev_link_t * link) | |||
3983 | while(0); | 3982 | while(0); |
3984 | if(i != CS_SUCCESS) | 3983 | if(i != CS_SUCCESS) |
3985 | { | 3984 | { |
3986 | cs_error(link->handle, ParseTuple, i); | 3985 | cs_error(link, ParseTuple, i); |
3987 | link->state &= ~DEV_CONFIG_PENDING; | ||
3988 | return FALSE; | 3986 | return FALSE; |
3989 | } | 3987 | } |
3990 | 3988 | ||
3991 | /* Configure card */ | ||
3992 | link->state |= DEV_CONFIG; | ||
3993 | do | 3989 | do |
3994 | { | 3990 | { |
3995 | i = pcmcia_request_io(link->handle, &link->io); | 3991 | i = pcmcia_request_io(link, &link->io); |
3996 | if(i != CS_SUCCESS) | 3992 | if(i != CS_SUCCESS) |
3997 | { | 3993 | { |
3998 | cs_error(link->handle, RequestIO, i); | 3994 | cs_error(link, RequestIO, i); |
3999 | break; | 3995 | break; |
4000 | } | 3996 | } |
4001 | 3997 | ||
@@ -4003,10 +3999,10 @@ wv_pcmcia_config(dev_link_t * link) | |||
4003 | * Now allocate an interrupt line. Note that this does not | 3999 | * Now allocate an interrupt line. Note that this does not |
4004 | * actually assign a handler to the interrupt. | 4000 | * actually assign a handler to the interrupt. |
4005 | */ | 4001 | */ |
4006 | i = pcmcia_request_irq(link->handle, &link->irq); | 4002 | i = pcmcia_request_irq(link, &link->irq); |
4007 | if(i != CS_SUCCESS) | 4003 | if(i != CS_SUCCESS) |
4008 | { | 4004 | { |
4009 | cs_error(link->handle, RequestIRQ, i); | 4005 | cs_error(link, RequestIRQ, i); |
4010 | break; | 4006 | break; |
4011 | } | 4007 | } |
4012 | 4008 | ||
@@ -4015,15 +4011,15 @@ wv_pcmcia_config(dev_link_t * link) | |||
4015 | * the I/O windows and the interrupt mapping. | 4011 | * the I/O windows and the interrupt mapping. |
4016 | */ | 4012 | */ |
4017 | link->conf.ConfigIndex = 1; | 4013 | link->conf.ConfigIndex = 1; |
4018 | i = pcmcia_request_configuration(link->handle, &link->conf); | 4014 | i = pcmcia_request_configuration(link, &link->conf); |
4019 | if(i != CS_SUCCESS) | 4015 | if(i != CS_SUCCESS) |
4020 | { | 4016 | { |
4021 | cs_error(link->handle, RequestConfiguration, i); | 4017 | cs_error(link, RequestConfiguration, i); |
4022 | break; | 4018 | break; |
4023 | } | 4019 | } |
4024 | 4020 | ||
4025 | /* | 4021 | /* |
4026 | * Allocate a small memory window. Note that the dev_link_t | 4022 | * Allocate a small memory window. Note that the struct pcmcia_device |
4027 | * structure provides space for one window handle -- if your | 4023 | * structure provides space for one window handle -- if your |
4028 | * device needs several windows, you'll need to keep track of | 4024 | * device needs several windows, you'll need to keep track of |
4029 | * the handles in your private data structure, link->priv. | 4025 | * the handles in your private data structure, link->priv. |
@@ -4031,10 +4027,10 @@ wv_pcmcia_config(dev_link_t * link) | |||
4031 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 4027 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; |
4032 | req.Base = req.Size = 0; | 4028 | req.Base = req.Size = 0; |
4033 | req.AccessSpeed = mem_speed; | 4029 | req.AccessSpeed = mem_speed; |
4034 | i = pcmcia_request_window(&link->handle, &req, &link->win); | 4030 | i = pcmcia_request_window(&link, &req, &link->win); |
4035 | if(i != CS_SUCCESS) | 4031 | if(i != CS_SUCCESS) |
4036 | { | 4032 | { |
4037 | cs_error(link->handle, RequestWindow, i); | 4033 | cs_error(link, RequestWindow, i); |
4038 | break; | 4034 | break; |
4039 | } | 4035 | } |
4040 | 4036 | ||
@@ -4046,7 +4042,7 @@ wv_pcmcia_config(dev_link_t * link) | |||
4046 | i = pcmcia_map_mem_page(link->win, &mem); | 4042 | i = pcmcia_map_mem_page(link->win, &mem); |
4047 | if(i != CS_SUCCESS) | 4043 | if(i != CS_SUCCESS) |
4048 | { | 4044 | { |
4049 | cs_error(link->handle, MapMemPage, i); | 4045 | cs_error(link, MapMemPage, i); |
4050 | break; | 4046 | break; |
4051 | } | 4047 | } |
4052 | 4048 | ||
@@ -4060,7 +4056,7 @@ wv_pcmcia_config(dev_link_t * link) | |||
4060 | lp->mem, dev->irq, (u_int) dev->base_addr); | 4056 | lp->mem, dev->irq, (u_int) dev->base_addr); |
4061 | #endif | 4057 | #endif |
4062 | 4058 | ||
4063 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | 4059 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
4064 | i = register_netdev(dev); | 4060 | i = register_netdev(dev); |
4065 | if(i != 0) | 4061 | if(i != 0) |
4066 | { | 4062 | { |
@@ -4072,7 +4068,6 @@ wv_pcmcia_config(dev_link_t * link) | |||
4072 | } | 4068 | } |
4073 | while(0); /* Humm... Disguised goto !!! */ | 4069 | while(0); /* Humm... Disguised goto !!! */ |
4074 | 4070 | ||
4075 | link->state &= ~DEV_CONFIG_PENDING; | ||
4076 | /* If any step failed, release any partially configured state */ | 4071 | /* If any step failed, release any partially configured state */ |
4077 | if(i != 0) | 4072 | if(i != 0) |
4078 | { | 4073 | { |
@@ -4081,7 +4076,7 @@ wv_pcmcia_config(dev_link_t * link) | |||
4081 | } | 4076 | } |
4082 | 4077 | ||
4083 | strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name); | 4078 | strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name); |
4084 | link->dev = &((net_local *) netdev_priv(dev))->node; | 4079 | link->dev_node = &((net_local *) netdev_priv(dev))->node; |
4085 | 4080 | ||
4086 | #ifdef DEBUG_CONFIG_TRACE | 4081 | #ifdef DEBUG_CONFIG_TRACE |
4087 | printk(KERN_DEBUG "<-wv_pcmcia_config()\n"); | 4082 | printk(KERN_DEBUG "<-wv_pcmcia_config()\n"); |
@@ -4096,26 +4091,20 @@ wv_pcmcia_config(dev_link_t * link) | |||
4096 | * still open, this will be postponed until it is closed. | 4091 | * still open, this will be postponed until it is closed. |
4097 | */ | 4092 | */ |
4098 | static void | 4093 | static void |
4099 | wv_pcmcia_release(dev_link_t *link) | 4094 | wv_pcmcia_release(struct pcmcia_device *link) |
4100 | { | 4095 | { |
4101 | struct net_device * dev = (struct net_device *) link->priv; | 4096 | struct net_device * dev = (struct net_device *) link->priv; |
4102 | net_local * lp = netdev_priv(dev); | 4097 | net_local * lp = netdev_priv(dev); |
4103 | 4098 | ||
4104 | #ifdef DEBUG_CONFIG_TRACE | 4099 | #ifdef DEBUG_CONFIG_TRACE |
4105 | printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link); | 4100 | printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link); |
4106 | #endif | 4101 | #endif |
4107 | 4102 | ||
4108 | /* Don't bother checking to see if these succeed or not */ | 4103 | iounmap(lp->mem); |
4109 | iounmap(lp->mem); | 4104 | pcmcia_disable_device(link); |
4110 | pcmcia_release_window(link->win); | ||
4111 | pcmcia_release_configuration(link->handle); | ||
4112 | pcmcia_release_io(link->handle, &link->io); | ||
4113 | pcmcia_release_irq(link->handle, &link->irq); | ||
4114 | |||
4115 | link->state &= ~DEV_CONFIG; | ||
4116 | 4105 | ||
4117 | #ifdef DEBUG_CONFIG_TRACE | 4106 | #ifdef DEBUG_CONFIG_TRACE |
4118 | printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); | 4107 | printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); |
4119 | #endif | 4108 | #endif |
4120 | } | 4109 | } |
4121 | 4110 | ||
@@ -4479,7 +4468,7 @@ static int | |||
4479 | wavelan_open(struct net_device * dev) | 4468 | wavelan_open(struct net_device * dev) |
4480 | { | 4469 | { |
4481 | net_local * lp = netdev_priv(dev); | 4470 | net_local * lp = netdev_priv(dev); |
4482 | dev_link_t * link = lp->link; | 4471 | struct pcmcia_device * link = lp->link; |
4483 | kio_addr_t base = dev->base_addr; | 4472 | kio_addr_t base = dev->base_addr; |
4484 | 4473 | ||
4485 | #ifdef DEBUG_CALLBACK_TRACE | 4474 | #ifdef DEBUG_CALLBACK_TRACE |
@@ -4533,7 +4522,7 @@ wavelan_open(struct net_device * dev) | |||
4533 | static int | 4522 | static int |
4534 | wavelan_close(struct net_device * dev) | 4523 | wavelan_close(struct net_device * dev) |
4535 | { | 4524 | { |
4536 | dev_link_t * link = ((net_local *)netdev_priv(dev))->link; | 4525 | struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link; |
4537 | kio_addr_t base = dev->base_addr; | 4526 | kio_addr_t base = dev->base_addr; |
4538 | 4527 | ||
4539 | #ifdef DEBUG_CALLBACK_TRACE | 4528 | #ifdef DEBUG_CALLBACK_TRACE |
@@ -4587,45 +4576,36 @@ wavelan_close(struct net_device * dev) | |||
4587 | * card insertion event. | 4576 | * card insertion event. |
4588 | */ | 4577 | */ |
4589 | static int | 4578 | static int |
4590 | wavelan_attach(struct pcmcia_device *p_dev) | 4579 | wavelan_probe(struct pcmcia_device *p_dev) |
4591 | { | 4580 | { |
4592 | dev_link_t * link; /* Info for cardmgr */ | ||
4593 | struct net_device * dev; /* Interface generic data */ | 4581 | struct net_device * dev; /* Interface generic data */ |
4594 | net_local * lp; /* Interface specific data */ | 4582 | net_local * lp; /* Interface specific data */ |
4583 | int ret; | ||
4595 | 4584 | ||
4596 | #ifdef DEBUG_CALLBACK_TRACE | 4585 | #ifdef DEBUG_CALLBACK_TRACE |
4597 | printk(KERN_DEBUG "-> wavelan_attach()\n"); | 4586 | printk(KERN_DEBUG "-> wavelan_attach()\n"); |
4598 | #endif | 4587 | #endif |
4599 | 4588 | ||
4600 | /* Initialize the dev_link_t structure */ | ||
4601 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); | ||
4602 | if (!link) return -ENOMEM; | ||
4603 | |||
4604 | /* The io structure describes IO port mapping */ | 4589 | /* The io structure describes IO port mapping */ |
4605 | link->io.NumPorts1 = 8; | 4590 | p_dev->io.NumPorts1 = 8; |
4606 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 4591 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
4607 | link->io.IOAddrLines = 3; | 4592 | p_dev->io.IOAddrLines = 3; |
4608 | 4593 | ||
4609 | /* Interrupt setup */ | 4594 | /* Interrupt setup */ |
4610 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | 4595 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; |
4611 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 4596 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
4612 | link->irq.Handler = wavelan_interrupt; | 4597 | p_dev->irq.Handler = wavelan_interrupt; |
4613 | 4598 | ||
4614 | /* General socket configuration */ | 4599 | /* General socket configuration */ |
4615 | link->conf.Attributes = CONF_ENABLE_IRQ; | 4600 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; |
4616 | link->conf.Vcc = 50; | 4601 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
4617 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
4618 | |||
4619 | /* Chain drivers */ | ||
4620 | link->next = NULL; | ||
4621 | 4602 | ||
4622 | /* Allocate the generic data structure */ | 4603 | /* Allocate the generic data structure */ |
4623 | dev = alloc_etherdev(sizeof(net_local)); | 4604 | dev = alloc_etherdev(sizeof(net_local)); |
4624 | if (!dev) { | 4605 | if (!dev) |
4625 | kfree(link); | ||
4626 | return -ENOMEM; | 4606 | return -ENOMEM; |
4627 | } | 4607 | |
4628 | link->priv = link->irq.Instance = dev; | 4608 | p_dev->priv = p_dev->irq.Instance = dev; |
4629 | 4609 | ||
4630 | lp = netdev_priv(dev); | 4610 | lp = netdev_priv(dev); |
4631 | 4611 | ||
@@ -4642,7 +4622,6 @@ wavelan_attach(struct pcmcia_device *p_dev) | |||
4642 | spin_lock_init(&lp->spinlock); | 4622 | spin_lock_init(&lp->spinlock); |
4643 | 4623 | ||
4644 | /* back links */ | 4624 | /* back links */ |
4645 | lp->link = link; | ||
4646 | lp->dev = dev; | 4625 | lp->dev = dev; |
4647 | 4626 | ||
4648 | /* wavelan NET3 callbacks */ | 4627 | /* wavelan NET3 callbacks */ |
@@ -4668,15 +4647,18 @@ wavelan_attach(struct pcmcia_device *p_dev) | |||
4668 | /* Other specific data */ | 4647 | /* Other specific data */ |
4669 | dev->mtu = WAVELAN_MTU; | 4648 | dev->mtu = WAVELAN_MTU; |
4670 | 4649 | ||
4671 | link->handle = p_dev; | 4650 | ret = wv_pcmcia_config(p_dev); |
4672 | p_dev->instance = link; | 4651 | if (ret) |
4652 | return ret; | ||
4673 | 4653 | ||
4674 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 4654 | ret = wv_hw_config(dev); |
4675 | if(wv_pcmcia_config(link) && | 4655 | if (ret) { |
4676 | wv_hw_config(dev)) | ||
4677 | wv_init_info(dev); | ||
4678 | else | ||
4679 | dev->irq = 0; | 4656 | dev->irq = 0; |
4657 | pcmcia_disable_device(p_dev); | ||
4658 | return ret; | ||
4659 | } | ||
4660 | |||
4661 | wv_init_info(dev); | ||
4680 | 4662 | ||
4681 | #ifdef DEBUG_CALLBACK_TRACE | 4663 | #ifdef DEBUG_CALLBACK_TRACE |
4682 | printk(KERN_DEBUG "<- wavelan_attach()\n"); | 4664 | printk(KERN_DEBUG "<- wavelan_attach()\n"); |
@@ -4693,25 +4675,14 @@ wavelan_attach(struct pcmcia_device *p_dev) | |||
4693 | * is released. | 4675 | * is released. |
4694 | */ | 4676 | */ |
4695 | static void | 4677 | static void |
4696 | wavelan_detach(struct pcmcia_device *p_dev) | 4678 | wavelan_detach(struct pcmcia_device *link) |
4697 | { | 4679 | { |
4698 | dev_link_t *link = dev_to_instance(p_dev); | ||
4699 | |||
4700 | #ifdef DEBUG_CALLBACK_TRACE | 4680 | #ifdef DEBUG_CALLBACK_TRACE |
4701 | printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); | 4681 | printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); |
4702 | #endif | 4682 | #endif |
4703 | 4683 | ||
4704 | /* | 4684 | /* Some others haven't done their job : give them another chance */ |
4705 | * If the device is currently configured and active, we won't | 4685 | wv_pcmcia_release(link); |
4706 | * actually delete it yet. Instead, it is marked so that when the | ||
4707 | * release() function is called, that will trigger a proper | ||
4708 | * detach(). | ||
4709 | */ | ||
4710 | if(link->state & DEV_CONFIG) | ||
4711 | { | ||
4712 | /* Some others haven't done their job : give them another chance */ | ||
4713 | wv_pcmcia_release(link); | ||
4714 | } | ||
4715 | 4686 | ||
4716 | /* Free pieces */ | 4687 | /* Free pieces */ |
4717 | if(link->priv) | 4688 | if(link->priv) |
@@ -4720,23 +4691,21 @@ wavelan_detach(struct pcmcia_device *p_dev) | |||
4720 | 4691 | ||
4721 | /* Remove ourselves from the kernel list of ethernet devices */ | 4692 | /* Remove ourselves from the kernel list of ethernet devices */ |
4722 | /* Warning : can't be called from interrupt, timer or wavelan_close() */ | 4693 | /* Warning : can't be called from interrupt, timer or wavelan_close() */ |
4723 | if (link->dev) | 4694 | if (link->dev_node) |
4724 | unregister_netdev(dev); | 4695 | unregister_netdev(dev); |
4725 | link->dev = NULL; | 4696 | link->dev_node = NULL; |
4726 | ((net_local *)netdev_priv(dev))->link = NULL; | 4697 | ((net_local *)netdev_priv(dev))->link = NULL; |
4727 | ((net_local *)netdev_priv(dev))->dev = NULL; | 4698 | ((net_local *)netdev_priv(dev))->dev = NULL; |
4728 | free_netdev(dev); | 4699 | free_netdev(dev); |
4729 | } | 4700 | } |
4730 | kfree(link); | ||
4731 | 4701 | ||
4732 | #ifdef DEBUG_CALLBACK_TRACE | 4702 | #ifdef DEBUG_CALLBACK_TRACE |
4733 | printk(KERN_DEBUG "<- wavelan_detach()\n"); | 4703 | printk(KERN_DEBUG "<- wavelan_detach()\n"); |
4734 | #endif | 4704 | #endif |
4735 | } | 4705 | } |
4736 | 4706 | ||
4737 | static int wavelan_suspend(struct pcmcia_device *p_dev) | 4707 | static int wavelan_suspend(struct pcmcia_device *link) |
4738 | { | 4708 | { |
4739 | dev_link_t *link = dev_to_instance(p_dev); | ||
4740 | struct net_device * dev = (struct net_device *) link->priv; | 4709 | struct net_device * dev = (struct net_device *) link->priv; |
4741 | 4710 | ||
4742 | /* NB: wavelan_close will be called, but too late, so we are | 4711 | /* NB: wavelan_close will be called, but too late, so we are |
@@ -4748,36 +4717,22 @@ static int wavelan_suspend(struct pcmcia_device *p_dev) | |||
4748 | /* Stop receiving new messages and wait end of transmission */ | 4717 | /* Stop receiving new messages and wait end of transmission */ |
4749 | wv_ru_stop(dev); | 4718 | wv_ru_stop(dev); |
4750 | 4719 | ||
4720 | if (link->open) | ||
4721 | netif_device_detach(dev); | ||
4722 | |||
4751 | /* Power down the module */ | 4723 | /* Power down the module */ |
4752 | hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT)); | 4724 | hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT)); |
4753 | 4725 | ||
4754 | /* The card is now suspended */ | ||
4755 | link->state |= DEV_SUSPEND; | ||
4756 | |||
4757 | if(link->state & DEV_CONFIG) | ||
4758 | { | ||
4759 | if(link->open) | ||
4760 | netif_device_detach(dev); | ||
4761 | pcmcia_release_configuration(link->handle); | ||
4762 | } | ||
4763 | |||
4764 | return 0; | 4726 | return 0; |
4765 | } | 4727 | } |
4766 | 4728 | ||
4767 | static int wavelan_resume(struct pcmcia_device *p_dev) | 4729 | static int wavelan_resume(struct pcmcia_device *link) |
4768 | { | 4730 | { |
4769 | dev_link_t *link = dev_to_instance(p_dev); | ||
4770 | struct net_device * dev = (struct net_device *) link->priv; | 4731 | struct net_device * dev = (struct net_device *) link->priv; |
4771 | 4732 | ||
4772 | link->state &= ~DEV_SUSPEND; | 4733 | if (link->open) { |
4773 | if(link->state & DEV_CONFIG) | 4734 | wv_hw_reset(dev); |
4774 | { | 4735 | netif_device_attach(dev); |
4775 | pcmcia_request_configuration(link->handle, &link->conf); | ||
4776 | if(link->open) /* If RESET -> True, If RESUME -> False ? */ | ||
4777 | { | ||
4778 | wv_hw_reset(dev); | ||
4779 | netif_device_attach(dev); | ||
4780 | } | ||
4781 | } | 4736 | } |
4782 | 4737 | ||
4783 | return 0; | 4738 | return 0; |
@@ -4798,7 +4753,7 @@ static struct pcmcia_driver wavelan_driver = { | |||
4798 | .drv = { | 4753 | .drv = { |
4799 | .name = "wavelan_cs", | 4754 | .name = "wavelan_cs", |
4800 | }, | 4755 | }, |
4801 | .probe = wavelan_attach, | 4756 | .probe = wavelan_probe, |
4802 | .remove = wavelan_detach, | 4757 | .remove = wavelan_detach, |
4803 | .id_table = wavelan_ids, | 4758 | .id_table = wavelan_ids, |
4804 | .suspend = wavelan_suspend, | 4759 | .suspend = wavelan_suspend, |