diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2013-02-06 07:06:39 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-02-06 14:21:51 -0500 |
commit | 2703d4b2e673cc240ad06d79d131fd1d0f77d65d (patch) | |
tree | 0e5bd20e88e2de4912ba44de8e0b6764c4028791 /drivers/misc/mei/main.c | |
parent | 890537b3ac953ad2cc4f5ecb83744e967ae2aa31 (diff) |
mei: sperate interface and pci code into two files
leave misc file operations in the main
and move PCI related code into pci-me
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei/main.c')
-rw-r--r-- | drivers/misc/mei/main.c | 354 |
1 files changed, 12 insertions, 342 deletions
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 123c663509ef..018623c9a8e1 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c | |||
@@ -43,54 +43,6 @@ | |||
43 | #include "hw-me.h" | 43 | #include "hw-me.h" |
44 | #include "client.h" | 44 | #include "client.h" |
45 | 45 | ||
46 | /* AMT device is a singleton on the platform */ | ||
47 | static struct pci_dev *mei_pdev; | ||
48 | |||
49 | /* mei_pci_tbl - PCI Device ID Table */ | ||
50 | static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = { | ||
51 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)}, | ||
52 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82G35)}, | ||
53 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82Q965)}, | ||
54 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82G965)}, | ||
55 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82GM965)}, | ||
56 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82GME965)}, | ||
57 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82Q35)}, | ||
58 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82G33)}, | ||
59 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82Q33)}, | ||
60 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82X38)}, | ||
61 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_3200)}, | ||
62 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_6)}, | ||
63 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_7)}, | ||
64 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_8)}, | ||
65 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_9)}, | ||
66 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_10)}, | ||
67 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_1)}, | ||
68 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_2)}, | ||
69 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_3)}, | ||
70 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_4)}, | ||
71 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_1)}, | ||
72 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_2)}, | ||
73 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_3)}, | ||
74 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_4)}, | ||
75 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_IBXPK_1)}, | ||
76 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_IBXPK_2)}, | ||
77 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_CPT_1)}, | ||
78 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PBG_1)}, | ||
79 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)}, | ||
80 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)}, | ||
81 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)}, | ||
82 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT)}, | ||
83 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_LP)}, | ||
84 | |||
85 | /* required last entry */ | ||
86 | {0, } | ||
87 | }; | ||
88 | |||
89 | MODULE_DEVICE_TABLE(pci, mei_pci_tbl); | ||
90 | |||
91 | static DEFINE_MUTEX(mei_mutex); | ||
92 | |||
93 | |||
94 | /** | 46 | /** |
95 | * mei_open - the open function | 47 | * mei_open - the open function |
96 | * | 48 | * |
@@ -101,15 +53,20 @@ static DEFINE_MUTEX(mei_mutex); | |||
101 | */ | 53 | */ |
102 | static int mei_open(struct inode *inode, struct file *file) | 54 | static int mei_open(struct inode *inode, struct file *file) |
103 | { | 55 | { |
56 | struct miscdevice *misc = file->private_data; | ||
57 | struct pci_dev *pdev; | ||
104 | struct mei_cl *cl; | 58 | struct mei_cl *cl; |
105 | struct mei_device *dev; | 59 | struct mei_device *dev; |
60 | |||
106 | int err; | 61 | int err; |
107 | 62 | ||
108 | err = -ENODEV; | 63 | err = -ENODEV; |
109 | if (!mei_pdev) | 64 | if (!misc->parent) |
110 | goto out; | 65 | goto out; |
111 | 66 | ||
112 | dev = pci_get_drvdata(mei_pdev); | 67 | pdev = container_of(misc->parent, struct pci_dev, dev); |
68 | |||
69 | dev = pci_get_drvdata(pdev); | ||
113 | if (!dev) | 70 | if (!dev) |
114 | goto out; | 71 | goto out; |
115 | 72 | ||
@@ -787,7 +744,6 @@ static const struct file_operations mei_fops = { | |||
787 | .llseek = no_llseek | 744 | .llseek = no_llseek |
788 | }; | 745 | }; |
789 | 746 | ||
790 | |||
791 | /* | 747 | /* |
792 | * Misc Device Struct | 748 | * Misc Device Struct |
793 | */ | 749 | */ |
@@ -797,302 +753,16 @@ static struct miscdevice mei_misc_device = { | |||
797 | .minor = MISC_DYNAMIC_MINOR, | 753 | .minor = MISC_DYNAMIC_MINOR, |
798 | }; | 754 | }; |
799 | 755 | ||
800 | /** | 756 | int mei_register(struct device *dev) |
801 | * mei_quirk_probe - probe for devices that doesn't valid ME interface | ||
802 | * @pdev: PCI device structure | ||
803 | * @ent: entry into pci_device_table | ||
804 | * | ||
805 | * returns true if ME Interface is valid, false otherwise | ||
806 | */ | ||
807 | static bool mei_quirk_probe(struct pci_dev *pdev, | ||
808 | const struct pci_device_id *ent) | ||
809 | { | 757 | { |
810 | u32 reg; | 758 | mei_misc_device.parent = dev; |
811 | if (ent->device == MEI_DEV_ID_PBG_1) { | 759 | return misc_register(&mei_misc_device); |
812 | pci_read_config_dword(pdev, 0x48, ®); | ||
813 | /* make sure that bit 9 is up and bit 10 is down */ | ||
814 | if ((reg & 0x600) == 0x200) { | ||
815 | dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n"); | ||
816 | return false; | ||
817 | } | ||
818 | } | ||
819 | return true; | ||
820 | } | ||
821 | /** | ||
822 | * mei_probe - Device Initialization Routine | ||
823 | * | ||
824 | * @pdev: PCI device structure | ||
825 | * @ent: entry in kcs_pci_tbl | ||
826 | * | ||
827 | * returns 0 on success, <0 on failure. | ||
828 | */ | ||
829 | static int mei_probe(struct pci_dev *pdev, | ||
830 | const struct pci_device_id *ent) | ||
831 | { | ||
832 | struct mei_device *dev; | ||
833 | int err; | ||
834 | |||
835 | mutex_lock(&mei_mutex); | ||
836 | |||
837 | if (!mei_quirk_probe(pdev, ent)) { | ||
838 | err = -ENODEV; | ||
839 | goto end; | ||
840 | } | ||
841 | |||
842 | if (mei_pdev) { | ||
843 | err = -EEXIST; | ||
844 | goto end; | ||
845 | } | ||
846 | /* enable pci dev */ | ||
847 | err = pci_enable_device(pdev); | ||
848 | if (err) { | ||
849 | dev_err(&pdev->dev, "failed to enable pci device.\n"); | ||
850 | goto end; | ||
851 | } | ||
852 | /* set PCI host mastering */ | ||
853 | pci_set_master(pdev); | ||
854 | /* pci request regions for mei driver */ | ||
855 | err = pci_request_regions(pdev, KBUILD_MODNAME); | ||
856 | if (err) { | ||
857 | dev_err(&pdev->dev, "failed to get pci regions.\n"); | ||
858 | goto disable_device; | ||
859 | } | ||
860 | /* allocates and initializes the mei dev structure */ | ||
861 | dev = mei_device_init(pdev); | ||
862 | if (!dev) { | ||
863 | err = -ENOMEM; | ||
864 | goto release_regions; | ||
865 | } | ||
866 | /* mapping IO device memory */ | ||
867 | dev->mem_addr = pci_iomap(pdev, 0, 0); | ||
868 | if (!dev->mem_addr) { | ||
869 | dev_err(&pdev->dev, "mapping I/O device memory failure.\n"); | ||
870 | err = -ENOMEM; | ||
871 | goto free_device; | ||
872 | } | ||
873 | pci_enable_msi(pdev); | ||
874 | |||
875 | /* request and enable interrupt */ | ||
876 | if (pci_dev_msi_enabled(pdev)) | ||
877 | err = request_threaded_irq(pdev->irq, | ||
878 | NULL, | ||
879 | mei_interrupt_thread_handler, | ||
880 | IRQF_ONESHOT, KBUILD_MODNAME, dev); | ||
881 | else | ||
882 | err = request_threaded_irq(pdev->irq, | ||
883 | mei_interrupt_quick_handler, | ||
884 | mei_interrupt_thread_handler, | ||
885 | IRQF_SHARED, KBUILD_MODNAME, dev); | ||
886 | |||
887 | if (err) { | ||
888 | dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n", | ||
889 | pdev->irq); | ||
890 | goto disable_msi; | ||
891 | } | ||
892 | |||
893 | if (mei_hw_init(dev)) { | ||
894 | dev_err(&pdev->dev, "init hw failure.\n"); | ||
895 | err = -ENODEV; | ||
896 | goto release_irq; | ||
897 | } | ||
898 | |||
899 | err = misc_register(&mei_misc_device); | ||
900 | if (err) | ||
901 | goto release_irq; | ||
902 | |||
903 | mei_pdev = pdev; | ||
904 | pci_set_drvdata(pdev, dev); | ||
905 | |||
906 | |||
907 | schedule_delayed_work(&dev->timer_work, HZ); | ||
908 | |||
909 | mutex_unlock(&mei_mutex); | ||
910 | |||
911 | pr_debug("initialization successful.\n"); | ||
912 | |||
913 | return 0; | ||
914 | |||
915 | release_irq: | ||
916 | mei_disable_interrupts(dev); | ||
917 | flush_scheduled_work(); | ||
918 | free_irq(pdev->irq, dev); | ||
919 | disable_msi: | ||
920 | pci_disable_msi(pdev); | ||
921 | pci_iounmap(pdev, dev->mem_addr); | ||
922 | free_device: | ||
923 | kfree(dev); | ||
924 | release_regions: | ||
925 | pci_release_regions(pdev); | ||
926 | disable_device: | ||
927 | pci_disable_device(pdev); | ||
928 | end: | ||
929 | mutex_unlock(&mei_mutex); | ||
930 | dev_err(&pdev->dev, "initialization failed.\n"); | ||
931 | return err; | ||
932 | } | 760 | } |
933 | 761 | ||
934 | /** | 762 | void mei_deregister(void) |
935 | * mei_remove - Device Removal Routine | ||
936 | * | ||
937 | * @pdev: PCI device structure | ||
938 | * | ||
939 | * mei_remove is called by the PCI subsystem to alert the driver | ||
940 | * that it should release a PCI device. | ||
941 | */ | ||
942 | static void mei_remove(struct pci_dev *pdev) | ||
943 | { | 763 | { |
944 | struct mei_device *dev; | ||
945 | |||
946 | if (mei_pdev != pdev) | ||
947 | return; | ||
948 | |||
949 | dev = pci_get_drvdata(pdev); | ||
950 | if (!dev) | ||
951 | return; | ||
952 | |||
953 | mutex_lock(&dev->device_lock); | ||
954 | |||
955 | cancel_delayed_work(&dev->timer_work); | ||
956 | |||
957 | mei_wd_stop(dev); | ||
958 | |||
959 | mei_pdev = NULL; | ||
960 | |||
961 | if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) { | ||
962 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTING; | ||
963 | mei_cl_disconnect(&dev->iamthif_cl); | ||
964 | } | ||
965 | if (dev->wd_cl.state == MEI_FILE_CONNECTED) { | ||
966 | dev->wd_cl.state = MEI_FILE_DISCONNECTING; | ||
967 | mei_cl_disconnect(&dev->wd_cl); | ||
968 | } | ||
969 | |||
970 | /* Unregistering watchdog device */ | ||
971 | mei_watchdog_unregister(dev); | ||
972 | |||
973 | /* remove entry if already in list */ | ||
974 | dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n"); | ||
975 | |||
976 | if (dev->open_handle_count > 0) | ||
977 | dev->open_handle_count--; | ||
978 | mei_cl_unlink(&dev->wd_cl); | ||
979 | |||
980 | if (dev->open_handle_count > 0) | ||
981 | dev->open_handle_count--; | ||
982 | mei_cl_unlink(&dev->iamthif_cl); | ||
983 | |||
984 | dev->iamthif_current_cb = NULL; | ||
985 | dev->me_clients_num = 0; | ||
986 | |||
987 | mutex_unlock(&dev->device_lock); | ||
988 | |||
989 | flush_scheduled_work(); | ||
990 | |||
991 | /* disable interrupts */ | ||
992 | mei_disable_interrupts(dev); | ||
993 | |||
994 | free_irq(pdev->irq, dev); | ||
995 | pci_disable_msi(pdev); | ||
996 | pci_set_drvdata(pdev, NULL); | ||
997 | |||
998 | if (dev->mem_addr) | ||
999 | pci_iounmap(pdev, dev->mem_addr); | ||
1000 | |||
1001 | kfree(dev); | ||
1002 | |||
1003 | pci_release_regions(pdev); | ||
1004 | pci_disable_device(pdev); | ||
1005 | |||
1006 | misc_deregister(&mei_misc_device); | 764 | misc_deregister(&mei_misc_device); |
765 | mei_misc_device.parent = NULL; | ||
1007 | } | 766 | } |
1008 | #ifdef CONFIG_PM | ||
1009 | static int mei_pci_suspend(struct device *device) | ||
1010 | { | ||
1011 | struct pci_dev *pdev = to_pci_dev(device); | ||
1012 | struct mei_device *dev = pci_get_drvdata(pdev); | ||
1013 | int err; | ||
1014 | |||
1015 | if (!dev) | ||
1016 | return -ENODEV; | ||
1017 | mutex_lock(&dev->device_lock); | ||
1018 | |||
1019 | cancel_delayed_work(&dev->timer_work); | ||
1020 | |||
1021 | /* Stop watchdog if exists */ | ||
1022 | err = mei_wd_stop(dev); | ||
1023 | /* Set new mei state */ | ||
1024 | if (dev->dev_state == MEI_DEV_ENABLED || | ||
1025 | dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) { | ||
1026 | dev->dev_state = MEI_DEV_POWER_DOWN; | ||
1027 | mei_reset(dev, 0); | ||
1028 | } | ||
1029 | mutex_unlock(&dev->device_lock); | ||
1030 | |||
1031 | free_irq(pdev->irq, dev); | ||
1032 | pci_disable_msi(pdev); | ||
1033 | |||
1034 | return err; | ||
1035 | } | ||
1036 | |||
1037 | static int mei_pci_resume(struct device *device) | ||
1038 | { | ||
1039 | struct pci_dev *pdev = to_pci_dev(device); | ||
1040 | struct mei_device *dev; | ||
1041 | int err; | ||
1042 | |||
1043 | dev = pci_get_drvdata(pdev); | ||
1044 | if (!dev) | ||
1045 | return -ENODEV; | ||
1046 | |||
1047 | pci_enable_msi(pdev); | ||
1048 | |||
1049 | /* request and enable interrupt */ | ||
1050 | if (pci_dev_msi_enabled(pdev)) | ||
1051 | err = request_threaded_irq(pdev->irq, | ||
1052 | NULL, | ||
1053 | mei_interrupt_thread_handler, | ||
1054 | IRQF_ONESHOT, KBUILD_MODNAME, dev); | ||
1055 | else | ||
1056 | err = request_threaded_irq(pdev->irq, | ||
1057 | mei_interrupt_quick_handler, | ||
1058 | mei_interrupt_thread_handler, | ||
1059 | IRQF_SHARED, KBUILD_MODNAME, dev); | ||
1060 | |||
1061 | if (err) { | ||
1062 | dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n", | ||
1063 | pdev->irq); | ||
1064 | return err; | ||
1065 | } | ||
1066 | |||
1067 | mutex_lock(&dev->device_lock); | ||
1068 | dev->dev_state = MEI_DEV_POWER_UP; | ||
1069 | mei_reset(dev, 1); | ||
1070 | mutex_unlock(&dev->device_lock); | ||
1071 | |||
1072 | /* Start timer if stopped in suspend */ | ||
1073 | schedule_delayed_work(&dev->timer_work, HZ); | ||
1074 | |||
1075 | return err; | ||
1076 | } | ||
1077 | static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume); | ||
1078 | #define MEI_PM_OPS (&mei_pm_ops) | ||
1079 | #else | ||
1080 | #define MEI_PM_OPS NULL | ||
1081 | #endif /* CONFIG_PM */ | ||
1082 | /* | ||
1083 | * PCI driver structure | ||
1084 | */ | ||
1085 | static struct pci_driver mei_driver = { | ||
1086 | .name = KBUILD_MODNAME, | ||
1087 | .id_table = mei_pci_tbl, | ||
1088 | .probe = mei_probe, | ||
1089 | .remove = mei_remove, | ||
1090 | .shutdown = mei_remove, | ||
1091 | .driver.pm = MEI_PM_OPS, | ||
1092 | }; | ||
1093 | 767 | ||
1094 | module_pci_driver(mei_driver); | ||
1095 | 768 | ||
1096 | MODULE_AUTHOR("Intel Corporation"); | ||
1097 | MODULE_DESCRIPTION("Intel(R) Management Engine Interface"); | ||
1098 | MODULE_LICENSE("GPL v2"); | ||