Lines Matching +full:msi +full:- +full:x
1 // SPDX-License-Identifier: GPL-2.0
3 * PCI Backend Operations - respond to PCI requests from Frontend
35 if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) in xen_pcibk_control_isr()
39 dev_data->enable_intx = 0; in xen_pcibk_control_isr()
40 dev_data->ack_intr = 0; in xen_pcibk_control_isr()
42 enable = dev_data->enable_intx; in xen_pcibk_control_isr()
45 if (!enable && !dev_data->isr_on) in xen_pcibk_control_isr()
49 * b/c when device transitions to MSI, the dev->irq is in xen_pcibk_control_isr()
50 * overwritten with the MSI vector. in xen_pcibk_control_isr()
53 dev_data->irq = dev->irq; in xen_pcibk_control_isr()
56 * SR-IOV devices in all use MSI-X and have no legacy in xen_pcibk_control_isr()
59 if (dev_data->irq == 0) in xen_pcibk_control_isr()
62 dev_dbg(&dev->dev, "%s: #%d %s %s%s %s-> %s\n", in xen_pcibk_control_isr()
63 dev_data->irq_name, in xen_pcibk_control_isr()
64 dev_data->irq, in xen_pcibk_control_isr()
66 dev->msi_enabled ? "MSI" : "", in xen_pcibk_control_isr()
67 dev->msix_enabled ? "MSI/X" : "", in xen_pcibk_control_isr()
68 dev_data->isr_on ? "enable" : "disable", in xen_pcibk_control_isr()
73 * The MSI or MSI-X should not have an IRQ handler. Otherwise in xen_pcibk_control_isr()
76 if (dev->msi_enabled || dev->msix_enabled) in xen_pcibk_control_isr()
79 rc = request_irq(dev_data->irq, in xen_pcibk_control_isr()
81 dev_data->irq_name, dev); in xen_pcibk_control_isr()
83 dev_err(&dev->dev, "%s: failed to install fake IRQ " \ in xen_pcibk_control_isr()
85 dev_data->irq_name, dev_data->irq, rc); in xen_pcibk_control_isr()
89 free_irq(dev_data->irq, dev); in xen_pcibk_control_isr()
90 dev_data->irq = 0; in xen_pcibk_control_isr()
92 dev_data->isr_on = enable; in xen_pcibk_control_isr()
93 dev_data->ack_intr = enable; in xen_pcibk_control_isr()
95 dev_dbg(&dev->dev, "%s: #%d %s %s%s %s\n", in xen_pcibk_control_isr()
96 dev_data->irq_name, in xen_pcibk_control_isr()
97 dev_data->irq, in xen_pcibk_control_isr()
99 dev->msi_enabled ? "MSI" : "", in xen_pcibk_control_isr()
100 dev->msix_enabled ? "MSI/X" : "", in xen_pcibk_control_isr()
101 enable ? (dev_data->isr_on ? "enabled" : "failed to enable") : in xen_pcibk_control_isr()
102 (dev_data->isr_on ? "failed to disable" : "disabled")); in xen_pcibk_control_isr()
107 * ready to be re-exported)
116 if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) { in xen_pcibk_reset_device()
119 * disabling MSI/MSI-X interrupts.*/ in xen_pcibk_reset_device()
120 if (dev->msix_enabled) in xen_pcibk_reset_device()
122 if (dev->msi_enabled) in xen_pcibk_reset_device()
128 dev->is_busmaster = 0; in xen_pcibk_reset_device()
135 dev->is_busmaster = 0; in xen_pcibk_reset_device()
148 if (dev->msi_enabled) in xen_pcibk_enable_msi()
149 status = -EALREADY; in xen_pcibk_enable_msi()
150 else if (dev->msix_enabled) in xen_pcibk_enable_msi()
151 status = -ENXIO; in xen_pcibk_enable_msi()
156 dev_warn_ratelimited(&dev->dev, "error enabling MSI for guest %u: err %d\n", in xen_pcibk_enable_msi()
157 pdev->xdev->otherend_id, status); in xen_pcibk_enable_msi()
158 op->value = 0; in xen_pcibk_enable_msi()
165 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; in xen_pcibk_enable_msi()
167 dev_dbg(&dev->dev, "MSI: %d\n", op->value); in xen_pcibk_enable_msi()
171 dev_data->ack_intr = 0; in xen_pcibk_enable_msi()
180 if (dev->msi_enabled) { in xen_pcibk_disable_msi()
187 dev_data->ack_intr = 1; in xen_pcibk_disable_msi()
189 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; in xen_pcibk_disable_msi()
191 dev_dbg(&dev->dev, "MSI: %d\n", op->value); in xen_pcibk_disable_msi()
205 dev_dbg(&dev->dev, "enable MSI-X\n"); in xen_pcibk_enable_msix()
207 if (op->value > SH_INFO_MAX_VEC) in xen_pcibk_enable_msix()
208 return -EINVAL; in xen_pcibk_enable_msix()
210 if (dev->msix_enabled) in xen_pcibk_enable_msix()
211 return -EALREADY; in xen_pcibk_enable_msix()
215 * to access the BARs where the MSI-X entries reside. in xen_pcibk_enable_msix()
219 if (dev->msi_enabled || !(cmd & PCI_COMMAND_MEMORY)) in xen_pcibk_enable_msix()
220 return -ENXIO; in xen_pcibk_enable_msix()
222 entries = kmalloc_array(op->value, sizeof(*entries), GFP_KERNEL); in xen_pcibk_enable_msix()
224 return -ENOMEM; in xen_pcibk_enable_msix()
226 for (i = 0; i < op->value; i++) { in xen_pcibk_enable_msix()
227 entries[i].entry = op->msix_entries[i].entry; in xen_pcibk_enable_msix()
228 entries[i].vector = op->msix_entries[i].vector; in xen_pcibk_enable_msix()
231 result = pci_enable_msix_exact(dev, entries, op->value); in xen_pcibk_enable_msix()
233 for (i = 0; i < op->value; i++) { in xen_pcibk_enable_msix()
234 op->msix_entries[i].entry = entries[i].entry; in xen_pcibk_enable_msix()
236 op->msix_entries[i].vector = in xen_pcibk_enable_msix()
238 dev_dbg(&dev->dev, "MSI-X[%d]: %d\n", i, in xen_pcibk_enable_msix()
239 op->msix_entries[i].vector); in xen_pcibk_enable_msix()
243 dev_warn_ratelimited(&dev->dev, "error enabling MSI-X for guest %u: err %d!\n", in xen_pcibk_enable_msix()
244 pdev->xdev->otherend_id, result); in xen_pcibk_enable_msix()
247 op->value = result; in xen_pcibk_enable_msix()
250 dev_data->ack_intr = 0; in xen_pcibk_enable_msix()
259 if (dev->msix_enabled) { in xen_pcibk_disable_msix()
266 dev_data->ack_intr = 1; in xen_pcibk_disable_msix()
269 * SR-IOV devices (which don't have any legacy IRQ) have in xen_pcibk_disable_msix()
272 op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; in xen_pcibk_disable_msix()
274 dev_dbg(&dev->dev, "MSI-X: %d\n", op->value); in xen_pcibk_disable_msix()
283 (unsigned long *)&pdev->sh_info->flags) && in xen_pcibk_test_op_pending()
284 !test_and_set_bit(_PDEVF_op_active, &pdev->flags); in xen_pcibk_test_op_pending()
300 schedule_work(&pdev->op_work); in xen_pcibk_test_and_schedule_op()
305 if (!test_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags) in xen_pcibk_test_and_schedule_op()
306 && test_bit(_PCIB_op_pending, &pdev->flags)) { in xen_pcibk_test_and_schedule_op()
325 struct xen_pci_op *op = &pdev->op; in xen_pcibk_do_one_op()
331 *op = pdev->sh_info->op; in xen_pcibk_do_one_op()
333 dev = xen_pcibk_get_pci_dev(pdev, op->domain, op->bus, op->devfn); in xen_pcibk_do_one_op()
336 op->err = XEN_PCI_ERR_dev_not_found; in xen_pcibk_do_one_op()
340 test_intx = dev_data->enable_intx; in xen_pcibk_do_one_op()
341 switch (op->cmd) { in xen_pcibk_do_one_op()
343 op->err = xen_pcibk_config_read(dev, in xen_pcibk_do_one_op()
344 op->offset, op->size, &op->value); in xen_pcibk_do_one_op()
347 op->err = xen_pcibk_config_write(dev, in xen_pcibk_do_one_op()
348 op->offset, op->size, op->value); in xen_pcibk_do_one_op()
352 op->err = xen_pcibk_enable_msi(pdev, dev, op); in xen_pcibk_do_one_op()
355 op->err = xen_pcibk_disable_msi(pdev, dev, op); in xen_pcibk_do_one_op()
358 nr = op->value; in xen_pcibk_do_one_op()
359 op->err = xen_pcibk_enable_msix(pdev, dev, op); in xen_pcibk_do_one_op()
362 op->err = xen_pcibk_disable_msix(pdev, dev, op); in xen_pcibk_do_one_op()
366 op->err = XEN_PCI_ERR_not_implemented; in xen_pcibk_do_one_op()
370 if (!op->err && dev && dev_data) { in xen_pcibk_do_one_op()
372 if ((dev_data->enable_intx != test_intx)) in xen_pcibk_do_one_op()
375 pdev->sh_info->op.err = op->err; in xen_pcibk_do_one_op()
376 pdev->sh_info->op.value = op->value; in xen_pcibk_do_one_op()
378 if (op->cmd == XEN_PCI_OP_enable_msix && op->err == 0) { in xen_pcibk_do_one_op()
382 pdev->sh_info->op.msix_entries[i].vector = in xen_pcibk_do_one_op()
383 op->msix_entries[i].vector; in xen_pcibk_do_one_op()
388 clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags); in xen_pcibk_do_one_op()
389 notify_remote_via_irq(pdev->evtchn_irq); in xen_pcibk_do_one_op()
393 clear_bit(_PDEVF_op_active, &pdev->flags); in xen_pcibk_do_one_op()
414 /* IRQs might come in before pdev->evtchn_irq is written. */ in xen_pcibk_handle_event()
415 if (unlikely(pdev->evtchn_irq != irq)) in xen_pcibk_handle_event()
416 pdev->evtchn_irq = irq; in xen_pcibk_handle_event()
418 eoi = test_and_set_bit(_EOI_pending, &pdev->flags); in xen_pcibk_handle_event()
430 if (dev_data->isr_on && dev_data->ack_intr) { in xen_pcibk_guest_interrupt()
431 dev_data->handled++; in xen_pcibk_guest_interrupt()
432 if ((dev_data->handled % 1000) == 0) { in xen_pcibk_guest_interrupt()
434 dev_info(&dev->dev, "%s IRQ line is not shared " in xen_pcibk_guest_interrupt()
436 dev_data->irq_name); in xen_pcibk_guest_interrupt()
437 dev_data->ack_intr = 0; in xen_pcibk_guest_interrupt()