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) */ |
