diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2009-10-18 12:14:32 -0400 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2009-10-24 11:13:01 -0400 |
commit | 6ae3b84d979308671bf6f6a2123c258a8603d61c (patch) | |
tree | 63fdd28c8b92cd34fbaf7d4cac3644cc7b06822c /drivers/serial | |
parent | bb015f0c85362aa767f8f00f50a40d85e489414f (diff) |
serial_cs: use pcmcia_loop_config() and pre-determined values
As the PCMCIA core already determines the multifunction count, the
ConfigBase address and the Present value, we can use them directly
instead of parsing the CIS again. By making use of pcmcia_loop_config(),
we can further remove the remaining call to pcmcia_get_first_tuple()
and friends.
CC: linux-serial@vger.kernel.org
CC: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/serial_cs.c | 87 |
1 files changed, 23 insertions, 64 deletions
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index ff4617e21426..7bf02cf3123f 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -426,21 +426,6 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, | |||
426 | 426 | ||
427 | /*====================================================================*/ | 427 | /*====================================================================*/ |
428 | 428 | ||
429 | static int | ||
430 | first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse) | ||
431 | { | ||
432 | int i; | ||
433 | i = pcmcia_get_first_tuple(handle, tuple); | ||
434 | if (i != 0) | ||
435 | return i; | ||
436 | i = pcmcia_get_tuple_data(handle, tuple); | ||
437 | if (i != 0) | ||
438 | return i; | ||
439 | return pcmcia_parse_tuple(tuple, parse); | ||
440 | } | ||
441 | |||
442 | /*====================================================================*/ | ||
443 | |||
444 | static int simple_config_check(struct pcmcia_device *p_dev, | 429 | static int simple_config_check(struct pcmcia_device *p_dev, |
445 | cistpl_cftable_entry_t *cf, | 430 | cistpl_cftable_entry_t *cf, |
446 | cistpl_cftable_entry_t *dflt, | 431 | cistpl_cftable_entry_t *dflt, |
@@ -665,6 +650,25 @@ static int multi_config(struct pcmcia_device *link) | |||
665 | return 0; | 650 | return 0; |
666 | } | 651 | } |
667 | 652 | ||
653 | static int serial_check_for_multi(struct pcmcia_device *p_dev, | ||
654 | cistpl_cftable_entry_t *cf, | ||
655 | cistpl_cftable_entry_t *dflt, | ||
656 | unsigned int vcc, | ||
657 | void *priv_data) | ||
658 | { | ||
659 | struct serial_info *info = p_dev->priv; | ||
660 | |||
661 | if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) | ||
662 | info->multi = cf->io.win[0].len >> 3; | ||
663 | |||
664 | if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && | ||
665 | (cf->io.win[1].len == 8)) | ||
666 | info->multi = 2; | ||
667 | |||
668 | return 0; /* break */ | ||
669 | } | ||
670 | |||
671 | |||
668 | /*====================================================================== | 672 | /*====================================================================== |
669 | 673 | ||
670 | serial_config() is scheduled to run after a CARD_INSERTION event | 674 | serial_config() is scheduled to run after a CARD_INSERTION event |
@@ -676,46 +680,14 @@ static int multi_config(struct pcmcia_device *link) | |||
676 | static int serial_config(struct pcmcia_device * link) | 680 | static int serial_config(struct pcmcia_device * link) |
677 | { | 681 | { |
678 | struct serial_info *info = link->priv; | 682 | struct serial_info *info = link->priv; |
679 | struct serial_cfg_mem *cfg_mem; | 683 | int i; |
680 | tuple_t *tuple; | ||
681 | u_char *buf; | ||
682 | cisparse_t *parse; | ||
683 | cistpl_cftable_entry_t *cf; | ||
684 | int i, last_ret, last_fn; | ||
685 | 684 | ||
686 | DEBUG(0, "serial_config(0x%p)\n", link); | 685 | DEBUG(0, "serial_config(0x%p)\n", link); |
687 | 686 | ||
688 | cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); | ||
689 | if (!cfg_mem) | ||
690 | goto failed; | ||
691 | |||
692 | tuple = &cfg_mem->tuple; | ||
693 | parse = &cfg_mem->parse; | ||
694 | cf = &parse->cftable_entry; | ||
695 | buf = cfg_mem->buf; | ||
696 | |||
697 | tuple->TupleData = (cisdata_t *) buf; | ||
698 | tuple->TupleOffset = 0; | ||
699 | tuple->TupleDataMax = 255; | ||
700 | tuple->Attributes = 0; | ||
701 | |||
702 | /* Get configuration register information */ | ||
703 | tuple->DesiredTuple = CISTPL_CONFIG; | ||
704 | last_ret = first_tuple(link, tuple, parse); | ||
705 | if (last_ret != 0) { | ||
706 | last_fn = ParseTuple; | ||
707 | goto cs_failed; | ||
708 | } | ||
709 | link->conf.ConfigBase = parse->config.base; | ||
710 | link->conf.Present = parse->config.rmask[0]; | ||
711 | |||
712 | /* Is this a compliant multifunction card? */ | 687 | /* Is this a compliant multifunction card? */ |
713 | tuple->DesiredTuple = CISTPL_LONGLINK_MFC; | 688 | info->multi = (link->socket->functions > 1); |
714 | tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; | ||
715 | info->multi = (first_tuple(link, tuple, parse) == 0); | ||
716 | 689 | ||
717 | /* Is this a multiport card? */ | 690 | /* Is this a multiport card? */ |
718 | tuple->DesiredTuple = CISTPL_MANFID; | ||
719 | info->manfid = link->manf_id; | 691 | info->manfid = link->manf_id; |
720 | info->prodid = link->card_id; | 692 | info->prodid = link->card_id; |
721 | 693 | ||
@@ -730,20 +702,11 @@ static int serial_config(struct pcmcia_device * link) | |||
730 | 702 | ||
731 | /* Another check for dual-serial cards: look for either serial or | 703 | /* Another check for dual-serial cards: look for either serial or |
732 | multifunction cards that ask for appropriate IO port ranges */ | 704 | multifunction cards that ask for appropriate IO port ranges */ |
733 | tuple->DesiredTuple = CISTPL_FUNCID; | ||
734 | if ((info->multi == 0) && | 705 | if ((info->multi == 0) && |
735 | (link->has_func_id) && | 706 | (link->has_func_id) && |
736 | ((link->func_id == CISTPL_FUNCID_MULTI) || | 707 | ((link->func_id == CISTPL_FUNCID_MULTI) || |
737 | (link->func_id == CISTPL_FUNCID_SERIAL))) { | 708 | (link->func_id == CISTPL_FUNCID_SERIAL))) |
738 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; | 709 | pcmcia_loop_config(link, serial_check_for_multi, info); |
739 | if (first_tuple(link, tuple, parse) == 0) { | ||
740 | if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) | ||
741 | info->multi = cf->io.win[0].len >> 3; | ||
742 | if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && | ||
743 | (cf->io.win[1].len == 8)) | ||
744 | info->multi = 2; | ||
745 | } | ||
746 | } | ||
747 | 710 | ||
748 | /* | 711 | /* |
749 | * Apply any multi-port quirk. | 712 | * Apply any multi-port quirk. |
@@ -768,14 +731,10 @@ static int serial_config(struct pcmcia_device * link) | |||
768 | goto failed; | 731 | goto failed; |
769 | 732 | ||
770 | link->dev_node = &info->node[0]; | 733 | link->dev_node = &info->node[0]; |
771 | kfree(cfg_mem); | ||
772 | return 0; | 734 | return 0; |
773 | 735 | ||
774 | cs_failed: | ||
775 | cs_error(link, last_fn, last_ret); | ||
776 | failed: | 736 | failed: |
777 | serial_remove(link); | 737 | serial_remove(link); |
778 | kfree(cfg_mem); | ||
779 | return -ENODEV; | 738 | return -ENODEV; |
780 | } | 739 | } |
781 | 740 | ||