diff options
author | Olof Johansson <olof@lixom.net> | 2005-09-21 12:55:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-21 13:11:54 -0400 |
commit | 3c2822ccb1f8cc96fc006aa82e68e1944290014a (patch) | |
tree | 3834b0004ef12b96f699529ca8008a0644531fa3 | |
parent | 31f6d9d628739c097964b8dbae939ea997da94a3 (diff) |
[PATCH] PPC64: Fix boot for some pre-POWER4 systems
Some RS64 systems (such as F80) have non-python host bridges with EADS.
However, they have two EADS with 4 buses each under them, so the old logic
that assumed no more than 7 busses per PHB failed miserably.
Big thanks to Olaf Hering for helping me test this, he's got one of the few
machines that broke from the previous logic.
Also, to be a bit smarter at detecting the need for a PHB-level IOMMU table
by checking for the presence of an ISA bus. Only PHBs with ISA bridges
should need the PHB-level table.
Signed-off-by: Olof Johansson <olof@lixom.net>
Cc: Anton Blanchard <anton@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/ppc64/kernel/pSeries_iommu.c | 169 |
1 files changed, 89 insertions, 80 deletions
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c index f0fd7fbd6531..8c6313e7e145 100644 --- a/arch/ppc64/kernel/pSeries_iommu.c +++ b/arch/ppc64/kernel/pSeries_iommu.c | |||
@@ -265,8 +265,10 @@ static void iommu_table_setparms(struct pci_controller *phb, | |||
265 | tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; | 265 | tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; |
266 | 266 | ||
267 | /* Test if we are going over 2GB of DMA space */ | 267 | /* Test if we are going over 2GB of DMA space */ |
268 | if (phb->dma_window_base_cur + phb->dma_window_size > (1L << 31)) | 268 | if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) { |
269 | udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); | ||
269 | panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); | 270 | panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); |
271 | } | ||
270 | 272 | ||
271 | phb->dma_window_base_cur += phb->dma_window_size; | 273 | phb->dma_window_base_cur += phb->dma_window_size; |
272 | 274 | ||
@@ -310,92 +312,84 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, | |||
310 | 312 | ||
311 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) | 313 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) |
312 | { | 314 | { |
313 | struct device_node *dn, *pdn; | 315 | struct device_node *dn; |
314 | struct pci_dn *pci; | ||
315 | struct iommu_table *tbl; | 316 | struct iommu_table *tbl; |
317 | struct device_node *isa_dn, *isa_dn_orig; | ||
318 | struct device_node *tmp; | ||
319 | struct pci_dn *pci; | ||
320 | int children; | ||
316 | 321 | ||
317 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); | 322 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); |
318 | 323 | ||
319 | /* For each (root) bus, we carve up the available DMA space in 256MB | 324 | dn = pci_bus_to_OF_node(bus); |
320 | * pieces. Since each piece is used by one (sub) bus/device, that would | 325 | pci = PCI_DN(dn); |
321 | * give a maximum of 7 devices per PHB. In most cases, this is plenty. | 326 | |
322 | * | 327 | if (bus->self) { |
323 | * The exception is on Python PHBs (pre-POWER4). Here we don't have EADS | 328 | /* This is not a root bus, any setup will be done for the |
324 | * bridges below the PHB to allocate the sectioned tables to, so instead | 329 | * device-side of the bridge in iommu_dev_setup_pSeries(). |
325 | * we allocate a 1GB table at the PHB level. | 330 | */ |
331 | return; | ||
332 | } | ||
333 | |||
334 | /* Check if the ISA bus on the system is under | ||
335 | * this PHB. | ||
326 | */ | 336 | */ |
337 | isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa"); | ||
327 | 338 | ||
328 | dn = pci_bus_to_OF_node(bus); | 339 | while (isa_dn && isa_dn != dn) |
329 | pci = dn->data; | 340 | isa_dn = isa_dn->parent; |
330 | 341 | ||
331 | if (!bus->self) { | 342 | if (isa_dn_orig) |
332 | /* Root bus */ | 343 | of_node_put(isa_dn_orig); |
333 | if (is_python(dn)) { | ||
334 | unsigned int *iohole; | ||
335 | |||
336 | DBG("Python root bus %s\n", bus->name); | ||
337 | |||
338 | iohole = (unsigned int *)get_property(dn, "io-hole", 0); | ||
339 | |||
340 | if (iohole) { | ||
341 | /* On first bus we need to leave room for the | ||
342 | * ISA address space. Just skip the first 256MB | ||
343 | * alltogether. This leaves 768MB for the window. | ||
344 | */ | ||
345 | DBG("PHB has io-hole, reserving 256MB\n"); | ||
346 | pci->phb->dma_window_size = 3 << 28; | ||
347 | pci->phb->dma_window_base_cur = 1 << 28; | ||
348 | } else { | ||
349 | /* 1GB window by default */ | ||
350 | pci->phb->dma_window_size = 1 << 30; | ||
351 | pci->phb->dma_window_base_cur = 0; | ||
352 | } | ||
353 | |||
354 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
355 | |||
356 | iommu_table_setparms(pci->phb, dn, tbl); | ||
357 | pci->iommu_table = iommu_init_table(tbl); | ||
358 | } else { | ||
359 | /* Do a 128MB table at root. This is used for the IDE | ||
360 | * controller on some SMP-mode POWER4 machines. It | ||
361 | * doesn't hurt to allocate it on other machines | ||
362 | * -- it'll just be unused since new tables are | ||
363 | * allocated on the EADS level. | ||
364 | * | ||
365 | * Allocate at offset 128MB to avoid having to deal | ||
366 | * with ISA holes; 128MB table for IDE is plenty. | ||
367 | */ | ||
368 | pci->phb->dma_window_size = 1 << 27; | ||
369 | pci->phb->dma_window_base_cur = 1 << 27; | ||
370 | |||
371 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
372 | |||
373 | iommu_table_setparms(pci->phb, dn, tbl); | ||
374 | pci->iommu_table = iommu_init_table(tbl); | ||
375 | |||
376 | /* All child buses have 256MB tables */ | ||
377 | pci->phb->dma_window_size = 1 << 28; | ||
378 | } | ||
379 | } else { | ||
380 | pdn = pci_bus_to_OF_node(bus->parent); | ||
381 | 344 | ||
382 | if (!bus->parent->self && !is_python(pdn)) { | 345 | /* Count number of direct PCI children of the PHB. |
383 | struct iommu_table *tbl; | 346 | * All PCI device nodes have class-code property, so it's |
384 | /* First child and not python means this is the EADS | 347 | * an easy way to find them. |
385 | * level. Allocate new table for this slot with 256MB | 348 | */ |
386 | * window. | 349 | for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) |
387 | */ | 350 | if (get_property(tmp, "class-code", NULL)) |
351 | children++; | ||
388 | 352 | ||
389 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | 353 | DBG("Children: %d\n", children); |
390 | 354 | ||
391 | iommu_table_setparms(pci->phb, dn, tbl); | 355 | /* Calculate amount of DMA window per slot. Each window must be |
356 | * a power of two (due to pci_alloc_consistent requirements). | ||
357 | * | ||
358 | * Keep 256MB aside for PHBs with ISA. | ||
359 | */ | ||
392 | 360 | ||
393 | pci->iommu_table = iommu_init_table(tbl); | 361 | if (!isa_dn) { |
394 | } else { | 362 | /* No ISA/IDE - just set window size and return */ |
395 | /* Lower than first child or under python, use parent table */ | 363 | pci->phb->dma_window_size = 0x80000000ul; /* To be divided */ |
396 | pci->iommu_table = PCI_DN(pdn)->iommu_table; | 364 | |
397 | } | 365 | while (pci->phb->dma_window_size * children > 0x80000000ul) |
366 | pci->phb->dma_window_size >>= 1; | ||
367 | DBG("No ISA/IDE, window size is %x\n", pci->phb->dma_window_size); | ||
368 | pci->phb->dma_window_base_cur = 0; | ||
369 | |||
370 | return; | ||
398 | } | 371 | } |
372 | |||
373 | /* If we have ISA, then we probably have an IDE | ||
374 | * controller too. Allocate a 128MB table but | ||
375 | * skip the first 128MB to avoid stepping on ISA | ||
376 | * space. | ||
377 | */ | ||
378 | pci->phb->dma_window_size = 0x8000000ul; | ||
379 | pci->phb->dma_window_base_cur = 0x8000000ul; | ||
380 | |||
381 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
382 | |||
383 | iommu_table_setparms(pci->phb, dn, tbl); | ||
384 | pci->iommu_table = iommu_init_table(tbl); | ||
385 | |||
386 | /* Divide the rest (1.75GB) among the children */ | ||
387 | pci->phb->dma_window_size = 0x80000000ul; | ||
388 | while (pci->phb->dma_window_size * children > 0x70000000ul) | ||
389 | pci->phb->dma_window_size >>= 1; | ||
390 | |||
391 | DBG("ISA/IDE, window size is %x\n", pci->phb->dma_window_size); | ||
392 | |||
399 | } | 393 | } |
400 | 394 | ||
401 | 395 | ||
@@ -446,14 +440,29 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
446 | static void iommu_dev_setup_pSeries(struct pci_dev *dev) | 440 | static void iommu_dev_setup_pSeries(struct pci_dev *dev) |
447 | { | 441 | { |
448 | struct device_node *dn, *mydn; | 442 | struct device_node *dn, *mydn; |
443 | struct iommu_table *tbl; | ||
449 | 444 | ||
450 | DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name); | 445 | DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name); |
451 | /* Now copy the iommu_table ptr from the bus device down to the | 446 | |
452 | * pci device_node. This means get_iommu_table() won't need to search | ||
453 | * up the device tree to find it. | ||
454 | */ | ||
455 | mydn = dn = pci_device_to_OF_node(dev); | 447 | mydn = dn = pci_device_to_OF_node(dev); |
456 | 448 | ||
449 | /* If we're the direct child of a root bus, then we need to allocate | ||
450 | * an iommu table ourselves. The bus setup code should have setup | ||
451 | * the window sizes already. | ||
452 | */ | ||
453 | if (!dev->bus->self) { | ||
454 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); | ||
455 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
456 | iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); | ||
457 | PCI_DN(mydn)->iommu_table = iommu_init_table(tbl); | ||
458 | |||
459 | return; | ||
460 | } | ||
461 | |||
462 | /* If this device is further down the bus tree, search upwards until | ||
463 | * an already allocated iommu table is found and use that. | ||
464 | */ | ||
465 | |||
457 | while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL) | 466 | while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL) |
458 | dn = dn->parent; | 467 | dn = dn->parent; |
459 | 468 | ||