Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCMCIA: soc_common: provide single socket add/remove functionality

Factor out the functionality for adding and removing a single
socket, thereby allowing SoCs to individually register each
socket. The advantage of this approach is that SoCs can then
extend soc_pcmcia_socket as they wish.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>

authored by

Russell King - ARM Linux and committed by
Dominik Brodowski
097e296d 0f767de6

+137 -120
+135 -119
drivers/pcmcia/soc_common.c
··· 574 574 EXPORT_SYMBOL(soc_pcmcia_enable_irqs); 575 575 576 576 577 - LIST_HEAD(soc_pcmcia_sockets); 577 + static LIST_HEAD(soc_pcmcia_sockets); 578 578 static DEFINE_MUTEX(soc_pcmcia_sockets_lock); 579 579 580 580 #ifdef CONFIG_CPU_FREQ ··· 619 619 620 620 #endif 621 621 622 + void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt) 623 + { 624 + mutex_lock(&soc_pcmcia_sockets_lock); 625 + del_timer_sync(&skt->poll_timer); 626 + 627 + pcmcia_unregister_socket(&skt->socket); 628 + 629 + flush_scheduled_work(); 630 + 631 + skt->ops->hw_shutdown(skt); 632 + 633 + soc_common_pcmcia_config_skt(skt, &dead_socket); 634 + 635 + list_del(&skt->node); 636 + mutex_unlock(&soc_pcmcia_sockets_lock); 637 + 638 + iounmap(skt->virt_io); 639 + skt->virt_io = NULL; 640 + release_resource(&skt->res_attr); 641 + release_resource(&skt->res_mem); 642 + release_resource(&skt->res_io); 643 + release_resource(&skt->res_skt); 644 + } 645 + EXPORT_SYMBOL(soc_pcmcia_remove_one); 646 + 647 + int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt) 648 + { 649 + int ret; 650 + 651 + init_timer(&skt->poll_timer); 652 + skt->poll_timer.function = soc_common_pcmcia_poll_event; 653 + skt->poll_timer.data = (unsigned long)skt; 654 + skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD; 655 + 656 + ret = request_resource(&iomem_resource, &skt->res_skt); 657 + if (ret) 658 + goto out_err_1; 659 + 660 + ret = request_resource(&skt->res_skt, &skt->res_io); 661 + if (ret) 662 + goto out_err_2; 663 + 664 + ret = request_resource(&skt->res_skt, &skt->res_mem); 665 + if (ret) 666 + goto out_err_3; 667 + 668 + ret = request_resource(&skt->res_skt, &skt->res_attr); 669 + if (ret) 670 + goto out_err_4; 671 + 672 + skt->virt_io = ioremap(skt->res_io.start, 0x10000); 673 + if (skt->virt_io == NULL) { 674 + ret = -ENOMEM; 675 + goto out_err_5; 676 + } 677 + 678 + mutex_lock(&soc_pcmcia_sockets_lock); 679 + 680 + list_add(&skt->node, &soc_pcmcia_sockets); 681 + 682 + /* 683 + * We initialize default socket timing here, because 684 + * we are not guaranteed to see a SetIOMap operation at 685 + * runtime. 686 + */ 687 + skt->ops->set_timing(skt); 688 + 689 + ret = skt->ops->hw_init(skt); 690 + if (ret) 691 + goto out_err_6; 692 + 693 + skt->socket.ops = &soc_common_pcmcia_operations; 694 + skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD; 695 + skt->socket.resource_ops = &pccard_static_ops; 696 + skt->socket.irq_mask = 0; 697 + skt->socket.map_size = PAGE_SIZE; 698 + skt->socket.pci_irq = skt->irq; 699 + skt->socket.io_offset = (unsigned long)skt->virt_io; 700 + 701 + skt->status = soc_common_pcmcia_skt_state(skt); 702 + 703 + ret = pcmcia_register_socket(&skt->socket); 704 + if (ret) 705 + goto out_err_7; 706 + 707 + add_timer(&skt->poll_timer); 708 + 709 + mutex_unlock(&soc_pcmcia_sockets_lock); 710 + 711 + ret = device_create_file(&skt->socket.dev, &dev_attr_status); 712 + if (ret) 713 + goto out_err_8; 714 + 715 + return ret; 716 + 717 + out_err_8: 718 + mutex_lock(&soc_pcmcia_sockets_lock); 719 + del_timer_sync(&skt->poll_timer); 720 + pcmcia_unregister_socket(&skt->socket); 721 + 722 + out_err_7: 723 + flush_scheduled_work(); 724 + 725 + skt->ops->hw_shutdown(skt); 726 + out_err_6: 727 + list_del(&skt->node); 728 + mutex_unlock(&soc_pcmcia_sockets_lock); 729 + iounmap(skt->virt_io); 730 + out_err_5: 731 + release_resource(&skt->res_attr); 732 + out_err_4: 733 + release_resource(&skt->res_mem); 734 + out_err_3: 735 + release_resource(&skt->res_io); 736 + out_err_2: 737 + release_resource(&skt->res_skt); 738 + out_err_1: 739 + 740 + return ret; 741 + } 742 + EXPORT_SYMBOL(soc_pcmcia_add_one); 743 + 622 744 int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, 623 745 struct skt_dev_info *sinfo) 624 746 { 625 747 struct soc_pcmcia_socket *skt; 626 748 int ret, i; 627 749 628 - mutex_lock(&soc_pcmcia_sockets_lock); 629 - 630 750 /* 631 751 * Initialise the per-socket structure. 632 752 */ 633 - for (i = 0; i < sinfo->nskt; i++) { 753 + for (i = ret = 0; i < sinfo->nskt; i++) { 634 754 skt = &sinfo->skt[i]; 635 755 636 - skt->socket.ops = &soc_common_pcmcia_operations; 637 756 skt->socket.owner = ops->owner; 638 757 skt->socket.dev.parent = dev; 639 - 640 - init_timer(&skt->poll_timer); 641 - skt->poll_timer.function = soc_common_pcmcia_poll_event; 642 - skt->poll_timer.data = (unsigned long)skt; 643 - skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD; 644 758 645 759 skt->dev = dev; 646 760 skt->ops = ops; 647 761 648 - ret = request_resource(&iomem_resource, &skt->res_skt); 762 + ret = soc_pcmcia_add_one(skt); 649 763 if (ret) 650 - goto out_err_1; 651 - 652 - ret = request_resource(&skt->res_skt, &skt->res_io); 653 - if (ret) 654 - goto out_err_2; 655 - 656 - ret = request_resource(&skt->res_skt, &skt->res_mem); 657 - if (ret) 658 - goto out_err_3; 659 - 660 - ret = request_resource(&skt->res_skt, &skt->res_attr); 661 - if (ret) 662 - goto out_err_4; 663 - 664 - skt->virt_io = ioremap(skt->res_io.start, 0x10000); 665 - if (skt->virt_io == NULL) { 666 - ret = -ENOMEM; 667 - goto out_err_5; 668 - } 669 - 670 - list_add(&skt->node, &soc_pcmcia_sockets); 671 - 672 - /* 673 - * We initialize default socket timing here, because 674 - * we are not guaranteed to see a SetIOMap operation at 675 - * runtime. 676 - */ 677 - ops->set_timing(skt); 678 - 679 - ret = ops->hw_init(skt); 680 - if (ret) 681 - goto out_err_6; 682 - 683 - skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD; 684 - skt->socket.resource_ops = &pccard_static_ops; 685 - skt->socket.irq_mask = 0; 686 - skt->socket.map_size = PAGE_SIZE; 687 - skt->socket.pci_irq = skt->irq; 688 - skt->socket.io_offset = (unsigned long)skt->virt_io; 689 - 690 - skt->status = soc_common_pcmcia_skt_state(skt); 691 - 692 - ret = pcmcia_register_socket(&skt->socket); 693 - if (ret) 694 - goto out_err_7; 764 + break; 695 765 696 766 WARN_ON(skt->socket.sock != i); 697 - 698 - add_timer(&skt->poll_timer); 699 - 700 - ret = device_create_file(&skt->socket.dev, &dev_attr_status); 701 - if (ret) 702 - goto out_err_8; 703 767 } 704 768 705 - dev_set_drvdata(dev, sinfo); 706 - ret = 0; 707 - goto out; 769 + if (ret) { 770 + while (--i >= 0) 771 + soc_pcmcia_remove_one(&sinfo->skt[i]); 772 + kfree(sinfo); 773 + } else { 774 + dev_set_drvdata(dev, sinfo); 775 + } 708 776 709 - do { 710 - skt = &sinfo->skt[i]; 711 - 712 - device_remove_file(&skt->socket.dev, &dev_attr_status); 713 - out_err_8: 714 - del_timer_sync(&skt->poll_timer); 715 - pcmcia_unregister_socket(&skt->socket); 716 - 717 - out_err_7: 718 - flush_scheduled_work(); 719 - 720 - ops->hw_shutdown(skt); 721 - out_err_6: 722 - list_del(&skt->node); 723 - iounmap(skt->virt_io); 724 - out_err_5: 725 - release_resource(&skt->res_attr); 726 - out_err_4: 727 - release_resource(&skt->res_mem); 728 - out_err_3: 729 - release_resource(&skt->res_io); 730 - out_err_2: 731 - release_resource(&skt->res_skt); 732 - out_err_1: 733 - i--; 734 - } while (i > 0); 735 - 736 - kfree(sinfo); 737 - 738 - out: 739 - mutex_unlock(&soc_pcmcia_sockets_lock); 740 777 return ret; 741 778 } 742 779 EXPORT_SYMBOL(soc_common_drv_pcmcia_probe); ··· 785 748 786 749 dev_set_drvdata(dev, NULL); 787 750 788 - mutex_lock(&soc_pcmcia_sockets_lock); 789 - for (i = 0; i < sinfo->nskt; i++) { 790 - struct soc_pcmcia_socket *skt = &sinfo->skt[i]; 791 - 792 - del_timer_sync(&skt->poll_timer); 793 - 794 - pcmcia_unregister_socket(&skt->socket); 795 - 796 - flush_scheduled_work(); 797 - 798 - skt->ops->hw_shutdown(skt); 799 - 800 - soc_common_pcmcia_config_skt(skt, &dead_socket); 801 - 802 - list_del(&skt->node); 803 - iounmap(skt->virt_io); 804 - skt->virt_io = NULL; 805 - release_resource(&skt->res_attr); 806 - release_resource(&skt->res_mem); 807 - release_resource(&skt->res_io); 808 - release_resource(&skt->res_skt); 809 - } 810 - mutex_unlock(&soc_pcmcia_sockets_lock); 751 + for (i = 0; i < sinfo->nskt; i++) 752 + soc_pcmcia_remove_one(&sinfo->skt[i]); 811 753 812 754 kfree(sinfo); 813 755
+2 -1
drivers/pcmcia/soc_common.h
··· 135 135 extern void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *, struct soc_pcmcia_timing *); 136 136 137 137 138 - extern struct list_head soc_pcmcia_sockets; 138 + void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt); 139 + int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt); 139 140 140 141 extern int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, struct skt_dev_info *sinfo); 141 142 extern int soc_common_drv_pcmcia_remove(struct device *dev);