Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Fix bogus it_blocksize in VIO iommu code

When looking at some issues with the virtual ethernet driver I noticed
that TCE allocation was following a very strange pattern:

address 00e9000 length 2048
address 0409000 length 2048 <-----
address 0429000 length 2048
address 0449000 length 2048
address 0469000 length 2048
address 0489000 length 2048
address 04a9000 length 2048
address 04c9000 length 2048
address 04e9000 length 2048
address 4009000 length 2048 <-----
address 4029000 length 2048

Huge unexplained gaps in what should be an empty TCE table. It turns out
it_blocksize, the amount we want to align the next allocation to, was
c0000000fe903b20. Completely bogus.

Initialise it to something reasonable in the VIO IOMMU code, and use kzalloc
everywhere to protect against this when we next add a non compulsary
field to iommu code and forget to initialise it.

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Anton Blanchard and committed by
Benjamin Herrenschmidt
7aa241fd 4138d653

+8 -7
+2 -1
arch/powerpc/kernel/vio.c
··· 1059 1059 if (!dma_window) 1060 1060 return NULL; 1061 1061 1062 - tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); 1062 + tbl = kzalloc(sizeof(*tbl), GFP_KERNEL); 1063 1063 if (tbl == NULL) 1064 1064 return NULL; 1065 1065 ··· 1072 1072 tbl->it_offset = offset >> IOMMU_PAGE_SHIFT; 1073 1073 tbl->it_busno = 0; 1074 1074 tbl->it_type = TCE_VB; 1075 + tbl->it_blocksize = 16; 1075 1076 1076 1077 return iommu_init_table(tbl, -1); 1077 1078 }
+1 -1
arch/powerpc/platforms/cell/iommu.c
··· 477 477 478 478 ioid = cell_iommu_get_ioid(np); 479 479 480 - window = kmalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid); 480 + window = kzalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid); 481 481 BUG_ON(window == NULL); 482 482 483 483 window->offset = offset;
+1 -1
arch/powerpc/platforms/iseries/iommu.c
··· 184 184 185 185 BUG_ON(lsn == NULL); 186 186 187 - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); 187 + tbl = kzalloc(sizeof(struct iommu_table), GFP_KERNEL); 188 188 189 189 iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl); 190 190
+4 -4
arch/powerpc/platforms/pseries/iommu.c
··· 403 403 pci->phb->dma_window_size = 0x8000000ul; 404 404 pci->phb->dma_window_base_cur = 0x8000000ul; 405 405 406 - tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 406 + tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 407 407 pci->phb->node); 408 408 409 409 iommu_table_setparms(pci->phb, dn, tbl); ··· 448 448 pdn->full_name, ppci->iommu_table); 449 449 450 450 if (!ppci->iommu_table) { 451 - tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 451 + tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 452 452 ppci->phb->node); 453 453 iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window, 454 454 bus->number); ··· 478 478 struct pci_controller *phb = PCI_DN(dn)->phb; 479 479 480 480 pr_debug(" --> first child, no bridge. Allocating iommu table.\n"); 481 - tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 481 + tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 482 482 phb->node); 483 483 iommu_table_setparms(phb, dn, tbl); 484 484 PCI_DN(dn)->iommu_table = iommu_init_table(tbl, phb->node); ··· 544 544 545 545 pci = PCI_DN(pdn); 546 546 if (!pci->iommu_table) { 547 - tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 547 + tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, 548 548 pci->phb->node); 549 549 iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window, 550 550 pci->phb->bus->number);