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

PCI: dwc: Drop dependency on ZONE_DMA32

Re-work the msi_msg DMA allocation logic to use dmam_alloc_coherent() which
uses the coherent DMA mask to try to return an allocation within the DMA
mask limits. With that, we now can drop the msi_page parameter in struct
dw_pcie_rp. This allows kernel configurations that disable ZONE_DMA32 to
continue supporting a 32-bit DMA mask. Without this patch, the PCIe host
device will fail to probe when ZONE_DMA32 is disabled.

Link: https://lore.kernel.org/r/20220825235404.4132818-2-willmcvicker@google.com
Fixes: 35797e672ff0 ("PCI: dwc: Fix MSI msi_msg DMA mapping")
Reported-by: Isaac J. Manjarres <isaacmanjarres@google.com>
Signed-off-by: Will McVicker <willmcvicker@google.com>
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Reviewed-by: Rob Herring <robh@kernel.org>
Acked-by: Jingoo Han <jingoohan1@gmail.com>

authored by

Will McVicker and committed by
Lorenzo Pieralisi
423511ec 568035b0

+7 -22
+7 -21
drivers/pci/controller/dwc/pcie-designware-host.c
··· 267 267 268 268 irq_domain_remove(pp->msi_domain); 269 269 irq_domain_remove(pp->irq_domain); 270 - 271 - if (pp->msi_data) { 272 - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 273 - struct device *dev = pci->dev; 274 - 275 - dma_unmap_page(dev, pp->msi_data, PAGE_SIZE, DMA_FROM_DEVICE); 276 - if (pp->msi_page) 277 - __free_page(pp->msi_page); 278 - } 279 270 } 280 271 281 272 static void dw_pcie_msi_init(struct dw_pcie_rp *pp) ··· 327 336 struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 328 337 struct device *dev = pci->dev; 329 338 struct platform_device *pdev = to_platform_device(dev); 339 + u64 *msi_vaddr; 330 340 int ret; 331 341 u32 ctrl, num_ctrls; 332 342 ··· 367 375 dw_chained_msi_isr, pp); 368 376 } 369 377 370 - ret = dma_set_mask(dev, DMA_BIT_MASK(32)); 378 + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); 371 379 if (ret) 372 380 dev_warn(dev, "Failed to set DMA mask to 32-bit. Devices with only 32-bit MSI support may not work properly\n"); 373 381 374 - pp->msi_page = alloc_page(GFP_DMA32); 375 - pp->msi_data = dma_map_page(dev, pp->msi_page, 0, 376 - PAGE_SIZE, DMA_FROM_DEVICE); 377 - ret = dma_mapping_error(dev, pp->msi_data); 378 - if (ret) { 379 - dev_err(pci->dev, "Failed to map MSI data\n"); 380 - __free_page(pp->msi_page); 381 - pp->msi_page = NULL; 382 - pp->msi_data = 0; 382 + msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data, 383 + GFP_KERNEL); 384 + if (!msi_vaddr) { 385 + dev_err(dev, "Failed to alloc and map MSI data\n"); 383 386 dw_pcie_free_msi(pp); 384 - 385 - return ret; 387 + return -ENOMEM; 386 388 } 387 389 388 390 return 0;
-1
drivers/pci/controller/dwc/pcie-designware.h
··· 243 243 struct irq_domain *irq_domain; 244 244 struct irq_domain *msi_domain; 245 245 dma_addr_t msi_data; 246 - struct page *msi_page; 247 246 struct irq_chip *msi_irq_chip; 248 247 u32 num_vectors; 249 248 u32 irq_mask[MAX_MSI_CTRLS];