diff options
-rw-r--r-- | arch/sparc64/kernel/pci.c | 16 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 224 | ||||
-rw-r--r-- | include/asm-sparc64/pbm.h | 10 |
3 files changed, 119 insertions, 131 deletions
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index b583deb05062..4d30d57c4619 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
@@ -1092,17 +1092,12 @@ EXPORT_SYMBOL(pci_domain_nr); | |||
1092 | int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) | 1092 | int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) |
1093 | { | 1093 | { |
1094 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; | 1094 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
1095 | struct pci_controller_info *p = pbm->parent; | 1095 | int virt_irq; |
1096 | int virt_irq, err; | ||
1097 | 1096 | ||
1098 | if (!pbm->msi_num || !p->setup_msi_irq) | 1097 | if (!pbm->setup_msi_irq) |
1099 | return -EINVAL; | 1098 | return -EINVAL; |
1100 | 1099 | ||
1101 | err = p->setup_msi_irq(&virt_irq, pdev, desc); | 1100 | return pbm->setup_msi_irq(&virt_irq, pdev, desc); |
1102 | if (err) | ||
1103 | return err; | ||
1104 | |||
1105 | return 0; | ||
1106 | } | 1101 | } |
1107 | 1102 | ||
1108 | void arch_teardown_msi_irq(unsigned int virt_irq) | 1103 | void arch_teardown_msi_irq(unsigned int virt_irq) |
@@ -1110,12 +1105,11 @@ void arch_teardown_msi_irq(unsigned int virt_irq) | |||
1110 | struct msi_desc *entry = get_irq_msi(virt_irq); | 1105 | struct msi_desc *entry = get_irq_msi(virt_irq); |
1111 | struct pci_dev *pdev = entry->dev; | 1106 | struct pci_dev *pdev = entry->dev; |
1112 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; | 1107 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
1113 | struct pci_controller_info *p = pbm->parent; | ||
1114 | 1108 | ||
1115 | if (!pbm->msi_num || !p->setup_msi_irq) | 1109 | if (!pbm->teardown_msi_irq) |
1116 | return; | 1110 | return; |
1117 | 1111 | ||
1118 | return p->teardown_msi_irq(virt_irq, pdev); | 1112 | return pbm->teardown_msi_irq(virt_irq, pdev); |
1119 | } | 1113 | } |
1120 | #endif /* !(CONFIG_PCI_MSI) */ | 1114 | #endif /* !(CONFIG_PCI_MSI) */ |
1121 | 1115 | ||
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index ea61fec206a7..7ebc04f9a880 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -991,114 +991,6 @@ h_error: | |||
991 | return -EINVAL; | 991 | return -EINVAL; |
992 | } | 992 | } |
993 | 993 | ||
994 | static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | ||
995 | { | ||
996 | const u32 *val; | ||
997 | int len; | ||
998 | |||
999 | val = of_get_property(pbm->prom_node, "#msi-eqs", &len); | ||
1000 | if (!val || len != 4) | ||
1001 | goto no_msi; | ||
1002 | pbm->msiq_num = *val; | ||
1003 | if (pbm->msiq_num) { | ||
1004 | const struct msiq_prop { | ||
1005 | u32 first_msiq; | ||
1006 | u32 num_msiq; | ||
1007 | u32 first_devino; | ||
1008 | } *mqp; | ||
1009 | const struct msi_range_prop { | ||
1010 | u32 first_msi; | ||
1011 | u32 num_msi; | ||
1012 | } *mrng; | ||
1013 | const struct addr_range_prop { | ||
1014 | u32 msi32_high; | ||
1015 | u32 msi32_low; | ||
1016 | u32 msi32_len; | ||
1017 | u32 msi64_high; | ||
1018 | u32 msi64_low; | ||
1019 | u32 msi64_len; | ||
1020 | } *arng; | ||
1021 | |||
1022 | val = of_get_property(pbm->prom_node, "msi-eq-size", &len); | ||
1023 | if (!val || len != 4) | ||
1024 | goto no_msi; | ||
1025 | |||
1026 | pbm->msiq_ent_count = *val; | ||
1027 | |||
1028 | mqp = of_get_property(pbm->prom_node, | ||
1029 | "msi-eq-to-devino", &len); | ||
1030 | if (!mqp || len != sizeof(struct msiq_prop)) | ||
1031 | goto no_msi; | ||
1032 | |||
1033 | pbm->msiq_first = mqp->first_msiq; | ||
1034 | pbm->msiq_first_devino = mqp->first_devino; | ||
1035 | |||
1036 | val = of_get_property(pbm->prom_node, "#msi", &len); | ||
1037 | if (!val || len != 4) | ||
1038 | goto no_msi; | ||
1039 | pbm->msi_num = *val; | ||
1040 | |||
1041 | mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); | ||
1042 | if (!mrng || len != sizeof(struct msi_range_prop)) | ||
1043 | goto no_msi; | ||
1044 | pbm->msi_first = mrng->first_msi; | ||
1045 | |||
1046 | val = of_get_property(pbm->prom_node, "msi-data-mask", &len); | ||
1047 | if (!val || len != 4) | ||
1048 | goto no_msi; | ||
1049 | pbm->msi_data_mask = *val; | ||
1050 | |||
1051 | val = of_get_property(pbm->prom_node, "msix-data-width", &len); | ||
1052 | if (!val || len != 4) | ||
1053 | goto no_msi; | ||
1054 | pbm->msix_data_width = *val; | ||
1055 | |||
1056 | arng = of_get_property(pbm->prom_node, "msi-address-ranges", | ||
1057 | &len); | ||
1058 | if (!arng || len != sizeof(struct addr_range_prop)) | ||
1059 | goto no_msi; | ||
1060 | pbm->msi32_start = ((u64)arng->msi32_high << 32) | | ||
1061 | (u64) arng->msi32_low; | ||
1062 | pbm->msi64_start = ((u64)arng->msi64_high << 32) | | ||
1063 | (u64) arng->msi64_low; | ||
1064 | pbm->msi32_len = arng->msi32_len; | ||
1065 | pbm->msi64_len = arng->msi64_len; | ||
1066 | |||
1067 | if (msi_bitmap_alloc(pbm)) | ||
1068 | goto no_msi; | ||
1069 | |||
1070 | if (msi_queue_alloc(pbm)) { | ||
1071 | msi_bitmap_free(pbm); | ||
1072 | goto no_msi; | ||
1073 | } | ||
1074 | |||
1075 | printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] " | ||
1076 | "devino[0x%x]\n", | ||
1077 | pbm->name, | ||
1078 | pbm->msiq_first, pbm->msiq_num, | ||
1079 | pbm->msiq_ent_count, | ||
1080 | pbm->msiq_first_devino); | ||
1081 | printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] " | ||
1082 | "width[%u]\n", | ||
1083 | pbm->name, | ||
1084 | pbm->msi_first, pbm->msi_num, pbm->msi_data_mask, | ||
1085 | pbm->msix_data_width); | ||
1086 | printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] " | ||
1087 | "addr64[0x%lx:0x%x]\n", | ||
1088 | pbm->name, | ||
1089 | pbm->msi32_start, pbm->msi32_len, | ||
1090 | pbm->msi64_start, pbm->msi64_len); | ||
1091 | printk(KERN_INFO "%s: MSI queues at RA [%p]\n", | ||
1092 | pbm->name, | ||
1093 | pbm->msi_queues); | ||
1094 | } | ||
1095 | |||
1096 | return; | ||
1097 | |||
1098 | no_msi: | ||
1099 | pbm->msiq_num = 0; | ||
1100 | printk(KERN_INFO "%s: No MSI support.\n", pbm->name); | ||
1101 | } | ||
1102 | 994 | ||
1103 | static int alloc_msi(struct pci_pbm_info *pbm) | 995 | static int alloc_msi(struct pci_pbm_info *pbm) |
1104 | { | 996 | { |
@@ -1217,6 +1109,117 @@ static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq, | |||
1217 | */ | 1109 | */ |
1218 | sun4v_destroy_msi(virt_irq); | 1110 | sun4v_destroy_msi(virt_irq); |
1219 | } | 1111 | } |
1112 | |||
1113 | static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | ||
1114 | { | ||
1115 | const u32 *val; | ||
1116 | int len; | ||
1117 | |||
1118 | val = of_get_property(pbm->prom_node, "#msi-eqs", &len); | ||
1119 | if (!val || len != 4) | ||
1120 | goto no_msi; | ||
1121 | pbm->msiq_num = *val; | ||
1122 | if (pbm->msiq_num) { | ||
1123 | const struct msiq_prop { | ||
1124 | u32 first_msiq; | ||
1125 | u32 num_msiq; | ||
1126 | u32 first_devino; | ||
1127 | } *mqp; | ||
1128 | const struct msi_range_prop { | ||
1129 | u32 first_msi; | ||
1130 | u32 num_msi; | ||
1131 | } *mrng; | ||
1132 | const struct addr_range_prop { | ||
1133 | u32 msi32_high; | ||
1134 | u32 msi32_low; | ||
1135 | u32 msi32_len; | ||
1136 | u32 msi64_high; | ||
1137 | u32 msi64_low; | ||
1138 | u32 msi64_len; | ||
1139 | } *arng; | ||
1140 | |||
1141 | val = of_get_property(pbm->prom_node, "msi-eq-size", &len); | ||
1142 | if (!val || len != 4) | ||
1143 | goto no_msi; | ||
1144 | |||
1145 | pbm->msiq_ent_count = *val; | ||
1146 | |||
1147 | mqp = of_get_property(pbm->prom_node, | ||
1148 | "msi-eq-to-devino", &len); | ||
1149 | if (!mqp || len != sizeof(struct msiq_prop)) | ||
1150 | goto no_msi; | ||
1151 | |||
1152 | pbm->msiq_first = mqp->first_msiq; | ||
1153 | pbm->msiq_first_devino = mqp->first_devino; | ||
1154 | |||
1155 | val = of_get_property(pbm->prom_node, "#msi", &len); | ||
1156 | if (!val || len != 4) | ||
1157 | goto no_msi; | ||
1158 | pbm->msi_num = *val; | ||
1159 | |||
1160 | mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); | ||
1161 | if (!mrng || len != sizeof(struct msi_range_prop)) | ||
1162 | goto no_msi; | ||
1163 | pbm->msi_first = mrng->first_msi; | ||
1164 | |||
1165 | val = of_get_property(pbm->prom_node, "msi-data-mask", &len); | ||
1166 | if (!val || len != 4) | ||
1167 | goto no_msi; | ||
1168 | pbm->msi_data_mask = *val; | ||
1169 | |||
1170 | val = of_get_property(pbm->prom_node, "msix-data-width", &len); | ||
1171 | if (!val || len != 4) | ||
1172 | goto no_msi; | ||
1173 | pbm->msix_data_width = *val; | ||
1174 | |||
1175 | arng = of_get_property(pbm->prom_node, "msi-address-ranges", | ||
1176 | &len); | ||
1177 | if (!arng || len != sizeof(struct addr_range_prop)) | ||
1178 | goto no_msi; | ||
1179 | pbm->msi32_start = ((u64)arng->msi32_high << 32) | | ||
1180 | (u64) arng->msi32_low; | ||
1181 | pbm->msi64_start = ((u64)arng->msi64_high << 32) | | ||
1182 | (u64) arng->msi64_low; | ||
1183 | pbm->msi32_len = arng->msi32_len; | ||
1184 | pbm->msi64_len = arng->msi64_len; | ||
1185 | |||
1186 | if (msi_bitmap_alloc(pbm)) | ||
1187 | goto no_msi; | ||
1188 | |||
1189 | if (msi_queue_alloc(pbm)) { | ||
1190 | msi_bitmap_free(pbm); | ||
1191 | goto no_msi; | ||
1192 | } | ||
1193 | |||
1194 | printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] " | ||
1195 | "devino[0x%x]\n", | ||
1196 | pbm->name, | ||
1197 | pbm->msiq_first, pbm->msiq_num, | ||
1198 | pbm->msiq_ent_count, | ||
1199 | pbm->msiq_first_devino); | ||
1200 | printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] " | ||
1201 | "width[%u]\n", | ||
1202 | pbm->name, | ||
1203 | pbm->msi_first, pbm->msi_num, pbm->msi_data_mask, | ||
1204 | pbm->msix_data_width); | ||
1205 | printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] " | ||
1206 | "addr64[0x%lx:0x%x]\n", | ||
1207 | pbm->name, | ||
1208 | pbm->msi32_start, pbm->msi32_len, | ||
1209 | pbm->msi64_start, pbm->msi64_len); | ||
1210 | printk(KERN_INFO "%s: MSI queues at RA [%p]\n", | ||
1211 | pbm->name, | ||
1212 | pbm->msi_queues); | ||
1213 | } | ||
1214 | pbm->setup_msi_irq = pci_sun4v_setup_msi_irq; | ||
1215 | pbm->teardown_msi_irq = pci_sun4v_teardown_msi_irq; | ||
1216 | |||
1217 | return; | ||
1218 | |||
1219 | no_msi: | ||
1220 | pbm->msiq_num = 0; | ||
1221 | printk(KERN_INFO "%s: No MSI support.\n", pbm->name); | ||
1222 | } | ||
1220 | #else /* CONFIG_PCI_MSI */ | 1223 | #else /* CONFIG_PCI_MSI */ |
1221 | static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | 1224 | static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) |
1222 | { | 1225 | { |
@@ -1303,11 +1306,6 @@ void sun4v_pci_init(struct device_node *dp, char *model_name) | |||
1303 | 1306 | ||
1304 | p->index = pci_num_controllers++; | 1307 | p->index = pci_num_controllers++; |
1305 | 1308 | ||
1306 | #ifdef CONFIG_PCI_MSI | ||
1307 | p->setup_msi_irq = pci_sun4v_setup_msi_irq; | ||
1308 | p->teardown_msi_irq = pci_sun4v_teardown_msi_irq; | ||
1309 | #endif | ||
1310 | |||
1311 | /* Like PSYCHO and SCHIZO we have a 2GB aligned area | 1309 | /* Like PSYCHO and SCHIZO we have a 2GB aligned area |
1312 | * for memory space. | 1310 | * for memory space. |
1313 | */ | 1311 | */ |
diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h index 1f4de53dcd03..1d5dcfe133a2 100644 --- a/include/asm-sparc64/pbm.h +++ b/include/asm-sparc64/pbm.h | |||
@@ -103,6 +103,9 @@ struct pci_pbm_info { | |||
103 | u32 msi64_len; | 103 | u32 msi64_len; |
104 | void *msi_queues; | 104 | void *msi_queues; |
105 | unsigned long *msi_bitmap; | 105 | unsigned long *msi_bitmap; |
106 | int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, | ||
107 | struct msi_desc *entry); | ||
108 | void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev); | ||
106 | #endif /* !(CONFIG_PCI_MSI) */ | 109 | #endif /* !(CONFIG_PCI_MSI) */ |
107 | 110 | ||
108 | /* This PBM's streaming buffer. */ | 111 | /* This PBM's streaming buffer. */ |
@@ -128,13 +131,6 @@ struct pci_controller_info { | |||
128 | /* The PCI bus modules controlled by us. */ | 131 | /* The PCI bus modules controlled by us. */ |
129 | struct pci_pbm_info pbm_A; | 132 | struct pci_pbm_info pbm_A; |
130 | struct pci_pbm_info pbm_B; | 133 | struct pci_pbm_info pbm_B; |
131 | |||
132 | /* Operations which are controller specific. */ | ||
133 | #ifdef CONFIG_PCI_MSI | ||
134 | int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, | ||
135 | struct msi_desc *entry); | ||
136 | void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev); | ||
137 | #endif | ||
138 | }; | 134 | }; |
139 | 135 | ||
140 | #endif /* !(__SPARC64_PBM_H) */ | 136 | #endif /* !(__SPARC64_PBM_H) */ |