diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 21:55:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 21:55:10 -0400 |
commit | 5375871d432ae9fc581014ac117b96aaee3cd0c7 (patch) | |
tree | be98e8255b0f927fb920fb532a598b93fa140dbe /arch/powerpc/sysdev/mpic.c | |
parent | b57cb7231b2ce52d3dda14a7b417ae125fb2eb97 (diff) | |
parent | dfbc2d75c1bd47c3186fa91f1655ea2f3825b0ec (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc merge from Benjamin Herrenschmidt:
"Here's the powerpc batch for this merge window. It is going to be a
bit more nasty than usual as in touching things outside of
arch/powerpc mostly due to the big iSeriesectomy :-) We finally got
rid of the bugger (legacy iSeries support) which was a PITA to
maintain and that nobody really used anymore.
Here are some of the highlights:
- Legacy iSeries is gone. Thanks Stephen ! There's still some bits
and pieces remaining if you do a grep -ir series arch/powerpc but
they are harmless and will be removed in the next few weeks
hopefully.
- The 'fadump' functionality (Firmware Assisted Dump) replaces the
previous (equivalent) "pHyp assisted dump"... it's a rewrite of a
mechanism to get the hypervisor to do crash dumps on pSeries, the
new implementation hopefully being much more reliable. Thanks
Mahesh Salgaonkar.
- The "EEH" code (pSeries PCI error handling & recovery) got a big
spring cleaning, motivated by the need to be able to implement a
new backend for it on top of some new different type of firwmare.
The work isn't complete yet, but a good chunk of the cleanups is
there. Note that this adds a field to struct device_node which is
not very nice and which Grant objects to. I will have a patch soon
that moves that to a powerpc private data structure (hopefully
before rc1) and we'll improve things further later on (hopefully
getting rid of the need for that pointer completely). Thanks Gavin
Shan.
- I dug into our exception & interrupt handling code to improve the
way we do lazy interrupt handling (and make it work properly with
"edge" triggered interrupt sources), and while at it found & fixed
a wagon of issues in those areas, including adding support for page
fault retry & fatal signals on page faults.
- Your usual random batch of small fixes & updates, including a bunch
of new embedded boards, both Freescale and APM based ones, etc..."
I fixed up some conflicts with the generalized irq-domain changes from
Grant Likely, hopefully correctly.
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (141 commits)
powerpc/ps3: Do not adjust the wrapper load address
powerpc: Remove the rest of the legacy iSeries include files
powerpc: Remove the remaining CONFIG_PPC_ISERIES pieces
init: Remove CONFIG_PPC_ISERIES
powerpc: Remove FW_FEATURE ISERIES from arch code
tty/hvc_vio: FW_FEATURE_ISERIES is no longer selectable
powerpc/spufs: Fix double unlocks
powerpc/5200: convert mpc5200 to use of_platform_populate()
powerpc/mpc5200: add options to mpc5200_defconfig
powerpc/mpc52xx: add a4m072 board support
powerpc/mpc5200: update mpc5200_defconfig to fit for charon board
Documentation/powerpc/mpc52xx.txt: Checkpatch cleanup
powerpc/44x: Add additional device support for APM821xx SoC and Bluestone board
powerpc/44x: Add support PCI-E for APM821xx SoC and Bluestone board
MAINTAINERS: Update PowerPC 4xx tree
powerpc/44x: The bug fixed support for APM821xx SoC and Bluestone board
powerpc: document the FSL MPIC message register binding
powerpc: add support for MPIC message register API
powerpc/fsl: Added aliased MSIIR register address to MSI node in dts
powerpc/85xx: mpc8548cds - add 36-bit dts
...
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 104 |
1 files changed, 55 insertions, 49 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index c83a512fa175..9ac71ebd2c40 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -873,7 +873,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type) | |||
873 | DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n", | 873 | DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n", |
874 | mpic, d->irq, src, flow_type); | 874 | mpic, d->irq, src, flow_type); |
875 | 875 | ||
876 | if (src >= mpic->irq_count) | 876 | if (src >= mpic->num_sources) |
877 | return -EINVAL; | 877 | return -EINVAL; |
878 | 878 | ||
879 | if (flow_type == IRQ_TYPE_NONE) | 879 | if (flow_type == IRQ_TYPE_NONE) |
@@ -909,7 +909,7 @@ void mpic_set_vector(unsigned int virq, unsigned int vector) | |||
909 | DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n", | 909 | DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n", |
910 | mpic, virq, src, vector); | 910 | mpic, virq, src, vector); |
911 | 911 | ||
912 | if (src >= mpic->irq_count) | 912 | if (src >= mpic->num_sources) |
913 | return; | 913 | return; |
914 | 914 | ||
915 | vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); | 915 | vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); |
@@ -926,7 +926,7 @@ void mpic_set_destination(unsigned int virq, unsigned int cpuid) | |||
926 | DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n", | 926 | DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n", |
927 | mpic, virq, src, cpuid); | 927 | mpic, virq, src, cpuid); |
928 | 928 | ||
929 | if (src >= mpic->irq_count) | 929 | if (src >= mpic->num_sources) |
930 | return; | 930 | return; |
931 | 931 | ||
932 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); | 932 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); |
@@ -1006,7 +1006,7 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq, | |||
1006 | return 0; | 1006 | return 0; |
1007 | } | 1007 | } |
1008 | 1008 | ||
1009 | if (hw >= mpic->irq_count) | 1009 | if (hw >= mpic->num_sources) |
1010 | return -EINVAL; | 1010 | return -EINVAL; |
1011 | 1011 | ||
1012 | mpic_msi_reserve_hwirq(mpic, hw); | 1012 | mpic_msi_reserve_hwirq(mpic, hw); |
@@ -1149,6 +1149,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1149 | u32 greg_feature; | 1149 | u32 greg_feature; |
1150 | const char *vers; | 1150 | const char *vers; |
1151 | const u32 *psrc; | 1151 | const u32 *psrc; |
1152 | u32 last_irq; | ||
1152 | 1153 | ||
1153 | /* Default MPIC search parameters */ | 1154 | /* Default MPIC search parameters */ |
1154 | static const struct of_device_id __initconst mpic_device_id[] = { | 1155 | static const struct of_device_id __initconst mpic_device_id[] = { |
@@ -1182,6 +1183,16 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1182 | } | 1183 | } |
1183 | } | 1184 | } |
1184 | 1185 | ||
1186 | /* Read extra device-tree properties into the flags variable */ | ||
1187 | if (of_get_property(node, "big-endian", NULL)) | ||
1188 | flags |= MPIC_BIG_ENDIAN; | ||
1189 | if (of_get_property(node, "pic-no-reset", NULL)) | ||
1190 | flags |= MPIC_NO_RESET; | ||
1191 | if (of_get_property(node, "single-cpu-affinity", NULL)) | ||
1192 | flags |= MPIC_SINGLE_DEST_CPU; | ||
1193 | if (of_device_is_compatible(node, "fsl,mpic")) | ||
1194 | flags |= MPIC_FSL; | ||
1195 | |||
1185 | mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL); | 1196 | mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL); |
1186 | if (mpic == NULL) | 1197 | if (mpic == NULL) |
1187 | goto err_of_node_put; | 1198 | goto err_of_node_put; |
@@ -1189,15 +1200,16 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1189 | mpic->name = name; | 1200 | mpic->name = name; |
1190 | mpic->node = node; | 1201 | mpic->node = node; |
1191 | mpic->paddr = phys_addr; | 1202 | mpic->paddr = phys_addr; |
1203 | mpic->flags = flags; | ||
1192 | 1204 | ||
1193 | mpic->hc_irq = mpic_irq_chip; | 1205 | mpic->hc_irq = mpic_irq_chip; |
1194 | mpic->hc_irq.name = name; | 1206 | mpic->hc_irq.name = name; |
1195 | if (!(flags & MPIC_SECONDARY)) | 1207 | if (!(mpic->flags & MPIC_SECONDARY)) |
1196 | mpic->hc_irq.irq_set_affinity = mpic_set_affinity; | 1208 | mpic->hc_irq.irq_set_affinity = mpic_set_affinity; |
1197 | #ifdef CONFIG_MPIC_U3_HT_IRQS | 1209 | #ifdef CONFIG_MPIC_U3_HT_IRQS |
1198 | mpic->hc_ht_irq = mpic_irq_ht_chip; | 1210 | mpic->hc_ht_irq = mpic_irq_ht_chip; |
1199 | mpic->hc_ht_irq.name = name; | 1211 | mpic->hc_ht_irq.name = name; |
1200 | if (!(flags & MPIC_SECONDARY)) | 1212 | if (!(mpic->flags & MPIC_SECONDARY)) |
1201 | mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity; | 1213 | mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity; |
1202 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ | 1214 | #endif /* CONFIG_MPIC_U3_HT_IRQS */ |
1203 | 1215 | ||
@@ -1209,12 +1221,9 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1209 | mpic->hc_tm = mpic_tm_chip; | 1221 | mpic->hc_tm = mpic_tm_chip; |
1210 | mpic->hc_tm.name = name; | 1222 | mpic->hc_tm.name = name; |
1211 | 1223 | ||
1212 | mpic->flags = flags; | ||
1213 | mpic->isu_size = isu_size; | ||
1214 | mpic->irq_count = irq_count; | ||
1215 | mpic->num_sources = 0; /* so far */ | 1224 | mpic->num_sources = 0; /* so far */ |
1216 | 1225 | ||
1217 | if (flags & MPIC_LARGE_VECTORS) | 1226 | if (mpic->flags & MPIC_LARGE_VECTORS) |
1218 | intvec_top = 2047; | 1227 | intvec_top = 2047; |
1219 | else | 1228 | else |
1220 | intvec_top = 255; | 1229 | intvec_top = 255; |
@@ -1233,12 +1242,6 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1233 | mpic->ipi_vecs[3] = intvec_top - 1; | 1242 | mpic->ipi_vecs[3] = intvec_top - 1; |
1234 | mpic->spurious_vec = intvec_top; | 1243 | mpic->spurious_vec = intvec_top; |
1235 | 1244 | ||
1236 | /* Check for "big-endian" in device-tree */ | ||
1237 | if (of_get_property(mpic->node, "big-endian", NULL) != NULL) | ||
1238 | mpic->flags |= MPIC_BIG_ENDIAN; | ||
1239 | if (of_device_is_compatible(mpic->node, "fsl,mpic")) | ||
1240 | mpic->flags |= MPIC_FSL; | ||
1241 | |||
1242 | /* Look for protected sources */ | 1245 | /* Look for protected sources */ |
1243 | psrc = of_get_property(mpic->node, "protected-sources", &psize); | 1246 | psrc = of_get_property(mpic->node, "protected-sources", &psize); |
1244 | if (psrc) { | 1247 | if (psrc) { |
@@ -1254,11 +1257,11 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1254 | } | 1257 | } |
1255 | 1258 | ||
1256 | #ifdef CONFIG_MPIC_WEIRD | 1259 | #ifdef CONFIG_MPIC_WEIRD |
1257 | mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; | 1260 | mpic->hw_set = mpic_infos[MPIC_GET_REGSET(mpic->flags)]; |
1258 | #endif | 1261 | #endif |
1259 | 1262 | ||
1260 | /* default register type */ | 1263 | /* default register type */ |
1261 | if (flags & MPIC_BIG_ENDIAN) | 1264 | if (mpic->flags & MPIC_BIG_ENDIAN) |
1262 | mpic->reg_type = mpic_access_mmio_be; | 1265 | mpic->reg_type = mpic_access_mmio_be; |
1263 | else | 1266 | else |
1264 | mpic->reg_type = mpic_access_mmio_le; | 1267 | mpic->reg_type = mpic_access_mmio_le; |
@@ -1268,10 +1271,10 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1268 | * only if the kernel includes DCR support. | 1271 | * only if the kernel includes DCR support. |
1269 | */ | 1272 | */ |
1270 | #ifdef CONFIG_PPC_DCR | 1273 | #ifdef CONFIG_PPC_DCR |
1271 | if (flags & MPIC_USES_DCR) | 1274 | if (mpic->flags & MPIC_USES_DCR) |
1272 | mpic->reg_type = mpic_access_dcr; | 1275 | mpic->reg_type = mpic_access_dcr; |
1273 | #else | 1276 | #else |
1274 | BUG_ON(flags & MPIC_USES_DCR); | 1277 | BUG_ON(mpic->flags & MPIC_USES_DCR); |
1275 | #endif | 1278 | #endif |
1276 | 1279 | ||
1277 | /* Map the global registers */ | 1280 | /* Map the global registers */ |
@@ -1283,10 +1286,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1283 | /* When using a device-node, reset requests are only honored if the MPIC | 1286 | /* When using a device-node, reset requests are only honored if the MPIC |
1284 | * is allowed to reset. | 1287 | * is allowed to reset. |
1285 | */ | 1288 | */ |
1286 | if (of_get_property(mpic->node, "pic-no-reset", NULL)) | 1289 | if (!(mpic->flags & MPIC_NO_RESET)) { |
1287 | mpic->flags |= MPIC_NO_RESET; | ||
1288 | |||
1289 | if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) { | ||
1290 | printk(KERN_DEBUG "mpic: Resetting\n"); | 1290 | printk(KERN_DEBUG "mpic: Resetting\n"); |
1291 | mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), | 1291 | mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), |
1292 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) | 1292 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) |
@@ -1297,31 +1297,17 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1297 | } | 1297 | } |
1298 | 1298 | ||
1299 | /* CoreInt */ | 1299 | /* CoreInt */ |
1300 | if (flags & MPIC_ENABLE_COREINT) | 1300 | if (mpic->flags & MPIC_ENABLE_COREINT) |
1301 | mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), | 1301 | mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), |
1302 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) | 1302 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) |
1303 | | MPIC_GREG_GCONF_COREINT); | 1303 | | MPIC_GREG_GCONF_COREINT); |
1304 | 1304 | ||
1305 | if (flags & MPIC_ENABLE_MCK) | 1305 | if (mpic->flags & MPIC_ENABLE_MCK) |
1306 | mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), | 1306 | mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), |
1307 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) | 1307 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) |
1308 | | MPIC_GREG_GCONF_MCK); | 1308 | | MPIC_GREG_GCONF_MCK); |
1309 | 1309 | ||
1310 | /* | 1310 | /* |
1311 | * Read feature register. For non-ISU MPICs, num sources as well. On | ||
1312 | * ISU MPICs, sources are counted as ISUs are added | ||
1313 | */ | ||
1314 | greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0)); | ||
1315 | if (isu_size == 0) { | ||
1316 | if (flags & MPIC_BROKEN_FRR_NIRQS) | ||
1317 | mpic->num_sources = mpic->irq_count; | ||
1318 | else | ||
1319 | mpic->num_sources = | ||
1320 | ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK) | ||
1321 | >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1; | ||
1322 | } | ||
1323 | |||
1324 | /* | ||
1325 | * The MPIC driver will crash if there are more cores than we | 1311 | * The MPIC driver will crash if there are more cores than we |
1326 | * can initialize, so we may as well catch that problem here. | 1312 | * can initialize, so we may as well catch that problem here. |
1327 | */ | 1313 | */ |
@@ -1336,17 +1322,41 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1336 | 0x1000); | 1322 | 0x1000); |
1337 | } | 1323 | } |
1338 | 1324 | ||
1325 | /* | ||
1326 | * Read feature register. For non-ISU MPICs, num sources as well. On | ||
1327 | * ISU MPICs, sources are counted as ISUs are added | ||
1328 | */ | ||
1329 | greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0)); | ||
1330 | |||
1331 | /* | ||
1332 | * By default, the last source number comes from the MPIC, but the | ||
1333 | * device-tree and board support code can override it on buggy hw. | ||
1334 | * If we get passed an isu_size (multi-isu MPIC) then we use that | ||
1335 | * as a default instead of the value read from the HW. | ||
1336 | */ | ||
1337 | last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK) | ||
1338 | >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT; | ||
1339 | if (isu_size) | ||
1340 | last_irq = isu_size * MPIC_MAX_ISU - 1; | ||
1341 | of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq); | ||
1342 | if (irq_count) | ||
1343 | last_irq = irq_count - 1; | ||
1344 | |||
1339 | /* Initialize main ISU if none provided */ | 1345 | /* Initialize main ISU if none provided */ |
1340 | if (mpic->isu_size == 0) { | 1346 | if (!isu_size) { |
1341 | mpic->isu_size = mpic->num_sources; | 1347 | isu_size = last_irq + 1; |
1348 | mpic->num_sources = isu_size; | ||
1342 | mpic_map(mpic, mpic->paddr, &mpic->isus[0], | 1349 | mpic_map(mpic, mpic->paddr, &mpic->isus[0], |
1343 | MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); | 1350 | MPIC_INFO(IRQ_BASE), |
1351 | MPIC_INFO(IRQ_STRIDE) * isu_size); | ||
1344 | } | 1352 | } |
1353 | |||
1354 | mpic->isu_size = isu_size; | ||
1345 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); | 1355 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); |
1346 | mpic->isu_mask = (1 << mpic->isu_shift) - 1; | 1356 | mpic->isu_mask = (1 << mpic->isu_shift) - 1; |
1347 | 1357 | ||
1348 | mpic->irqhost = irq_domain_add_linear(mpic->node, | 1358 | mpic->irqhost = irq_domain_add_linear(mpic->node, |
1349 | isu_size ? isu_size : mpic->num_sources, | 1359 | last_irq + 1, |
1350 | &mpic_host_ops, mpic); | 1360 | &mpic_host_ops, mpic); |
1351 | 1361 | ||
1352 | /* | 1362 | /* |
@@ -1380,7 +1390,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1380 | mpic->next = mpics; | 1390 | mpic->next = mpics; |
1381 | mpics = mpic; | 1391 | mpics = mpic; |
1382 | 1392 | ||
1383 | if (!(flags & MPIC_SECONDARY)) { | 1393 | if (!(mpic->flags & MPIC_SECONDARY)) { |
1384 | mpic_primary = mpic; | 1394 | mpic_primary = mpic; |
1385 | irq_set_default_host(mpic->irqhost); | 1395 | irq_set_default_host(mpic->irqhost); |
1386 | } | 1396 | } |
@@ -1447,10 +1457,6 @@ void __init mpic_init(struct mpic *mpic) | |||
1447 | (mpic->ipi_vecs[0] + i)); | 1457 | (mpic->ipi_vecs[0] + i)); |
1448 | } | 1458 | } |
1449 | 1459 | ||
1450 | /* Initialize interrupt sources */ | ||
1451 | if (mpic->irq_count == 0) | ||
1452 | mpic->irq_count = mpic->num_sources; | ||
1453 | |||
1454 | /* Do the HT PIC fixups on U3 broken mpic */ | 1460 | /* Do the HT PIC fixups on U3 broken mpic */ |
1455 | DBG("MPIC flags: %x\n", mpic->flags); | 1461 | DBG("MPIC flags: %x\n", mpic->flags); |
1456 | if ((mpic->flags & MPIC_U3_HT_IRQS) && !(mpic->flags & MPIC_SECONDARY)) { | 1462 | if ((mpic->flags & MPIC_U3_HT_IRQS) && !(mpic->flags & MPIC_SECONDARY)) { |