diff options
Diffstat (limited to 'drivers/net/wireless/hostap')
-rw-r--r-- | drivers/net/wireless/hostap/hostap_cs.c | 237 |
1 files changed, 104 insertions, 133 deletions
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 3b4e55cf33cd..633740277352 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -234,7 +234,7 @@ static void sandisk_set_iobase(local_info_t *local) | |||
234 | reg.Value = hw_priv->link->io.BasePort1 & 0x00ff; | 234 | reg.Value = hw_priv->link->io.BasePort1 & 0x00ff; |
235 | res = pcmcia_access_configuration_register(hw_priv->link, | 235 | res = pcmcia_access_configuration_register(hw_priv->link, |
236 | ®); | 236 | ®); |
237 | if (res != CS_SUCCESS) { | 237 | if (res != 0) { |
238 | printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -" | 238 | printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -" |
239 | " res=%d\n", res); | 239 | " res=%d\n", res); |
240 | } | 240 | } |
@@ -246,7 +246,7 @@ static void sandisk_set_iobase(local_info_t *local) | |||
246 | reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8; | 246 | reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8; |
247 | res = pcmcia_access_configuration_register(hw_priv->link, | 247 | res = pcmcia_access_configuration_register(hw_priv->link, |
248 | ®); | 248 | ®); |
249 | if (res != CS_SUCCESS) { | 249 | if (res != 0) { |
250 | printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -" | 250 | printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -" |
251 | " res=%d\n", res); | 251 | " res=%d\n", res); |
252 | } | 252 | } |
@@ -305,7 +305,7 @@ static int sandisk_enable_wireless(struct net_device *dev) | |||
305 | tuple.DesiredTuple = CISTPL_LONGLINK_MFC; | 305 | tuple.DesiredTuple = CISTPL_LONGLINK_MFC; |
306 | if (pcmcia_get_first_tuple(hw_priv->link, &tuple) || | 306 | if (pcmcia_get_first_tuple(hw_priv->link, &tuple) || |
307 | pcmcia_get_tuple_data(hw_priv->link, &tuple) || | 307 | pcmcia_get_tuple_data(hw_priv->link, &tuple) || |
308 | pcmcia_parse_tuple(hw_priv->link, &tuple, parse) || | 308 | pcmcia_parse_tuple(&tuple, parse) || |
309 | parse->longlink_mfc.nfn < 2) { | 309 | parse->longlink_mfc.nfn < 2) { |
310 | /* No multi-function links found */ | 310 | /* No multi-function links found */ |
311 | ret = -ENODEV; | 311 | ret = -ENODEV; |
@@ -322,7 +322,7 @@ static int sandisk_enable_wireless(struct net_device *dev) | |||
322 | reg.Value = COR_SOFT_RESET; | 322 | reg.Value = COR_SOFT_RESET; |
323 | res = pcmcia_access_configuration_register(hw_priv->link, | 323 | res = pcmcia_access_configuration_register(hw_priv->link, |
324 | ®); | 324 | ®); |
325 | if (res != CS_SUCCESS) { | 325 | if (res != 0) { |
326 | printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", | 326 | printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", |
327 | dev->name, res); | 327 | dev->name, res); |
328 | goto done; | 328 | goto done; |
@@ -339,7 +339,7 @@ static int sandisk_enable_wireless(struct net_device *dev) | |||
339 | reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA; | 339 | reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA; |
340 | res = pcmcia_access_configuration_register(hw_priv->link, | 340 | res = pcmcia_access_configuration_register(hw_priv->link, |
341 | ®); | 341 | ®); |
342 | if (res != CS_SUCCESS) { | 342 | if (res != 0) { |
343 | printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", | 343 | printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", |
344 | dev->name, res); | 344 | dev->name, res); |
345 | goto done; | 345 | goto done; |
@@ -374,7 +374,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local) | |||
374 | reg.Value = 0; | 374 | reg.Value = 0; |
375 | res = pcmcia_access_configuration_register(hw_priv->link, | 375 | res = pcmcia_access_configuration_register(hw_priv->link, |
376 | ®); | 376 | ®); |
377 | if (res != CS_SUCCESS) { | 377 | if (res != 0) { |
378 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n", | 378 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n", |
379 | res); | 379 | res); |
380 | return; | 380 | return; |
@@ -386,7 +386,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local) | |||
386 | reg.Value |= COR_SOFT_RESET; | 386 | reg.Value |= COR_SOFT_RESET; |
387 | res = pcmcia_access_configuration_register(hw_priv->link, | 387 | res = pcmcia_access_configuration_register(hw_priv->link, |
388 | ®); | 388 | ®); |
389 | if (res != CS_SUCCESS) { | 389 | if (res != 0) { |
390 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n", | 390 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n", |
391 | res); | 391 | res); |
392 | return; | 392 | return; |
@@ -399,7 +399,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local) | |||
399 | reg.Value |= COR_IREQ_ENA; | 399 | reg.Value |= COR_IREQ_ENA; |
400 | res = pcmcia_access_configuration_register(hw_priv->link, | 400 | res = pcmcia_access_configuration_register(hw_priv->link, |
401 | ®); | 401 | ®); |
402 | if (res != CS_SUCCESS) { | 402 | if (res != 0) { |
403 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n", | 403 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n", |
404 | res); | 404 | res); |
405 | return; | 405 | return; |
@@ -433,7 +433,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) | |||
433 | reg.Value = 0; | 433 | reg.Value = 0; |
434 | res = pcmcia_access_configuration_register(hw_priv->link, | 434 | res = pcmcia_access_configuration_register(hw_priv->link, |
435 | ®); | 435 | ®); |
436 | if (res != CS_SUCCESS) { | 436 | if (res != 0) { |
437 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 " | 437 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 " |
438 | "(%d)\n", res); | 438 | "(%d)\n", res); |
439 | return; | 439 | return; |
@@ -446,7 +446,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) | |||
446 | reg.Value |= COR_SOFT_RESET; | 446 | reg.Value |= COR_SOFT_RESET; |
447 | res = pcmcia_access_configuration_register(hw_priv->link, | 447 | res = pcmcia_access_configuration_register(hw_priv->link, |
448 | ®); | 448 | ®); |
449 | if (res != CS_SUCCESS) { | 449 | if (res != 0) { |
450 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 " | 450 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 " |
451 | "(%d)\n", res); | 451 | "(%d)\n", res); |
452 | return; | 452 | return; |
@@ -460,7 +460,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) | |||
460 | reg.Offset = CISREG_CCSR; | 460 | reg.Offset = CISREG_CCSR; |
461 | res = pcmcia_access_configuration_register(hw_priv->link, | 461 | res = pcmcia_access_configuration_register(hw_priv->link, |
462 | ®); | 462 | ®); |
463 | if (res != CS_SUCCESS) { | 463 | if (res != 0) { |
464 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 " | 464 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 " |
465 | "(%d)\n", res); | 465 | "(%d)\n", res); |
466 | return; | 466 | return; |
@@ -472,7 +472,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) | |||
472 | reg.Value = old_cor & ~COR_SOFT_RESET; | 472 | reg.Value = old_cor & ~COR_SOFT_RESET; |
473 | res = pcmcia_access_configuration_register(hw_priv->link, | 473 | res = pcmcia_access_configuration_register(hw_priv->link, |
474 | ®); | 474 | ®); |
475 | if (res != CS_SUCCESS) { | 475 | if (res != 0) { |
476 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 " | 476 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 " |
477 | "(%d)\n", res); | 477 | "(%d)\n", res); |
478 | return; | 478 | return; |
@@ -532,145 +532,118 @@ static void prism2_detach(struct pcmcia_device *link) | |||
532 | #define CS_CHECK(fn, ret) \ | 532 | #define CS_CHECK(fn, ret) \ |
533 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 533 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
534 | 534 | ||
535 | #define CFG_CHECK2(fn, retf) \ | ||
536 | do { int _ret = (retf); \ | ||
537 | if (_ret != 0) { \ | ||
538 | PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", _ret); \ | ||
539 | cs_error(link, fn, _ret); \ | ||
540 | goto next_entry; \ | ||
541 | } \ | ||
542 | } while (0) | ||
543 | |||
544 | 535 | ||
545 | /* run after a CARD_INSERTION event is received to configure the PCMCIA | 536 | /* run after a CARD_INSERTION event is received to configure the PCMCIA |
546 | * socket and make the device available to the system */ | 537 | * socket and make the device available to the system */ |
538 | |||
539 | static int prism2_config_check(struct pcmcia_device *p_dev, | ||
540 | cistpl_cftable_entry_t *cfg, | ||
541 | cistpl_cftable_entry_t *dflt, | ||
542 | unsigned int vcc, | ||
543 | void *priv_data) | ||
544 | { | ||
545 | if (cfg->index == 0) | ||
546 | return -ENODEV; | ||
547 | |||
548 | PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X " | ||
549 | "(default 0x%02X)\n", cfg->index, dflt->index); | ||
550 | |||
551 | /* Does this card need audio output? */ | ||
552 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
553 | p_dev->conf.Attributes |= CONF_ENABLE_SPKR; | ||
554 | p_dev->conf.Status = CCSR_AUDIO_ENA; | ||
555 | } | ||
556 | |||
557 | /* Use power settings for Vcc and Vpp if present */ | ||
558 | /* Note that the CIS values need to be rescaled */ | ||
559 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
560 | if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / | ||
561 | 10000 && !ignore_cis_vcc) { | ||
562 | PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping" | ||
563 | " this entry\n"); | ||
564 | return -ENODEV; | ||
565 | } | ||
566 | } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
567 | if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / | ||
568 | 10000 && !ignore_cis_vcc) { | ||
569 | PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch " | ||
570 | "- skipping this entry\n"); | ||
571 | return -ENODEV; | ||
572 | } | ||
573 | } | ||
574 | |||
575 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
576 | p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
577 | else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
578 | p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
579 | |||
580 | /* Do we need to allocate an interrupt? */ | ||
581 | if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) | ||
582 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
583 | else if (!(p_dev->conf.Attributes & CONF_ENABLE_IRQ)) { | ||
584 | /* At least Compaq WL200 does not have IRQInfo1 set, | ||
585 | * but it does not work without interrupts.. */ | ||
586 | printk(KERN_WARNING "Config has no IRQ info, but trying to " | ||
587 | "enable IRQ anyway..\n"); | ||
588 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
589 | } | ||
590 | |||
591 | /* IO window settings */ | ||
592 | PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d " | ||
593 | "dflt->io.nwin=%d\n", | ||
594 | cfg->io.nwin, dflt->io.nwin); | ||
595 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; | ||
596 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
597 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
598 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
599 | PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, " | ||
600 | "io.base=0x%04x, len=%d\n", io->flags, | ||
601 | io->win[0].base, io->win[0].len); | ||
602 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
603 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
604 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
605 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
606 | p_dev->io.IOAddrLines = io->flags & | ||
607 | CISTPL_IO_LINES_MASK; | ||
608 | p_dev->io.BasePort1 = io->win[0].base; | ||
609 | p_dev->io.NumPorts1 = io->win[0].len; | ||
610 | if (io->nwin > 1) { | ||
611 | p_dev->io.Attributes2 = p_dev->io.Attributes1; | ||
612 | p_dev->io.BasePort2 = io->win[1].base; | ||
613 | p_dev->io.NumPorts2 = io->win[1].len; | ||
614 | } | ||
615 | } | ||
616 | |||
617 | /* This reserves IO space but doesn't actually enable it */ | ||
618 | return pcmcia_request_io(p_dev, &p_dev->io); | ||
619 | } | ||
620 | |||
547 | static int prism2_config(struct pcmcia_device *link) | 621 | static int prism2_config(struct pcmcia_device *link) |
548 | { | 622 | { |
549 | struct net_device *dev; | 623 | struct net_device *dev; |
550 | struct hostap_interface *iface; | 624 | struct hostap_interface *iface; |
551 | local_info_t *local; | 625 | local_info_t *local; |
552 | int ret = 1; | 626 | int ret = 1; |
553 | tuple_t tuple; | ||
554 | cisparse_t *parse; | ||
555 | int last_fn, last_ret; | 627 | int last_fn, last_ret; |
556 | u_char buf[64]; | ||
557 | config_info_t conf; | ||
558 | cistpl_cftable_entry_t dflt = { 0 }; | ||
559 | struct hostap_cs_priv *hw_priv; | 628 | struct hostap_cs_priv *hw_priv; |
560 | 629 | ||
561 | PDEBUG(DEBUG_FLOW, "prism2_config()\n"); | 630 | PDEBUG(DEBUG_FLOW, "prism2_config()\n"); |
562 | 631 | ||
563 | parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); | ||
564 | hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); | 632 | hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); |
565 | if (parse == NULL || hw_priv == NULL) { | 633 | if (hw_priv == NULL) { |
566 | ret = -ENOMEM; | 634 | ret = -ENOMEM; |
567 | goto failed; | 635 | goto failed; |
568 | } | 636 | } |
569 | 637 | ||
570 | tuple.Attributes = 0; | ||
571 | tuple.TupleData = buf; | ||
572 | tuple.TupleDataMax = sizeof(buf); | ||
573 | tuple.TupleOffset = 0; | ||
574 | |||
575 | CS_CHECK(GetConfigurationInfo, | ||
576 | pcmcia_get_configuration_info(link, &conf)); | ||
577 | |||
578 | /* Look for an appropriate configuration table entry in the CIS */ | 638 | /* Look for an appropriate configuration table entry in the CIS */ |
579 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 639 | last_ret = pcmcia_loop_config(link, prism2_config_check, NULL); |
580 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 640 | if (last_ret) { |
581 | for (;;) { | 641 | if (!ignore_cis_vcc) |
582 | cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); | 642 | printk(KERN_ERR "GetNextTuple(): No matching " |
583 | CFG_CHECK2(GetTupleData, | 643 | "CIS configuration. Maybe you need the " |
584 | pcmcia_get_tuple_data(link, &tuple)); | 644 | "ignore_cis_vcc=1 parameter.\n"); |
585 | CFG_CHECK2(ParseTuple, | 645 | cs_error(link, RequestIO, last_ret); |
586 | pcmcia_parse_tuple(link, &tuple, parse)); | 646 | goto failed; |
587 | |||
588 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
589 | dflt = *cfg; | ||
590 | if (cfg->index == 0) | ||
591 | goto next_entry; | ||
592 | link->conf.ConfigIndex = cfg->index; | ||
593 | PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X " | ||
594 | "(default 0x%02X)\n", cfg->index, dflt.index); | ||
595 | |||
596 | /* Does this card need audio output? */ | ||
597 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
598 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
599 | link->conf.Status = CCSR_AUDIO_ENA; | ||
600 | } | ||
601 | |||
602 | /* Use power settings for Vcc and Vpp if present */ | ||
603 | /* Note that the CIS values need to be rescaled */ | ||
604 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
605 | if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / | ||
606 | 10000 && !ignore_cis_vcc) { | ||
607 | PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping" | ||
608 | " this entry\n"); | ||
609 | goto next_entry; | ||
610 | } | ||
611 | } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
612 | if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / | ||
613 | 10000 && !ignore_cis_vcc) { | ||
614 | PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch " | ||
615 | "- skipping this entry\n"); | ||
616 | goto next_entry; | ||
617 | } | ||
618 | } | ||
619 | |||
620 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
621 | link->conf.Vpp = | ||
622 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
623 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
624 | link->conf.Vpp = | ||
625 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
626 | |||
627 | /* Do we need to allocate an interrupt? */ | ||
628 | if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) | ||
629 | link->conf.Attributes |= CONF_ENABLE_IRQ; | ||
630 | else if (!(link->conf.Attributes & CONF_ENABLE_IRQ)) { | ||
631 | /* At least Compaq WL200 does not have IRQInfo1 set, | ||
632 | * but it does not work without interrupts.. */ | ||
633 | printk("Config has no IRQ info, but trying to enable " | ||
634 | "IRQ anyway..\n"); | ||
635 | link->conf.Attributes |= CONF_ENABLE_IRQ; | ||
636 | } | ||
637 | |||
638 | /* IO window settings */ | ||
639 | PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d " | ||
640 | "dflt.io.nwin=%d\n", | ||
641 | cfg->io.nwin, dflt.io.nwin); | ||
642 | link->io.NumPorts1 = link->io.NumPorts2 = 0; | ||
643 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { | ||
644 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; | ||
645 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
646 | PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, " | ||
647 | "io.base=0x%04x, len=%d\n", io->flags, | ||
648 | io->win[0].base, io->win[0].len); | ||
649 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
650 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
651 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
652 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
653 | link->io.IOAddrLines = io->flags & | ||
654 | CISTPL_IO_LINES_MASK; | ||
655 | link->io.BasePort1 = io->win[0].base; | ||
656 | link->io.NumPorts1 = io->win[0].len; | ||
657 | if (io->nwin > 1) { | ||
658 | link->io.Attributes2 = link->io.Attributes1; | ||
659 | link->io.BasePort2 = io->win[1].base; | ||
660 | link->io.NumPorts2 = io->win[1].len; | ||
661 | } | ||
662 | } | ||
663 | |||
664 | /* This reserves IO space but doesn't actually enable it */ | ||
665 | CFG_CHECK2(RequestIO, | ||
666 | pcmcia_request_io(link, &link->io)); | ||
667 | |||
668 | /* This configuration table entry is OK */ | ||
669 | break; | ||
670 | |||
671 | next_entry: | ||
672 | CS_CHECK(GetNextTuple, | ||
673 | pcmcia_get_next_tuple(link, &tuple)); | ||
674 | } | 647 | } |
675 | 648 | ||
676 | /* Need to allocate net_device before requesting IRQ handler */ | 649 | /* Need to allocate net_device before requesting IRQ handler */ |
@@ -738,14 +711,12 @@ static int prism2_config(struct pcmcia_device *link) | |||
738 | if (ret == 0 && local->ddev) | 711 | if (ret == 0 && local->ddev) |
739 | strcpy(hw_priv->node.dev_name, local->ddev->name); | 712 | strcpy(hw_priv->node.dev_name, local->ddev->name); |
740 | } | 713 | } |
741 | kfree(parse); | ||
742 | return ret; | 714 | return ret; |
743 | 715 | ||
744 | cs_failed: | 716 | cs_failed: |
745 | cs_error(link, last_fn, last_ret); | 717 | cs_error(link, last_fn, last_ret); |
746 | 718 | ||
747 | failed: | 719 | failed: |
748 | kfree(parse); | ||
749 | kfree(hw_priv); | 720 | kfree(hw_priv); |
750 | prism2_release((u_long)link); | 721 | prism2_release((u_long)link); |
751 | return ret; | 722 | return ret; |