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

Configure Feed

Select the types of activity you want to include in your feed.

i3c: mipi-i3c-hci: Use physical device pointer with DMA API

DMA transfer faults on Intel hardware when the IOMMU is enabled and
driver initialization will fail when attempting to do the first transfer:

DMAR: DRHD: handling fault status reg 2
DMAR: [DMA Read NO_PASID] Request device [00:11.0] fault addr 0x676e3000 [fault reason 0x71] SM: Present bit in first-level paging entry is clear
i3c mipi-i3c-hci.0: ring 0: Transfer Aborted
mipi-i3c-hci mipi-i3c-hci.0: probe with driver mipi-i3c-hci failed with error -62

Reason for this is that the IOMMU setup is done for the physical devices
only and not for the virtual I3C Controller device object.

Therefore use the pointer to a physical device object with the DMA API.

Due to a data corruption observation when the device DMA is IOMMU
mapped, a properly sized receive bounce buffer is required if transfer
length is not a multiple of DWORDs.

Reported-by:
Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20250822105630.2820009-4-jarkko.nikula@linux.intel.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

authored by

Jarkko Nikula and committed by
Alexandre Belloni
9e23897b 1c46bfc4

+33 -13
+33 -13
drivers/i3c/master/mipi-i3c-hci/dma.c
··· 14 14 #include <linux/errno.h> 15 15 #include <linux/i3c/master.h> 16 16 #include <linux/io.h> 17 + #include <linux/pci.h> 17 18 18 19 #include "hci.h" 19 20 #include "cmd.h" ··· 139 138 }; 140 139 141 140 struct hci_rings_data { 141 + struct device *sysdev; 142 142 unsigned int total; 143 143 struct hci_rh_data headers[] __counted_by(total); 144 144 }; ··· 167 165 rh_reg_write(IBI_SETUP, 0); 168 166 169 167 if (rh->xfer) 170 - dma_free_coherent(&hci->master.dev, 168 + dma_free_coherent(rings->sysdev, 171 169 rh->xfer_struct_sz * rh->xfer_entries, 172 170 rh->xfer, rh->xfer_dma); 173 171 if (rh->resp) 174 - dma_free_coherent(&hci->master.dev, 172 + dma_free_coherent(rings->sysdev, 175 173 rh->resp_struct_sz * rh->xfer_entries, 176 174 rh->resp, rh->resp_dma); 177 175 kfree(rh->src_xfers); 178 176 if (rh->ibi_status) 179 - dma_free_coherent(&hci->master.dev, 177 + dma_free_coherent(rings->sysdev, 180 178 rh->ibi_status_sz * rh->ibi_status_entries, 181 179 rh->ibi_status, rh->ibi_status_dma); 182 180 if (rh->ibi_data_dma) 183 - dma_unmap_single(&hci->master.dev, rh->ibi_data_dma, 181 + dma_unmap_single(rings->sysdev, rh->ibi_data_dma, 184 182 rh->ibi_chunk_sz * rh->ibi_chunks_total, 185 183 DMA_FROM_DEVICE); 186 184 kfree(rh->ibi_data); ··· 196 194 { 197 195 struct hci_rings_data *rings; 198 196 struct hci_rh_data *rh; 197 + struct device *sysdev; 199 198 u32 regval; 200 199 unsigned int i, nr_rings, xfers_sz, resps_sz; 201 200 unsigned int ibi_status_ring_sz, ibi_data_ring_sz; 202 201 int ret; 202 + 203 + /* 204 + * Set pointer to a physical device that does DMA and has IOMMU setup 205 + * done for it in case of enabled IOMMU and use it with the DMA API. 206 + * Here such device is either 207 + * "mipi-i3c-hci" platform device (OF/ACPI enumeration) parent or 208 + * grandparent (PCI enumeration). 209 + */ 210 + sysdev = hci->master.dev.parent; 211 + if (sysdev->parent && dev_is_pci(sysdev->parent)) 212 + sysdev = sysdev->parent; 203 213 204 214 regval = rhs_reg_read(CONTROL); 205 215 nr_rings = FIELD_GET(MAX_HEADER_COUNT_CAP, regval); ··· 227 213 return -ENOMEM; 228 214 hci->io_data = rings; 229 215 rings->total = nr_rings; 216 + rings->sysdev = sysdev; 230 217 231 218 regval = FIELD_PREP(MAX_HEADER_COUNT, rings->total); 232 219 rhs_reg_write(CONTROL, regval); ··· 254 239 xfers_sz = rh->xfer_struct_sz * rh->xfer_entries; 255 240 resps_sz = rh->resp_struct_sz * rh->xfer_entries; 256 241 257 - rh->xfer = dma_alloc_coherent(&hci->master.dev, xfers_sz, 242 + rh->xfer = dma_alloc_coherent(rings->sysdev, xfers_sz, 258 243 &rh->xfer_dma, GFP_KERNEL); 259 - rh->resp = dma_alloc_coherent(&hci->master.dev, resps_sz, 244 + rh->resp = dma_alloc_coherent(rings->sysdev, resps_sz, 260 245 &rh->resp_dma, GFP_KERNEL); 261 246 rh->src_xfers = 262 247 kmalloc_array(rh->xfer_entries, sizeof(*rh->src_xfers), ··· 310 295 ibi_data_ring_sz = rh->ibi_chunk_sz * rh->ibi_chunks_total; 311 296 312 297 rh->ibi_status = 313 - dma_alloc_coherent(&hci->master.dev, ibi_status_ring_sz, 298 + dma_alloc_coherent(rings->sysdev, ibi_status_ring_sz, 314 299 &rh->ibi_status_dma, GFP_KERNEL); 315 300 rh->ibi_data = kmalloc(ibi_data_ring_sz, GFP_KERNEL); 316 301 ret = -ENOMEM; 317 302 if (!rh->ibi_status || !rh->ibi_data) 318 303 goto err_out; 319 304 rh->ibi_data_dma = 320 - dma_map_single(&hci->master.dev, rh->ibi_data, 305 + dma_map_single(rings->sysdev, rh->ibi_data, 321 306 ibi_data_ring_sz, DMA_FROM_DEVICE); 322 - if (dma_mapping_error(&hci->master.dev, rh->ibi_data_dma)) { 307 + if (dma_mapping_error(rings->sysdev, rh->ibi_data_dma)) { 323 308 rh->ibi_data_dma = 0; 324 309 ret = -ENOMEM; 325 310 goto err_out; ··· 387 372 u32 *ring_data = rh->xfer + rh->xfer_struct_sz * enqueue_ptr; 388 373 enum dma_data_direction dir = xfer->rnw ? DMA_FROM_DEVICE : 389 374 DMA_TO_DEVICE; 375 + bool need_bounce; 390 376 391 377 /* store cmd descriptor */ 392 378 *ring_data++ = xfer->cmd_desc[0]; ··· 406 390 407 391 /* 2nd and 3rd words of Data Buffer Descriptor Structure */ 408 392 if (xfer->data) { 409 - xfer->dma = i3c_master_dma_map_single(&hci->master.dev, 393 + need_bounce = device_iommu_mapped(rings->sysdev) && 394 + xfer->rnw && 395 + xfer->data_len != ALIGN(xfer->data_len, 4); 396 + xfer->dma = i3c_master_dma_map_single(rings->sysdev, 410 397 xfer->data, 411 398 xfer->data_len, 412 - false, 399 + need_bounce, 413 400 dir); 414 401 if (!xfer->dma) { 415 402 hci_dma_unmap_xfer(hci, xfer_list, i); ··· 600 581 601 582 static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh) 602 583 { 584 + struct hci_rings_data *rings = hci->io_data; 603 585 struct i3c_dev_desc *dev; 604 586 struct i3c_hci_dev_data *dev_data; 605 587 struct hci_dma_dev_ibi_data *dev_ibi; ··· 711 691 * rh->ibi_chunk_sz; 712 692 if (first_part > ibi_size) 713 693 first_part = ibi_size; 714 - dma_sync_single_for_cpu(&hci->master.dev, ring_ibi_data_dma, 694 + dma_sync_single_for_cpu(rings->sysdev, ring_ibi_data_dma, 715 695 first_part, DMA_FROM_DEVICE); 716 696 memcpy(slot->data, ring_ibi_data, first_part); 717 697 ··· 720 700 /* we wrap back to the start and copy remaining data */ 721 701 ring_ibi_data = rh->ibi_data; 722 702 ring_ibi_data_dma = rh->ibi_data_dma; 723 - dma_sync_single_for_cpu(&hci->master.dev, ring_ibi_data_dma, 703 + dma_sync_single_for_cpu(rings->sysdev, ring_ibi_data_dma, 724 704 ibi_size - first_part, DMA_FROM_DEVICE); 725 705 memcpy(slot->data + first_part, ring_ibi_data, 726 706 ibi_size - first_part);