| 1320 | } |
| 1321 | |
| 1322 | int |
| 1323 | intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count, |
| 1324 | int maxcount, int *irqs) |
| 1325 | { |
| 1326 | struct iommu_domain *domain; |
| 1327 | struct intr_irqsrc **isrc; |
| 1328 | struct intr_pic *pic; |
| 1329 | device_t pdev; |
| 1330 | struct intr_map_data_msi *msi; |
| 1331 | int err, i; |
| 1332 | |
| 1333 | pic = pic_lookup(NULL, xref, FLAG_MSI); |
| 1334 | if (pic == NULL) |
| 1335 | return (ESRCH); |
| 1336 | |
| 1337 | KASSERT((pic->pic_flags & FLAG_TYPE_MASK) == FLAG_MSI, |
| 1338 | ("%s: Found a non-MSI controller: %s", __func__, |
| 1339 | device_get_name(pic->pic_dev))); |
| 1340 | |
| 1341 | /* |
| 1342 | * If this is the first time we have used this context ask the |
| 1343 | * interrupt controller to map memory the msi source will need. |
| 1344 | */ |
| 1345 | err = MSI_IOMMU_INIT(pic->pic_dev, child, &domain); |
| 1346 | if (err != 0) |
| 1347 | return (err); |
| 1348 | |
| 1349 | isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK); |
| 1350 | err = MSI_ALLOC_MSI(pic->pic_dev, child, count, maxcount, &pdev, isrc); |
| 1351 | if (err != 0) { |
| 1352 | free(isrc, M_INTRNG); |
| 1353 | return (err); |
| 1354 | } |
| 1355 | |
| 1356 | for (i = 0; i < count; i++) { |
| 1357 | isrc[i]->isrc_iommu = domain; |
| 1358 | msi = (struct intr_map_data_msi *)intr_alloc_map_data( |
| 1359 | INTR_MAP_DATA_MSI, sizeof(*msi), M_WAITOK | M_ZERO); |
| 1360 | msi-> isrc = isrc[i]; |
| 1361 | |
| 1362 | irqs[i] = intr_map_irq(pic->pic_dev, xref, |
| 1363 | (struct intr_map_data *)msi); |
| 1364 | } |
| 1365 | free(isrc, M_INTRNG); |
| 1366 | |
| 1367 | return (err); |
| 1368 | } |
| 1369 | |
| 1370 | int |
| 1371 | intr_release_msi(device_t pci, device_t child, intptr_t xref, int count, |
no test coverage detected