X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Fspectrum_cs.c;h=fee4be1ce810af9528ee1ad802513504d10005c9;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=54fe4e4eaf5bdf07835c3374e87a91c22eeb3f4f;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 54fe4e4ea..fee4be1ce 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -63,7 +63,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket /* PCMCIA specific device information (goes in the card field of * struct orinoco_private */ struct orinoco_pccard { - struct pcmcia_device *p_dev; + dev_link_t link; dev_node_t node; }; @@ -71,8 +71,8 @@ struct orinoco_pccard { /* Function prototypes */ /********************************************************************/ -static int spectrum_cs_config(struct pcmcia_device *link); -static void spectrum_cs_release(struct pcmcia_device *link); +static void spectrum_cs_config(dev_link_t *link); +static void spectrum_cs_release(dev_link_t *link); /********************************************************************/ /* Firmware downloader */ @@ -147,7 +147,7 @@ struct pdi { __le16 _len; /* length of ID and data, in words */ __le16 _id; /* record ID */ char data[0]; /* plug data */ -} __attribute__ ((packed)); +} __attribute__ ((packed));; /* Functions for access to little-endian data */ @@ -238,14 +238,14 @@ spectrum_aux_open(hermes_t *hw) * If IDLE is 1, stop the firmware, so that it can be safely rewritten. */ static int -spectrum_reset(struct pcmcia_device *link, int idle) +spectrum_reset(dev_link_t *link, int idle) { int last_ret, last_fn; conf_reg_t reg; u_int save_cor; /* Doing it if hardware is gone is guaranteed crash */ - if (!pcmcia_dev_present(link)) + if (!(link->state & DEV_CONFIG)) return -ENODEV; /* Save original COR value */ @@ -253,7 +253,7 @@ spectrum_reset(struct pcmcia_device *link, int idle) reg.Action = CS_READ; reg.Offset = CISREG_COR; CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link, ®)); + pcmcia_access_configuration_register(link->handle, ®)); save_cor = reg.Value; /* Soft-Reset card */ @@ -261,14 +261,14 @@ spectrum_reset(struct pcmcia_device *link, int idle) reg.Offset = CISREG_COR; reg.Value = (save_cor | COR_SOFT_RESET); CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link, ®)); + pcmcia_access_configuration_register(link->handle, ®)); udelay(1000); /* Read CCSR */ reg.Action = CS_READ; reg.Offset = CISREG_CCSR; CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link, ®)); + pcmcia_access_configuration_register(link->handle, ®)); /* * Start or stop the firmware. Memory width bit should be @@ -278,7 +278,7 @@ spectrum_reset(struct pcmcia_device *link, int idle) reg.Offset = CISREG_CCSR; reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16); CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link, ®)); + pcmcia_access_configuration_register(link->handle, ®)); udelay(1000); /* Restore original COR configuration index */ @@ -286,12 +286,12 @@ spectrum_reset(struct pcmcia_device *link, int idle) reg.Offset = CISREG_COR; reg.Value = (save_cor & ~COR_SOFT_RESET); CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link, ®)); + pcmcia_access_configuration_register(link->handle, ®)); udelay(1000); return 0; cs_failed: - cs_error(link, last_fn, last_ret); + cs_error(link->handle, last_fn, last_ret); return -ENODEV; } @@ -441,7 +441,7 @@ spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block) * care of the PDA - read it and then write it on top of the firmware. */ static int -spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, +spectrum_dl_image(hermes_t *hw, dev_link_t *link, const unsigned char *image) { int ret; @@ -505,13 +505,14 @@ spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, * reset on the card, to make sure it's in a sane state. */ static int -spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link) +spectrum_dl_firmware(hermes_t *hw, dev_link_t *link) { int ret; + client_handle_t handle = link->handle; const struct firmware *fw_entry; if (request_firmware(&fw_entry, primary_fw_name, - &handle_to_dev(link)) == 0) { + &handle_to_dev(handle)) == 0) { primsym = fw_entry->data; } else { printk(KERN_ERR PFX "Cannot find firmware: %s\n", @@ -520,7 +521,7 @@ spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link) } if (request_firmware(&fw_entry, secondary_fw_name, - &handle_to_dev(link)) == 0) { + &handle_to_dev(handle)) == 0) { secsym = fw_entry->data; } else { printk(KERN_ERR PFX "Cannot find firmware: %s\n", @@ -553,12 +554,12 @@ static int spectrum_cs_hard_reset(struct orinoco_private *priv) { struct orinoco_pccard *card = priv->card; - struct pcmcia_device *link = card->p_dev; + dev_link_t *link = &card->link; int err; if (!hermes_present(&priv->hw)) { /* The firmware needs to be reloaded */ - if (spectrum_dl_firmware(&priv->hw, link) != 0) { + if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) { printk(KERN_ERR PFX "Firmware download failed\n"); err = -ENODEV; } @@ -583,11 +584,12 @@ spectrum_cs_hard_reset(struct orinoco_private *priv) * configure the card at this point -- we wait until we receive a card * insertion event. */ static int -spectrum_cs_probe(struct pcmcia_device *link) +spectrum_cs_attach(struct pcmcia_device *p_dev) { struct net_device *dev; struct orinoco_private *priv; struct orinoco_pccard *card; + dev_link_t *link; dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); if (! dev) @@ -596,7 +598,7 @@ spectrum_cs_probe(struct pcmcia_device *link) card = priv->card; /* Link both structures together */ - card->p_dev = link; + link = &card->link; link->priv = dev; /* Interrupt setup */ @@ -613,7 +615,13 @@ spectrum_cs_probe(struct pcmcia_device *link) link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; - return spectrum_cs_config(link); + link->handle = p_dev; + p_dev->instance = link; + + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + spectrum_cs_config(link); + + return 0; } /* spectrum_cs_attach */ /* @@ -622,14 +630,16 @@ spectrum_cs_probe(struct pcmcia_device *link) * are freed. Otherwise, the structures will be freed when the device * is released. */ -static void spectrum_cs_detach(struct pcmcia_device *link) +static void spectrum_cs_detach(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - spectrum_cs_release(link); + if (link->state & DEV_CONFIG) + spectrum_cs_release(link); - DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); - if (link->dev_node) { + DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); + if (link->dev) { DEBUG(0, PFX "About to unregister net device %p\n", dev); unregister_netdev(dev); @@ -643,10 +653,11 @@ static void spectrum_cs_detach(struct pcmcia_device *link) * device available to the system. */ -static int -spectrum_cs_config(struct pcmcia_device *link) +static void +spectrum_cs_config(dev_link_t *link) { struct net_device *dev = link->priv; + client_handle_t handle = link->handle; struct orinoco_private *priv = netdev_priv(dev); struct orinoco_pccard *card = priv->card; hermes_t *hw = &priv->hw; @@ -658,7 +669,7 @@ spectrum_cs_config(struct pcmcia_device *link) cisparse_t parse; void __iomem *mem; - CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info)); + CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info)); /* * This reads the card's CONFIG tuple to find its @@ -669,15 +680,19 @@ spectrum_cs_config(struct pcmcia_device *link) tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; + /* Configure card */ + link->state |= DEV_CONFIG; + /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, - pcmcia_get_configuration_info(link, &conf)); + pcmcia_get_configuration_info(handle, &conf)); + link->conf.Vcc = conf.Vcc; /* * In this loop, we scan the CIS for configuration table @@ -694,13 +709,13 @@ spectrum_cs_config(struct pcmcia_device *link) * implementation-defined details. */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); cistpl_cftable_entry_t dflt = { .index = 0 }; - if ( (pcmcia_get_tuple_data(link, &tuple) != 0) - || (pcmcia_parse_tuple(link, &tuple, &parse) != 0)) + if ( (pcmcia_get_tuple_data(handle, &tuple) != 0) + || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0)) goto next_entry; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) @@ -732,10 +747,10 @@ spectrum_cs_config(struct pcmcia_device *link) } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp = + link->conf.Vpp1 = link->conf.Vpp2 = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp = + link->conf.Vpp1 = link->conf.Vpp2 = dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; /* Do we need to allocate an interrupt? */ @@ -765,7 +780,7 @@ spectrum_cs_config(struct pcmcia_device *link) } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(link, &link->io) != 0) + if (pcmcia_request_io(link->handle, &link->io) != 0) goto next_entry; } @@ -775,8 +790,9 @@ spectrum_cs_config(struct pcmcia_device *link) break; next_entry: - pcmcia_disable_device(link); - last_ret = pcmcia_get_next_tuple(link, &tuple); + if (link->io.NumPorts1) + pcmcia_release_io(link->handle, &link->io); + last_ret = pcmcia_get_next_tuple(handle, &tuple); if (last_ret == CS_NO_MORE_ITEMS) { printk(KERN_ERR PFX "GetNextTuple(): No matching " "CIS configuration. Maybe you need the " @@ -790,7 +806,7 @@ spectrum_cs_config(struct pcmcia_device *link) * a handler to the interrupt, unless the 'Handler' member of * the irq structure is initialized. */ - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); /* We initialize the hermes structure before completing PCMCIA * configuration just in case the interrupt handler gets @@ -807,7 +823,7 @@ spectrum_cs_config(struct pcmcia_device *link) * card and host interface into "Memory and IO" mode. */ CS_CHECK(RequestConfiguration, - pcmcia_request_configuration(link, &link->conf)); + pcmcia_request_configuration(link->handle, &link->conf)); /* Ok, we have the configuration, prepare to register the netdev */ dev->base_addr = link->io.BasePort1; @@ -820,7 +836,7 @@ spectrum_cs_config(struct pcmcia_device *link) goto failed; } - SET_NETDEV_DEV(dev, &handle_to_dev(link)); + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); /* Tell the stack we exist */ if (register_netdev(dev) != 0) { printk(KERN_ERR PFX "register_netdev() failed\n"); @@ -828,18 +844,20 @@ spectrum_cs_config(struct pcmcia_device *link) } /* At this point, the dev_node_t structure(s) needs to be - * initialized and arranged in a linked list at link->dev_node. */ + * initialized and arranged in a linked list at link->dev. */ strcpy(card->node.dev_name, dev->name); - link->dev_node = &card->node; /* link->dev_node being non-NULL is also + link->dev = &card->node; /* link->dev being non-NULL is also used to indicate that the net_device has been registered */ + link->state &= ~DEV_CONFIG_PENDING; /* Finally, report what we've done */ - printk(KERN_DEBUG "%s: index 0x%02x: ", - dev->name, link->conf.ConfigIndex); - if (link->conf.Vpp) - printk(", Vpp %d.%d", link->conf.Vpp / 10, - link->conf.Vpp % 10); + printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d", + dev->name, link->conf.ConfigIndex, + link->conf.Vcc / 10, link->conf.Vcc % 10); + if (link->conf.Vpp1) + printk(", Vpp %d.%d", link->conf.Vpp1 / 10, + link->conf.Vpp1 % 10); printk(", irq %d", link->irq.AssignedIRQ); if (link->io.NumPorts1) printk(", io 0x%04x-0x%04x", link->io.BasePort1, @@ -849,14 +867,13 @@ spectrum_cs_config(struct pcmcia_device *link) link->io.BasePort2 + link->io.NumPorts2 - 1); printk("\n"); - return 0; + return; cs_failed: - cs_error(link, last_fn, last_ret); + cs_error(link->handle, last_fn, last_ret); failed: spectrum_cs_release(link); - return -ENODEV; } /* spectrum_cs_config */ /* @@ -865,7 +882,7 @@ spectrum_cs_config(struct pcmcia_device *link) * still open, this will be postponed until it is closed. */ static void -spectrum_cs_release(struct pcmcia_device *link) +spectrum_cs_release(dev_link_t *link) { struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); @@ -877,46 +894,64 @@ spectrum_cs_release(struct pcmcia_device *link) priv->hw_unavailable++; spin_unlock_irqrestore(&priv->lock, flags); - pcmcia_disable_device(link); + /* Don't bother checking to see if these succeed or not */ + pcmcia_release_configuration(link->handle); + if (link->io.NumPorts1) + pcmcia_release_io(link->handle, &link->io); + if (link->irq.AssignedIRQ) + pcmcia_release_irq(link->handle, &link->irq); + link->state &= ~DEV_CONFIG; if (priv->hw.iobase) ioport_unmap(priv->hw.iobase); } /* spectrum_cs_release */ static int -spectrum_cs_suspend(struct pcmcia_device *link) +spectrum_cs_suspend(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); unsigned long flags; int err = 0; + link->state |= DEV_SUSPEND; /* Mark the device as stopped, to block IO until later */ - spin_lock_irqsave(&priv->lock, flags); + if (link->state & DEV_CONFIG) { + spin_lock_irqsave(&priv->lock, flags); - err = __orinoco_down(dev); - if (err) - printk(KERN_WARNING "%s: Error %d downing interface\n", - dev->name, err); + err = __orinoco_down(dev); + if (err) + printk(KERN_WARNING "%s: Error %d downing interface\n", + dev->name, err); - netif_device_detach(dev); - priv->hw_unavailable++; + netif_device_detach(dev); + priv->hw_unavailable++; - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); + + pcmcia_release_configuration(link->handle); + } return 0; } static int -spectrum_cs_resume(struct pcmcia_device *link) +spectrum_cs_resume(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); - netif_device_attach(dev); - priv->hw_unavailable--; - schedule_work(&priv->reset_work); - + link->state &= ~DEV_SUSPEND; + if (link->state & DEV_CONFIG) { + /* FIXME: should we double check that this is + * the same card as we had before */ + pcmcia_request_configuration(link->handle, &link->conf); + netif_device_attach(dev); + priv->hw_unavailable--; + schedule_work(&priv->reset_work); + } return 0; } @@ -944,7 +979,7 @@ static struct pcmcia_driver orinoco_driver = { .drv = { .name = DRIVER_NAME, }, - .probe = spectrum_cs_probe, + .probe = spectrum_cs_attach, .remove = spectrum_cs_detach, .suspend = spectrum_cs_suspend, .resume = spectrum_cs_resume,