diff options
author | Yum Rayan <yum.rayan@gmail.com> | 2005-05-05 18:14:10 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-05-15 23:16:30 -0400 |
commit | 4638aef40ba9ebb9734caeed1f373c24015259fd (patch) | |
tree | 12aaa5eeaabefd1b9f92f881c1f9aa5f9f41e7d7 /drivers/net/pcmcia/smc91c92_cs.c | |
parent | 54d06c3184f416b8244816f3c1d3abb55e99d909 (diff) |
[PATCH] smc91c92_cs: Reduce stack usage in smc91c92_event()
This patch reduces the stack usage of the function smc91c92_event() in
smc91c92_cs driver from 3540 to 132. Currently this is the highest stack
user in linux-2.6.12-rc2-mm3. I used a patched version of gcc 3.4.3 on
i386 with -fno-unit-at-a-time disabled.
The patch has only been compile tested.
Acked-by: Jörn Engel <joern@wohnheim.fh-wedel.de>
Acked-by: Randy Dunlap <rddunlap@osdl.org>
Signed-off-by: Yum Rayan <yum.rayan@gmail.com>
Cc: Jeff Garzik <jgarzik@pobox.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Diffstat (limited to 'drivers/net/pcmcia/smc91c92_cs.c')
-rw-r--r-- | drivers/net/pcmcia/smc91c92_cs.c | 287 |
1 files changed, 189 insertions, 98 deletions
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 85a152173148..8a5e52c40e46 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
@@ -127,6 +127,12 @@ struct smc_private { | |||
127 | int rx_ovrn; | 127 | int rx_ovrn; |
128 | }; | 128 | }; |
129 | 129 | ||
130 | struct smc_cfg_mem { | ||
131 | tuple_t tuple; | ||
132 | cisparse_t parse; | ||
133 | u_char buf[255]; | ||
134 | }; | ||
135 | |||
130 | /* Special definitions for Megahertz multifunction cards */ | 136 | /* Special definitions for Megahertz multifunction cards */ |
131 | #define MEGAHERTZ_ISR 0x0380 | 137 | #define MEGAHERTZ_ISR 0x0380 |
132 | 138 | ||
@@ -498,14 +504,24 @@ static int mhz_mfc_config(dev_link_t *link) | |||
498 | { | 504 | { |
499 | struct net_device *dev = link->priv; | 505 | struct net_device *dev = link->priv; |
500 | struct smc_private *smc = netdev_priv(dev); | 506 | struct smc_private *smc = netdev_priv(dev); |
501 | tuple_t tuple; | 507 | struct smc_cfg_mem *cfg_mem; |
502 | cisparse_t parse; | 508 | tuple_t *tuple; |
503 | u_char buf[255]; | 509 | cisparse_t *parse; |
504 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | 510 | cistpl_cftable_entry_t *cf; |
511 | u_char *buf; | ||
505 | win_req_t req; | 512 | win_req_t req; |
506 | memreq_t mem; | 513 | memreq_t mem; |
507 | int i, k; | 514 | int i, k; |
508 | 515 | ||
516 | cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); | ||
517 | if (!cfg_mem) | ||
518 | return CS_OUT_OF_RESOURCE; | ||
519 | |||
520 | tuple = &cfg_mem->tuple; | ||
521 | parse = &cfg_mem->parse; | ||
522 | cf = &parse->cftable_entry; | ||
523 | buf = cfg_mem->buf; | ||
524 | |||
509 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 525 | link->conf.Attributes |= CONF_ENABLE_SPKR; |
510 | link->conf.Status = CCSR_AUDIO_ENA; | 526 | link->conf.Status = CCSR_AUDIO_ENA; |
511 | link->irq.Attributes = | 527 | link->irq.Attributes = |
@@ -514,12 +530,12 @@ static int mhz_mfc_config(dev_link_t *link) | |||
514 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; | 530 | link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; |
515 | link->io.NumPorts2 = 8; | 531 | link->io.NumPorts2 = 8; |
516 | 532 | ||
517 | tuple.Attributes = tuple.TupleOffset = 0; | 533 | tuple->Attributes = tuple->TupleOffset = 0; |
518 | tuple.TupleData = (cisdata_t *)buf; | 534 | tuple->TupleData = (cisdata_t *)buf; |
519 | tuple.TupleDataMax = sizeof(buf); | 535 | tuple->TupleDataMax = 255; |
520 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 536 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; |
521 | 537 | ||
522 | i = first_tuple(link->handle, &tuple, &parse); | 538 | i = first_tuple(link->handle, tuple, parse); |
523 | /* The Megahertz combo cards have modem-like CIS entries, so | 539 | /* The Megahertz combo cards have modem-like CIS entries, so |
524 | we have to explicitly try a bunch of port combinations. */ | 540 | we have to explicitly try a bunch of port combinations. */ |
525 | while (i == CS_SUCCESS) { | 541 | while (i == CS_SUCCESS) { |
@@ -532,10 +548,10 @@ static int mhz_mfc_config(dev_link_t *link) | |||
532 | if (i == CS_SUCCESS) break; | 548 | if (i == CS_SUCCESS) break; |
533 | } | 549 | } |
534 | if (i == CS_SUCCESS) break; | 550 | if (i == CS_SUCCESS) break; |
535 | i = next_tuple(link->handle, &tuple, &parse); | 551 | i = next_tuple(link->handle, tuple, parse); |
536 | } | 552 | } |
537 | if (i != CS_SUCCESS) | 553 | if (i != CS_SUCCESS) |
538 | return i; | 554 | goto free_cfg_mem; |
539 | dev->base_addr = link->io.BasePort1; | 555 | dev->base_addr = link->io.BasePort1; |
540 | 556 | ||
541 | /* Allocate a memory window, for accessing the ISR */ | 557 | /* Allocate a memory window, for accessing the ISR */ |
@@ -544,7 +560,7 @@ static int mhz_mfc_config(dev_link_t *link) | |||
544 | req.AccessSpeed = 0; | 560 | req.AccessSpeed = 0; |
545 | i = pcmcia_request_window(&link->handle, &req, &link->win); | 561 | i = pcmcia_request_window(&link->handle, &req, &link->win); |
546 | if (i != CS_SUCCESS) | 562 | if (i != CS_SUCCESS) |
547 | return i; | 563 | goto free_cfg_mem; |
548 | smc->base = ioremap(req.Base, req.Size); | 564 | smc->base = ioremap(req.Base, req.Size); |
549 | mem.CardOffset = mem.Page = 0; | 565 | mem.CardOffset = mem.Page = 0; |
550 | if (smc->manfid == MANFID_MOTOROLA) | 566 | if (smc->manfid == MANFID_MOTOROLA) |
@@ -556,6 +572,8 @@ static int mhz_mfc_config(dev_link_t *link) | |||
556 | && (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | 572 | && (smc->cardid == PRODID_MEGAHERTZ_EM3288)) |
557 | mhz_3288_power(link); | 573 | mhz_3288_power(link); |
558 | 574 | ||
575 | free_cfg_mem: | ||
576 | kfree(cfg_mem); | ||
559 | return i; | 577 | return i; |
560 | } | 578 | } |
561 | 579 | ||
@@ -563,39 +581,61 @@ static int mhz_setup(dev_link_t *link) | |||
563 | { | 581 | { |
564 | client_handle_t handle = link->handle; | 582 | client_handle_t handle = link->handle; |
565 | struct net_device *dev = link->priv; | 583 | struct net_device *dev = link->priv; |
566 | tuple_t tuple; | 584 | struct smc_cfg_mem *cfg_mem; |
567 | cisparse_t parse; | 585 | tuple_t *tuple; |
568 | u_char buf[255], *station_addr; | 586 | cisparse_t *parse; |
587 | u_char *buf, *station_addr; | ||
588 | int rc; | ||
589 | |||
590 | cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); | ||
591 | if (!cfg_mem) | ||
592 | return -1; | ||
593 | |||
594 | tuple = &cfg_mem->tuple; | ||
595 | parse = &cfg_mem->parse; | ||
596 | buf = cfg_mem->buf; | ||
569 | 597 | ||
570 | tuple.Attributes = tuple.TupleOffset = 0; | 598 | tuple->Attributes = tuple->TupleOffset = 0; |
571 | tuple.TupleData = buf; | 599 | tuple->TupleData = (cisdata_t *)buf; |
572 | tuple.TupleDataMax = sizeof(buf); | 600 | tuple->TupleDataMax = 255; |
573 | 601 | ||
574 | /* Read the station address from the CIS. It is stored as the last | 602 | /* Read the station address from the CIS. It is stored as the last |
575 | (fourth) string in the Version 1 Version/ID tuple. */ | 603 | (fourth) string in the Version 1 Version/ID tuple. */ |
576 | tuple.DesiredTuple = CISTPL_VERS_1; | 604 | tuple->DesiredTuple = CISTPL_VERS_1; |
577 | if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS) | 605 | if (first_tuple(handle, tuple, parse) != CS_SUCCESS) { |
578 | return -1; | 606 | rc = -1; |
607 | goto free_cfg_mem; | ||
608 | } | ||
579 | /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ | 609 | /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ |
580 | if (next_tuple(handle, &tuple, &parse) != CS_SUCCESS) | 610 | if (next_tuple(handle, tuple, parse) != CS_SUCCESS) |
581 | first_tuple(handle, &tuple, &parse); | 611 | first_tuple(handle, tuple, parse); |
582 | if (parse.version_1.ns > 3) { | 612 | if (parse->version_1.ns > 3) { |
583 | station_addr = parse.version_1.str + parse.version_1.ofs[3]; | 613 | station_addr = parse->version_1.str + parse->version_1.ofs[3]; |
584 | if (cvt_ascii_address(dev, station_addr) == 0) | 614 | if (cvt_ascii_address(dev, station_addr) == 0) { |
585 | return 0; | 615 | rc = 0; |
616 | goto free_cfg_mem; | ||
617 | } | ||
586 | } | 618 | } |
587 | 619 | ||
588 | /* Another possibility: for the EM3288, in a special tuple */ | 620 | /* Another possibility: for the EM3288, in a special tuple */ |
589 | tuple.DesiredTuple = 0x81; | 621 | tuple->DesiredTuple = 0x81; |
590 | if (pcmcia_get_first_tuple(handle, &tuple) != CS_SUCCESS) | 622 | if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) { |
591 | return -1; | 623 | rc = -1; |
592 | if (pcmcia_get_tuple_data(handle, &tuple) != CS_SUCCESS) | 624 | goto free_cfg_mem; |
593 | return -1; | 625 | } |
626 | if (pcmcia_get_tuple_data(handle, tuple) != CS_SUCCESS) { | ||
627 | rc = -1; | ||
628 | goto free_cfg_mem; | ||
629 | } | ||
594 | buf[12] = '\0'; | 630 | buf[12] = '\0'; |
595 | if (cvt_ascii_address(dev, buf) == 0) | 631 | if (cvt_ascii_address(dev, buf) == 0) { |
596 | return 0; | 632 | rc = 0; |
597 | 633 | goto free_cfg_mem; | |
598 | return -1; | 634 | } |
635 | rc = -1; | ||
636 | free_cfg_mem: | ||
637 | kfree(cfg_mem); | ||
638 | return rc; | ||
599 | } | 639 | } |
600 | 640 | ||
601 | /*====================================================================== | 641 | /*====================================================================== |
@@ -665,19 +705,29 @@ static int mot_setup(dev_link_t *link) | |||
665 | static int smc_config(dev_link_t *link) | 705 | static int smc_config(dev_link_t *link) |
666 | { | 706 | { |
667 | struct net_device *dev = link->priv; | 707 | struct net_device *dev = link->priv; |
668 | tuple_t tuple; | 708 | struct smc_cfg_mem *cfg_mem; |
669 | cisparse_t parse; | 709 | tuple_t *tuple; |
670 | u_char buf[255]; | 710 | cisparse_t *parse; |
671 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | 711 | cistpl_cftable_entry_t *cf; |
712 | u_char *buf; | ||
672 | int i; | 713 | int i; |
673 | 714 | ||
674 | tuple.Attributes = tuple.TupleOffset = 0; | 715 | cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); |
675 | tuple.TupleData = (cisdata_t *)buf; | 716 | if (!cfg_mem) |
676 | tuple.TupleDataMax = sizeof(buf); | 717 | return CS_OUT_OF_RESOURCE; |
677 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 718 | |
719 | tuple = &cfg_mem->tuple; | ||
720 | parse = &cfg_mem->parse; | ||
721 | cf = &parse->cftable_entry; | ||
722 | buf = cfg_mem->buf; | ||
723 | |||
724 | tuple->Attributes = tuple->TupleOffset = 0; | ||
725 | tuple->TupleData = (cisdata_t *)buf; | ||
726 | tuple->TupleDataMax = 255; | ||
727 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
678 | 728 | ||
679 | link->io.NumPorts1 = 16; | 729 | link->io.NumPorts1 = 16; |
680 | i = first_tuple(link->handle, &tuple, &parse); | 730 | i = first_tuple(link->handle, tuple, parse); |
681 | while (i != CS_NO_MORE_ITEMS) { | 731 | while (i != CS_NO_MORE_ITEMS) { |
682 | if (i == CS_SUCCESS) { | 732 | if (i == CS_SUCCESS) { |
683 | link->conf.ConfigIndex = cf->index; | 733 | link->conf.ConfigIndex = cf->index; |
@@ -686,10 +736,12 @@ static int smc_config(dev_link_t *link) | |||
686 | i = pcmcia_request_io(link->handle, &link->io); | 736 | i = pcmcia_request_io(link->handle, &link->io); |
687 | if (i == CS_SUCCESS) break; | 737 | if (i == CS_SUCCESS) break; |
688 | } | 738 | } |
689 | i = next_tuple(link->handle, &tuple, &parse); | 739 | i = next_tuple(link->handle, tuple, parse); |
690 | } | 740 | } |
691 | if (i == CS_SUCCESS) | 741 | if (i == CS_SUCCESS) |
692 | dev->base_addr = link->io.BasePort1; | 742 | dev->base_addr = link->io.BasePort1; |
743 | |||
744 | kfree(cfg_mem); | ||
693 | return i; | 745 | return i; |
694 | } | 746 | } |
695 | 747 | ||
@@ -697,41 +749,58 @@ static int smc_setup(dev_link_t *link) | |||
697 | { | 749 | { |
698 | client_handle_t handle = link->handle; | 750 | client_handle_t handle = link->handle; |
699 | struct net_device *dev = link->priv; | 751 | struct net_device *dev = link->priv; |
700 | tuple_t tuple; | 752 | struct smc_cfg_mem *cfg_mem; |
701 | cisparse_t parse; | 753 | tuple_t *tuple; |
754 | cisparse_t *parse; | ||
702 | cistpl_lan_node_id_t *node_id; | 755 | cistpl_lan_node_id_t *node_id; |
703 | u_char buf[255], *station_addr; | 756 | u_char *buf, *station_addr; |
704 | int i; | 757 | int i, rc; |
705 | 758 | ||
706 | tuple.Attributes = tuple.TupleOffset = 0; | 759 | cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); |
707 | tuple.TupleData = buf; | 760 | if (!cfg_mem) |
708 | tuple.TupleDataMax = sizeof(buf); | 761 | return CS_OUT_OF_RESOURCE; |
762 | |||
763 | tuple = &cfg_mem->tuple; | ||
764 | parse = &cfg_mem->parse; | ||
765 | buf = cfg_mem->buf; | ||
766 | |||
767 | tuple->Attributes = tuple->TupleOffset = 0; | ||
768 | tuple->TupleData = (cisdata_t *)buf; | ||
769 | tuple->TupleDataMax = 255; | ||
709 | 770 | ||
710 | /* Check for a LAN function extension tuple */ | 771 | /* Check for a LAN function extension tuple */ |
711 | tuple.DesiredTuple = CISTPL_FUNCE; | 772 | tuple->DesiredTuple = CISTPL_FUNCE; |
712 | i = first_tuple(handle, &tuple, &parse); | 773 | i = first_tuple(handle, tuple, parse); |
713 | while (i == CS_SUCCESS) { | 774 | while (i == CS_SUCCESS) { |
714 | if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID) | 775 | if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID) |
715 | break; | 776 | break; |
716 | i = next_tuple(handle, &tuple, &parse); | 777 | i = next_tuple(handle, tuple, parse); |
717 | } | 778 | } |
718 | if (i == CS_SUCCESS) { | 779 | if (i == CS_SUCCESS) { |
719 | node_id = (cistpl_lan_node_id_t *)parse.funce.data; | 780 | node_id = (cistpl_lan_node_id_t *)parse->funce.data; |
720 | if (node_id->nb == 6) { | 781 | if (node_id->nb == 6) { |
721 | for (i = 0; i < 6; i++) | 782 | for (i = 0; i < 6; i++) |
722 | dev->dev_addr[i] = node_id->id[i]; | 783 | dev->dev_addr[i] = node_id->id[i]; |
723 | return 0; | 784 | rc = 0; |
785 | goto free_cfg_mem; | ||
724 | } | 786 | } |
725 | } | 787 | } |
726 | /* Try the third string in the Version 1 Version/ID tuple. */ | 788 | /* Try the third string in the Version 1 Version/ID tuple. */ |
727 | tuple.DesiredTuple = CISTPL_VERS_1; | 789 | tuple->DesiredTuple = CISTPL_VERS_1; |
728 | if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS) | 790 | if (first_tuple(handle, tuple, parse) != CS_SUCCESS) { |
729 | return -1; | 791 | rc = -1; |
730 | station_addr = parse.version_1.str + parse.version_1.ofs[2]; | 792 | goto free_cfg_mem; |
731 | if (cvt_ascii_address(dev, station_addr) == 0) | 793 | } |
732 | return 0; | 794 | station_addr = parse->version_1.str + parse->version_1.ofs[2]; |
795 | if (cvt_ascii_address(dev, station_addr) == 0) { | ||
796 | rc = 0; | ||
797 | goto free_cfg_mem; | ||
798 | } | ||
733 | 799 | ||
734 | return -1; | 800 | rc = -1; |
801 | free_cfg_mem: | ||
802 | kfree(cfg_mem); | ||
803 | return rc; | ||
735 | } | 804 | } |
736 | 805 | ||
737 | /*====================================================================*/ | 806 | /*====================================================================*/ |
@@ -773,26 +842,36 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) | |||
773 | { | 842 | { |
774 | client_handle_t handle = link->handle; | 843 | client_handle_t handle = link->handle; |
775 | struct net_device *dev = link->priv; | 844 | struct net_device *dev = link->priv; |
776 | tuple_t tuple; | 845 | struct smc_cfg_mem *cfg_mem; |
777 | u_char buf[255]; | 846 | tuple_t *tuple; |
778 | int i; | 847 | u_char *buf; |
848 | int i, rc; | ||
779 | 849 | ||
780 | tuple.Attributes = TUPLE_RETURN_COMMON; | 850 | cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); |
781 | tuple.TupleData = buf; | 851 | if (!cfg_mem) |
782 | tuple.TupleDataMax = sizeof(buf); | 852 | return -1; |
783 | tuple.TupleOffset = 0; | 853 | |
854 | tuple = &cfg_mem->tuple; | ||
855 | buf = cfg_mem->buf; | ||
856 | |||
857 | tuple->Attributes = TUPLE_RETURN_COMMON; | ||
858 | tuple->TupleData = (cisdata_t *)buf; | ||
859 | tuple->TupleDataMax = 255; | ||
860 | tuple->TupleOffset = 0; | ||
784 | 861 | ||
785 | /* Read the station address from tuple 0x90, subtuple 0x04 */ | 862 | /* Read the station address from tuple 0x90, subtuple 0x04 */ |
786 | tuple.DesiredTuple = 0x90; | 863 | tuple->DesiredTuple = 0x90; |
787 | i = pcmcia_get_first_tuple(handle, &tuple); | 864 | i = pcmcia_get_first_tuple(handle, tuple); |
788 | while (i == CS_SUCCESS) { | 865 | while (i == CS_SUCCESS) { |
789 | i = pcmcia_get_tuple_data(handle, &tuple); | 866 | i = pcmcia_get_tuple_data(handle, tuple); |
790 | if ((i != CS_SUCCESS) || (buf[0] == 0x04)) | 867 | if ((i != CS_SUCCESS) || (buf[0] == 0x04)) |
791 | break; | 868 | break; |
792 | i = pcmcia_get_next_tuple(handle, &tuple); | 869 | i = pcmcia_get_next_tuple(handle, tuple); |
870 | } | ||
871 | if (i != CS_SUCCESS) { | ||
872 | rc = -1; | ||
873 | goto free_cfg_mem; | ||
793 | } | 874 | } |
794 | if (i != CS_SUCCESS) | ||
795 | return -1; | ||
796 | for (i = 0; i < 6; i++) | 875 | for (i = 0; i < 6; i++) |
797 | dev->dev_addr[i] = buf[i+2]; | 876 | dev->dev_addr[i] = buf[i+2]; |
798 | 877 | ||
@@ -814,8 +893,10 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) | |||
814 | inw(link->io.BasePort1 + OSITECH_AUI_PWR), | 893 | inw(link->io.BasePort1 + OSITECH_AUI_PWR), |
815 | inw(link->io.BasePort1 + OSITECH_RESET_ISR)); | 894 | inw(link->io.BasePort1 + OSITECH_RESET_ISR)); |
816 | } | 895 | } |
817 | 896 | rc = 0; | |
818 | return 0; | 897 | free_cfg_mem: |
898 | kfree(cfg_mem); | ||
899 | return rc; | ||
819 | } | 900 | } |
820 | 901 | ||
821 | /*====================================================================== | 902 | /*====================================================================== |
@@ -887,9 +968,10 @@ static void smc91c92_config(dev_link_t *link) | |||
887 | client_handle_t handle = link->handle; | 968 | client_handle_t handle = link->handle; |
888 | struct net_device *dev = link->priv; | 969 | struct net_device *dev = link->priv; |
889 | struct smc_private *smc = netdev_priv(dev); | 970 | struct smc_private *smc = netdev_priv(dev); |
890 | tuple_t tuple; | 971 | struct smc_cfg_mem *cfg_mem; |
891 | cisparse_t parse; | 972 | tuple_t *tuple; |
892 | u_short buf[32]; | 973 | cisparse_t *parse; |
974 | u_char *buf; | ||
893 | char *name; | 975 | char *name; |
894 | int i, j, rev; | 976 | int i, j, rev; |
895 | kio_addr_t ioaddr; | 977 | kio_addr_t ioaddr; |
@@ -897,21 +979,29 @@ static void smc91c92_config(dev_link_t *link) | |||
897 | 979 | ||
898 | DEBUG(0, "smc91c92_config(0x%p)\n", link); | 980 | DEBUG(0, "smc91c92_config(0x%p)\n", link); |
899 | 981 | ||
900 | tuple.Attributes = tuple.TupleOffset = 0; | 982 | cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); |
901 | tuple.TupleData = (cisdata_t *)buf; | 983 | if (!cfg_mem) |
902 | tuple.TupleDataMax = sizeof(buf); | 984 | goto config_failed; |
903 | 985 | ||
904 | tuple.DesiredTuple = CISTPL_CONFIG; | 986 | tuple = &cfg_mem->tuple; |
905 | i = first_tuple(handle, &tuple, &parse); | 987 | parse = &cfg_mem->parse; |
906 | CS_EXIT_TEST(i, ParseTuple, config_failed); | 988 | buf = cfg_mem->buf; |
907 | link->conf.ConfigBase = parse.config.base; | ||
908 | link->conf.Present = parse.config.rmask[0]; | ||
909 | 989 | ||
910 | tuple.DesiredTuple = CISTPL_MANFID; | 990 | tuple->Attributes = tuple->TupleOffset = 0; |
911 | tuple.Attributes = TUPLE_RETURN_COMMON; | 991 | tuple->TupleData = (cisdata_t *)buf; |
912 | if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { | 992 | tuple->TupleDataMax = 64; |
913 | smc->manfid = parse.manfid.manf; | 993 | |
914 | smc->cardid = parse.manfid.card; | 994 | tuple->DesiredTuple = CISTPL_CONFIG; |
995 | i = first_tuple(handle, tuple, parse); | ||
996 | CS_EXIT_TEST(i, ParseTuple, config_failed); | ||
997 | link->conf.ConfigBase = parse->config.base; | ||
998 | link->conf.Present = parse->config.rmask[0]; | ||
999 | |||
1000 | tuple->DesiredTuple = CISTPL_MANFID; | ||
1001 | tuple->Attributes = TUPLE_RETURN_COMMON; | ||
1002 | if (first_tuple(handle, tuple, parse) == CS_SUCCESS) { | ||
1003 | smc->manfid = parse->manfid.manf; | ||
1004 | smc->cardid = parse->manfid.card; | ||
915 | } | 1005 | } |
916 | 1006 | ||
917 | /* Configure card */ | 1007 | /* Configure card */ |
@@ -1046,7 +1136,7 @@ static void smc91c92_config(dev_link_t *link) | |||
1046 | printk(KERN_NOTICE " No MII transceivers found!\n"); | 1136 | printk(KERN_NOTICE " No MII transceivers found!\n"); |
1047 | } | 1137 | } |
1048 | } | 1138 | } |
1049 | 1139 | kfree(cfg_mem); | |
1050 | return; | 1140 | return; |
1051 | 1141 | ||
1052 | config_undo: | 1142 | config_undo: |
@@ -1054,6 +1144,7 @@ config_undo: | |||
1054 | config_failed: /* CS_EXIT_TEST() calls jump to here... */ | 1144 | config_failed: /* CS_EXIT_TEST() calls jump to here... */ |
1055 | smc91c92_release(link); | 1145 | smc91c92_release(link); |
1056 | link->state &= ~DEV_CONFIG_PENDING; | 1146 | link->state &= ~DEV_CONFIG_PENDING; |
1147 | kfree(cfg_mem); | ||
1057 | 1148 | ||
1058 | } /* smc91c92_config */ | 1149 | } /* smc91c92_config */ |
1059 | 1150 | ||