static int ntb_setup_interrupts(struct ntb_softc *ntb) { uint32_t desired_vectors, num_vectors; uint64_t mask; int rc; ntb->allocated_interrupts = 0; /* * On SOC, disable all interrupts. On XEON, disable all but Link * Interrupt. The rest will be unmasked as callbacks are registered. */ mask = 0; if (ntb->type == NTB_XEON) mask = (1 << XEON_LINK_DB); db_iowrite(ntb, ntb->reg_ofs.ldb_mask, ~mask); num_vectors = desired_vectors = MIN(pci_msix_count(ntb->device), ntb->limits.max_db_bits); if (desired_vectors >= 1) { rc = pci_alloc_msix(ntb->device, &num_vectors); if (ntb_force_remap_mode != 0 && rc == 0 && num_vectors == desired_vectors) num_vectors--; if (rc == 0 && num_vectors < desired_vectors) { rc = ntb_remap_msix(ntb->device, desired_vectors, num_vectors); if (rc == 0) num_vectors = desired_vectors; else pci_release_msi(ntb->device); } if (rc != 0) num_vectors = 1; } else num_vectors = 1; ntb_create_callbacks(ntb, num_vectors); if (ntb->type == NTB_XEON) rc = ntb_setup_xeon_msix(ntb, num_vectors); else rc = ntb_setup_soc_msix(ntb, num_vectors); if (rc != 0) device_printf(ntb->device, "Error allocating MSI-X interrupts: %d\n", rc); if (ntb->type == NTB_XEON && rc == ENOSPC) rc = ntb_setup_legacy_interrupt(ntb); return (rc); }
static int ntb_setup_interrupts(struct ntb_softc *ntb) { uint32_t desired_vectors, num_vectors; uint64_t mask; int rc; ntb->allocated_interrupts = 0; /* * On SOC, disable all interrupts. On XEON, disable all but Link * Interrupt. The rest will be unmasked as callbacks are registered. */ mask = 0; if (ntb->type == NTB_XEON) mask = (1 << XEON_LINK_DB); db_iowrite(ntb, ntb->reg_ofs.ldb_mask, ~mask); num_vectors = desired_vectors = MIN(pci_msix_count(ntb->device), ntb->limits.max_db_bits); if (desired_vectors >= 1) { rc = pci_alloc_msix(ntb->device, &num_vectors); if (ntb_force_remap_mode != 0 && rc == 0 && num_vectors == desired_vectors) num_vectors--; if (rc == 0 && num_vectors < desired_vectors) { rc = ntb_remap_msix(ntb->device, desired_vectors, num_vectors); if (rc == 0) num_vectors = desired_vectors; else pci_release_msi(ntb->device); } if (rc != 0) num_vectors = 1; } else num_vectors = 1; /* * If allocating MSI-X interrupts succeeds, limit callbacks to the * number of MSI-X slots available. */ ntb_create_callbacks(ntb, num_vectors); if (ntb->type == NTB_XEON) rc = ntb_setup_xeon_msix(ntb, num_vectors); else rc = ntb_setup_soc_msix(ntb, num_vectors); if (rc != 0) { device_printf(ntb->device, "Error allocating MSI-X interrupts: %d\n", rc); /* * If allocating MSI-X interrupts failed and we're forced to * use legacy INTx anyway, the only limit on individual * callbacks is the number of doorbell bits. * * CEM: This seems odd to me but matches the behavior of the * Linux driver ca. September 2013 */ ntb_free_callbacks(ntb); ntb_create_callbacks(ntb, ntb->limits.max_db_bits); } if (ntb->type == NTB_XEON && rc == ENOSPC) rc = ntb_setup_legacy_interrupt(ntb); return (rc); }