X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fpcmcia%2Fxirc2ps_cs.c;h=14a523c44403258c346b0824f140294e55238cde;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=71f45056a70cef15b33970c6f8b530a3ee74dc7b;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 71f45056a..14a523c44 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -208,7 +208,7 @@ enum xirc_cmd { /* Commands */ #define XIRCREG45_REV 15 /* Revision Register (rd) */ #define XIRCREG50_IA 8 /* Individual Address (8-13) */ -static const char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; +static char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; /**************** * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If @@ -289,9 +289,9 @@ static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, * and ejection events. They are invoked from the event handler. */ -static int has_ce2_string(struct pcmcia_device * link); -static int xirc2ps_config(struct pcmcia_device * link); -static void xirc2ps_release(struct pcmcia_device * link); +static int has_ce2_string(dev_link_t * link); +static void xirc2ps_config(dev_link_t * link); +static void xirc2ps_release(dev_link_t * link); /**************** * The attach() and detach() entry points are used to create and destroy @@ -313,10 +313,10 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs /**************** * A linked list of "instances" of the device. Each actual * PCMCIA card corresponds to one device instance, and is described - * by one struct pcmcia_device structure (defined in ds.h). + * by one dev_link_t structure (defined in ds.h). * * You may not want to use a linked list for this -- for example, the - * memory card driver uses an array of struct pcmcia_device pointers, where minor + * memory card driver uses an array of dev_link_t pointers, where minor * device numbers are used to derive the corresponding array index. */ @@ -326,13 +326,13 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs * example, ethernet cards, modems). In other cases, there may be * many actual or logical devices (SCSI adapters, memory cards with * multiple partitions). The dev_node_t structures need to be kept - * in a linked list starting at the 'dev' field of a struct pcmcia_device + * in a linked list starting at the 'dev' field of a dev_link_t * structure. We allocate them in the card's private data structure, * because they generally can't be allocated dynamically. */ typedef struct local_info_t { - struct pcmcia_device *p_dev; + dev_link_t link; dev_node_t node; struct net_device_stats stats; int card_type; @@ -345,6 +345,7 @@ typedef struct local_info_t { void __iomem *dingo_ccr; /* only used for CEM56 cards */ unsigned last_ptr_value; /* last packets transmitted value */ const char *manf_str; + struct work_struct tx_timeout_task; } local_info_t; /**************** @@ -352,10 +353,11 @@ typedef struct local_info_t { */ static int do_start_xmit(struct sk_buff *skb, struct net_device *dev); static void do_tx_timeout(struct net_device *dev); +static void xirc2ps_tx_timeout_task(void *data); static struct net_device_stats *do_get_stats(struct net_device *dev); static void set_addresses(struct net_device *dev); static void set_multicast_list(struct net_device *dev); -static int set_card_type(struct pcmcia_device *link, const void *s); +static int set_card_type(dev_link_t *link, const void *s); static int do_config(struct net_device *dev, struct ifmap *map); static int do_open(struct net_device *dev); static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); @@ -368,7 +370,7 @@ static int do_stop(struct net_device *dev); /*=============== Helper functions =========================*/ static int -first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) +first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) { int err; @@ -379,7 +381,7 @@ first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) } static int -next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) +next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) { int err; @@ -553,8 +555,9 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len) */ static int -xirc2ps_probe(struct pcmcia_device *link) +xirc2ps_attach(struct pcmcia_device *p_dev) { + dev_link_t *link; struct net_device *dev; local_info_t *local; @@ -565,11 +568,12 @@ xirc2ps_probe(struct pcmcia_device *link) if (!dev) return -ENOMEM; local = netdev_priv(dev); - local->p_dev = link; + link = &local->link; link->priv = dev; /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; @@ -589,9 +593,16 @@ xirc2ps_probe(struct pcmcia_device *link) #ifdef HAVE_TX_TIMEOUT dev->tx_timeout = do_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task, dev); #endif - return xirc2ps_config(link); + link->handle = p_dev; + p_dev->instance = link; + + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + xirc2ps_config(link); + + return 0; } /* xirc2ps_attach */ /**************** @@ -602,16 +613,18 @@ xirc2ps_probe(struct pcmcia_device *link) */ static void -xirc2ps_detach(struct pcmcia_device *link) +xirc2ps_detach(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; DEBUG(0, "detach(0x%p)\n", link); - if (link->dev_node) + if (link->dev) unregister_netdev(dev); - xirc2ps_release(link); + if (link->state & DEV_CONFIG) + xirc2ps_release(link); free_netdev(dev); } /* xirc2ps_detach */ @@ -635,7 +648,7 @@ xirc2ps_detach(struct pcmcia_device *link) * */ static int -set_card_type(struct pcmcia_device *link, const void *s) +set_card_type(dev_link_t *link, const void *s) { struct net_device *dev = link->priv; local_info_t *local = netdev_priv(dev); @@ -704,8 +717,9 @@ set_card_type(struct pcmcia_device *link, const void *s) * Returns: true if this is a CE2 */ static int -has_ce2_string(struct pcmcia_device * link) +has_ce2_string(dev_link_t * link) { + client_handle_t handle = link->handle; tuple_t tuple; cisparse_t parse; u_char buf[256]; @@ -715,7 +729,7 @@ has_ce2_string(struct pcmcia_device * link) tuple.TupleDataMax = 254; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_VERS_1; - if (!first_tuple(link, &tuple, &parse) && parse.version_1.ns > 2) { + if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) { if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2")) return 1; } @@ -727,9 +741,10 @@ has_ce2_string(struct pcmcia_device * link) * is received, to configure the PCMCIA socket, and to make the * ethernet device available to the system. */ -static int -xirc2ps_config(struct pcmcia_device * link) +static void +xirc2ps_config(dev_link_t * link) { + client_handle_t handle = link->handle; struct net_device *dev = link->priv; local_info_t *local = netdev_priv(dev); tuple_t tuple; @@ -755,7 +770,7 @@ xirc2ps_config(struct pcmcia_device * link) /* Is this a valid card */ tuple.DesiredTuple = CISTPL_MANFID; - if ((err=first_tuple(link, &tuple, &parse))) { + if ((err=first_tuple(handle, &tuple, &parse))) { printk(KNOT_XIRC "manfid not found in CIS\n"); goto failure; } @@ -791,15 +806,15 @@ xirc2ps_config(struct pcmcia_device * link) /* get configuration stuff */ tuple.DesiredTuple = CISTPL_CONFIG; - if ((err=first_tuple(link, &tuple, &parse))) + if ((err=first_tuple(handle, &tuple, &parse))) goto cis_error; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* get the ethernet address from the CIS */ tuple.DesiredTuple = CISTPL_FUNCE; - for (err = first_tuple(link, &tuple, &parse); !err; - err = next_tuple(link, &tuple, &parse)) { + for (err = first_tuple(handle, &tuple, &parse); !err; + err = next_tuple(handle, &tuple, &parse)) { /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries: * the first one with a length of zero the second correct - * so I skip all entries with length 0 */ @@ -809,8 +824,8 @@ xirc2ps_config(struct pcmcia_device * link) } if (err) { /* not found: try to get the node-id from tuple 0x89 */ tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */ - if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 && - (err = pcmcia_get_tuple_data(link, &tuple)) == 0) { + if ((err = pcmcia_get_first_tuple(handle, &tuple)) == 0 && + (err = pcmcia_get_tuple_data(handle, &tuple)) == 0) { if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID) memcpy(&parse, buf, 8); else @@ -819,8 +834,8 @@ xirc2ps_config(struct pcmcia_device * link) } if (err) { /* another try (James Lehmer's CE2 version 4.1)*/ tuple.DesiredTuple = CISTPL_FUNCE; - for (err = first_tuple(link, &tuple, &parse); !err; - err = next_tuple(link, &tuple, &parse)) { + for (err = first_tuple(handle, &tuple, &parse); !err; + err = next_tuple(handle, &tuple, &parse)) { if (parse.funce.type == 0x02 && parse.funce.data[0] == 1 && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) { buf[1] = 4; @@ -841,6 +856,9 @@ xirc2ps_config(struct pcmcia_device * link) for (i=0; i < 6; i++) dev->dev_addr[i] = node_id->id[i]; + /* Configure card */ + link->state |= DEV_CONFIG; + link->io.IOAddrLines =10; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; link->irq.Attributes = IRQ_HANDLE_PRESENT; @@ -860,14 +878,14 @@ xirc2ps_config(struct pcmcia_device * link) * Ethernet port */ link->io.NumPorts1 = 16; /* no Mako stuff anymore */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - for (err = first_tuple(link, &tuple, &parse); !err; - err = next_tuple(link, &tuple, &parse)) { + for (err = first_tuple(handle, &tuple, &parse); !err; + err = next_tuple(handle, &tuple, &parse)) { if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = ioaddr; - if (!(err=pcmcia_request_io(link, &link->io))) + if (!(err=pcmcia_request_io(link->handle, &link->io))) goto port_found; } } @@ -881,15 +899,15 @@ xirc2ps_config(struct pcmcia_device * link) */ for (pass=0; pass < 2; pass++) { tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - for (err = first_tuple(link, &tuple, &parse); !err; - err = next_tuple(link, &tuple, &parse)){ + for (err = first_tuple(handle, &tuple, &parse); !err; + err = next_tuple(handle, &tuple, &parse)){ if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){ link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = link->io.BasePort2 + (pass ? (cf->index & 0x20 ? -24:8) : (cf->index & 0x20 ? 8:-24)); - if (!(err=pcmcia_request_io(link, &link->io))) + if (!(err=pcmcia_request_io(link->handle, &link->io))) goto port_found; } } @@ -904,12 +922,12 @@ xirc2ps_config(struct pcmcia_device * link) link->io.NumPorts1 = 16; for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->io.BasePort1 = ioaddr; - if (!(err=pcmcia_request_io(link, &link->io))) + if (!(err=pcmcia_request_io(link->handle, &link->io))) goto port_found; } link->io.BasePort1 = 0; /* let CS decide */ - if ((err=pcmcia_request_io(link, &link->io))) { - cs_error(link, RequestIO, err); + if ((err=pcmcia_request_io(link->handle, &link->io))) { + cs_error(link->handle, RequestIO, err); goto config_error; } } @@ -921,8 +939,8 @@ xirc2ps_config(struct pcmcia_device * link) * Now allocate an interrupt line. Note that this does not * actually assign a handler to the interrupt. */ - if ((err=pcmcia_request_irq(link, &link->irq))) { - cs_error(link, RequestIRQ, err); + if ((err=pcmcia_request_irq(link->handle, &link->irq))) { + cs_error(link->handle, RequestIRQ, err); goto config_error; } @@ -930,8 +948,8 @@ xirc2ps_config(struct pcmcia_device * link) * This actually configures the PCMCIA socket -- setting up * the I/O windows and the interrupt mapping. */ - if ((err=pcmcia_request_configuration(link, &link->conf))) { - cs_error(link, RequestConfiguration, err); + if ((err=pcmcia_request_configuration(link->handle, &link->conf))) { + cs_error(link->handle, RequestConfiguration, err); goto config_error; } @@ -948,15 +966,15 @@ xirc2ps_config(struct pcmcia_device * link) reg.Action = CS_WRITE; reg.Offset = CISREG_IOBASE_0; reg.Value = link->io.BasePort2 & 0xff; - if ((err = pcmcia_access_configuration_register(link, ®))) { - cs_error(link, AccessConfigurationRegister, err); + if ((err = pcmcia_access_configuration_register(link->handle, ®))) { + cs_error(link->handle, AccessConfigurationRegister, err); goto config_error; } reg.Action = CS_WRITE; reg.Offset = CISREG_IOBASE_1; reg.Value = (link->io.BasePort2 >> 8) & 0xff; - if ((err = pcmcia_access_configuration_register(link, ®))) { - cs_error(link, AccessConfigurationRegister, err); + if ((err = pcmcia_access_configuration_register(link->handle, ®))) { + cs_error(link->handle, AccessConfigurationRegister, err); goto config_error; } @@ -967,15 +985,15 @@ xirc2ps_config(struct pcmcia_device * link) req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Base = req.Size = 0; req.AccessSpeed = 0; - if ((err = pcmcia_request_window(&link, &req, &link->win))) { - cs_error(link, RequestWindow, err); + if ((err = pcmcia_request_window(&link->handle, &req, &link->win))) { + cs_error(link->handle, RequestWindow, err); goto config_error; } local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800; mem.CardOffset = 0x0; mem.Page = 0; if ((err = pcmcia_map_mem_page(link->win, &mem))) { - cs_error(link, MapMemPage, err); + cs_error(link->handle, MapMemPage, err); goto config_error; } @@ -1035,12 +1053,13 @@ xirc2ps_config(struct pcmcia_device * link) if (local->dingo) do_reset(dev, 1); /* a kludge to make the cem56 work */ - link->dev_node = &local->node; - SET_NETDEV_DEV(dev, &handle_to_dev(link)); + link->dev = &local->node; + link->state &= ~DEV_CONFIG_PENDING; + SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if ((err=register_netdev(dev))) { printk(KNOT_XIRC "register_netdev() failed\n"); - link->dev_node = NULL; + link->dev = NULL; goto config_error; } @@ -1053,16 +1072,17 @@ xirc2ps_config(struct pcmcia_device * link) printk("%c%02X", i?':':' ', dev->dev_addr[i]); printk("\n"); - return 0; + return; config_error: + link->state &= ~DEV_CONFIG_PENDING; xirc2ps_release(link); - return -ENODEV; + return; cis_error: printk(KNOT_XIRC "unable to parse CIS\n"); failure: - return -ENODEV; + link->state &= ~DEV_CONFIG_PENDING; } /* xirc2ps_config */ /**************** @@ -1071,41 +1091,57 @@ xirc2ps_config(struct pcmcia_device * link) * still open, this will be postponed until it is closed. */ static void -xirc2ps_release(struct pcmcia_device *link) +xirc2ps_release(dev_link_t *link) { - DEBUG(0, "release(0x%p)\n", link); - if (link->win) { - struct net_device *dev = link->priv; - local_info_t *local = netdev_priv(dev); - if (local->dingo) - iounmap(local->dingo_ccr - 0x0800); - } - pcmcia_disable_device(link); + DEBUG(0, "release(0x%p)\n", link); + + if (link->win) { + struct net_device *dev = link->priv; + local_info_t *local = netdev_priv(dev); + if (local->dingo) + iounmap(local->dingo_ccr - 0x0800); + pcmcia_release_window(link->win); + } + pcmcia_release_configuration(link->handle); + pcmcia_release_io(link->handle, &link->io); + pcmcia_release_irq(link->handle, &link->irq); + link->state &= ~DEV_CONFIG; + } /* xirc2ps_release */ /*====================================================================*/ -static int xirc2ps_suspend(struct pcmcia_device *link) +static int xirc2ps_suspend(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - if (link->open) { - netif_device_detach(dev); - do_powerdown(dev); + link->state |= DEV_SUSPEND; + if (link->state & DEV_CONFIG) { + if (link->open) { + netif_device_detach(dev); + do_powerdown(dev); + } + pcmcia_release_configuration(link->handle); } return 0; } -static int xirc2ps_resume(struct pcmcia_device *link) +static int xirc2ps_resume(struct pcmcia_device *p_dev) { + dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - if (link->open) { - do_reset(dev,1); - netif_device_attach(dev); + link->state &= ~DEV_SUSPEND; + if (link->state & DEV_CONFIG) { + pcmcia_request_configuration(link->handle, &link->conf); + if (link->open) { + do_reset(dev,1); + netif_device_attach(dev); + } } return 0; @@ -1341,17 +1377,24 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) /*====================================================================*/ static void -do_tx_timeout(struct net_device *dev) +xirc2ps_tx_timeout_task(void *data) { - local_info_t *lp = netdev_priv(dev); - printk(KERN_NOTICE "%s: transmit timed out\n", dev->name); - lp->stats.tx_errors++; + struct net_device *dev = data; /* reset the card */ do_reset(dev,1); dev->trans_start = jiffies; netif_wake_queue(dev); } +static void +do_tx_timeout(struct net_device *dev) +{ + local_info_t *lp = netdev_priv(dev); + lp->stats.tx_errors++; + printk(KERN_NOTICE "%s: transmit timed out\n", dev->name); + schedule_work(&lp->tx_timeout_task); +} + static int do_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -1519,13 +1562,13 @@ static int do_open(struct net_device *dev) { local_info_t *lp = netdev_priv(dev); - struct pcmcia_device *link = lp->p_dev; + dev_link_t *link = &lp->link; DEBUG(0, "do_open(%p)\n", dev); /* Check that the PCMCIA card is still here. */ /* Physical device present signature. */ - if (!pcmcia_dev_present(link)) + if (!DEV_OK(link)) return -ENODEV; /* okay */ @@ -1849,7 +1892,7 @@ do_stop(struct net_device *dev) { kio_addr_t ioaddr = dev->base_addr; local_info_t *lp = netdev_priv(dev); - struct pcmcia_device *link = lp->p_dev; + dev_link_t *link = &lp->link; DEBUG(0, "do_stop(%p)\n", dev); @@ -1902,7 +1945,7 @@ static struct pcmcia_driver xirc2ps_cs_driver = { .drv = { .name = "xirc2ps_cs", }, - .probe = xirc2ps_probe, + .probe = xirc2ps_attach, .remove = xirc2ps_detach, .id_table = xirc2ps_ids, .suspend = xirc2ps_suspend, @@ -1940,7 +1983,7 @@ static int __init setup_xirc2ps_cs(char *str) MAYBE_SET(lockup_hack, 6); #undef MAYBE_SET - return 1; + return 0; } __setup("xirc2ps_cs=", setup_xirc2ps_cs);