130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk/* 230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * PCI Backend Operations - respond to PCI requests from Frontend 330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * 430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * Author: Ryan Wilson <hap9@epoch.ncsc.mil> 530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <linux/module.h> 730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <linux/wait.h> 830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <linux/bitops.h> 930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <xen/events.h> 1030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include <linux/sched.h> 1130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#include "pciback.h" 1230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 1330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkint verbose_request; 1430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilkmodule_param(verbose_request, int, 0644); 1530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 16a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic irqreturn_t xen_pcibk_guest_interrupt(int irq, void *dev_id); 17a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 180513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk/* Ensure a device is has the fake IRQ handler "turned on/off" and is 19a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk * ready to be exported. This MUST be run after xen_pcibk_reset_device 200513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk * which does the actual PCI device enable/disable. 210513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk */ 22a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic void xen_pcibk_control_isr(struct pci_dev *dev, int reset) 230513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk{ 24a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_dev_data *dev_data; 250513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk int rc; 260513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk int enable = 0; 270513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk 280513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data = pci_get_drvdata(dev); 290513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if (!dev_data) 300513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk return; 310513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk 320513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk /* We don't deal with bridges */ 330513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) 340513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk return; 350513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk 360513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if (reset) { 370513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->enable_intx = 0; 380513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->ack_intr = 0; 390513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk } 400513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk enable = dev_data->enable_intx; 410513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk 420513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk /* Asked to disable, but ISR isn't runnig */ 430513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if (!enable && !dev_data->isr_on) 440513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk return; 450513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk 460513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk /* Squirrel away the IRQs in the dev_data. We need this 470513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk * b/c when device transitions to MSI, the dev->irq is 480513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk * overwritten with the MSI vector. 490513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk */ 500513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if (enable) 510513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->irq = dev->irq; 520513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk 53e17ab35f05cb8b3d19c70454a41ea67207caf484Konrad Rzeszutek Wilk /* 54e17ab35f05cb8b3d19c70454a41ea67207caf484Konrad Rzeszutek Wilk * SR-IOV devices in all use MSI-X and have no legacy 55e17ab35f05cb8b3d19c70454a41ea67207caf484Konrad Rzeszutek Wilk * interrupts, so inhibit creating a fake IRQ handler for them. 56e17ab35f05cb8b3d19c70454a41ea67207caf484Konrad Rzeszutek Wilk */ 57e17ab35f05cb8b3d19c70454a41ea67207caf484Konrad Rzeszutek Wilk if (dev_data->irq == 0) 58e17ab35f05cb8b3d19c70454a41ea67207caf484Konrad Rzeszutek Wilk goto out; 59e17ab35f05cb8b3d19c70454a41ea67207caf484Konrad Rzeszutek Wilk 600513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_dbg(&dev->dev, "%s: #%d %s %s%s %s-> %s\n", 610513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->irq_name, 620513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->irq, 630513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk pci_is_enabled(dev) ? "on" : "off", 640513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev->msi_enabled ? "MSI" : "", 650513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev->msix_enabled ? "MSI/X" : "", 660513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->isr_on ? "enable" : "disable", 670513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk enable ? "enable" : "disable"); 680513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk 690513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if (enable) { 700513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk rc = request_irq(dev_data->irq, 71a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_guest_interrupt, IRQF_SHARED, 720513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->irq_name, dev); 730513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if (rc) { 740513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_err(&dev->dev, "%s: failed to install fake IRQ " \ 750513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk "handler for IRQ %d! (rc:%d)\n", 760513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->irq_name, dev_data->irq, rc); 770513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk goto out; 780513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk } 790513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk } else { 800513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk free_irq(dev_data->irq, dev); 810513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->irq = 0; 820513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk } 830513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->isr_on = enable; 840513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->ack_intr = enable; 850513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilkout: 860513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_dbg(&dev->dev, "%s: #%d %s %s%s %s\n", 870513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->irq_name, 880513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->irq, 890513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk pci_is_enabled(dev) ? "on" : "off", 900513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev->msi_enabled ? "MSI" : "", 910513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev->msix_enabled ? "MSI/X" : "", 920513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk enable ? (dev_data->isr_on ? "enabled" : "failed to enable") : 930513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk (dev_data->isr_on ? "failed to disable" : "disabled")); 940513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk} 950513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk 9630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk/* Ensure a device is "turned off" and ready to be exported. 97a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk * (Also see xen_pcibk_config_reset to ensure virtual configuration space is 9830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * ready to be re-exported) 9930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 100a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkvoid xen_pcibk_reset_device(struct pci_dev *dev) 10130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 10230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk u16 cmd; 10330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 104a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_control_isr(dev, 1 /* reset device */); 1050513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk 10630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Disable devices (but not bridges) */ 10730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) { 108a2be65fd363831502afdf0babdf48149b3959cdeKonrad Rzeszutek Wilk#ifdef CONFIG_PCI_MSI 109a2be65fd363831502afdf0babdf48149b3959cdeKonrad Rzeszutek Wilk /* The guest could have been abruptly killed without 110a2be65fd363831502afdf0babdf48149b3959cdeKonrad Rzeszutek Wilk * disabling MSI/MSI-X interrupts.*/ 111a2be65fd363831502afdf0babdf48149b3959cdeKonrad Rzeszutek Wilk if (dev->msix_enabled) 112a2be65fd363831502afdf0babdf48149b3959cdeKonrad Rzeszutek Wilk pci_disable_msix(dev); 113a2be65fd363831502afdf0babdf48149b3959cdeKonrad Rzeszutek Wilk if (dev->msi_enabled) 114a2be65fd363831502afdf0babdf48149b3959cdeKonrad Rzeszutek Wilk pci_disable_msi(dev); 115a2be65fd363831502afdf0babdf48149b3959cdeKonrad Rzeszutek Wilk#endif 11630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pci_disable_device(dev); 11730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 11830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pci_write_config_word(dev, PCI_COMMAND, 0); 11930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 12030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev->is_busmaster = 0; 12130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } else { 12230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pci_read_config_word(dev, PCI_COMMAND, &cmd); 12330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (cmd & (PCI_COMMAND_INVALIDATE)) { 12430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk cmd &= ~(PCI_COMMAND_INVALIDATE); 12530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk pci_write_config_word(dev, PCI_COMMAND, cmd); 12630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 12730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk dev->is_busmaster = 0; 12830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 12930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 13030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 131a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 132a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk#ifdef CONFIG_PCI_MSI 133a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic 134a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_enable_msi(struct xen_pcibk_device *pdev, 135a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct pci_dev *dev, struct xen_pci_op *op) 136a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk{ 137a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_dev_data *dev_data; 138a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk int otherend = pdev->xdev->otherend_id; 139a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk int status; 140a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 141a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (unlikely(verbose_request)) 142a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk printk(KERN_DEBUG DRV_NAME ": %s: enable MSI\n", pci_name(dev)); 143a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 144a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk status = pci_enable_msi(dev); 145a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 146a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (status) { 147a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk printk(KERN_ERR "error enable msi for guest %x status %x\n", 148a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk otherend, status); 149a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->value = 0; 150a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk return XEN_PCI_ERR_op_failed; 151a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk } 152a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 153a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk /* The value the guest needs is actually the IDT vector, not the 154a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk * the local domain's IRQ number. */ 155a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 156a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; 157a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (unlikely(verbose_request)) 158a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk printk(KERN_DEBUG DRV_NAME ": %s: MSI: %d\n", pci_name(dev), 159a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->value); 160a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 161a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk dev_data = pci_get_drvdata(dev); 162a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (dev_data) 163a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk dev_data->ack_intr = 0; 164a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 165a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk return 0; 166a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk} 167a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 168a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic 169a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_disable_msi(struct xen_pcibk_device *pdev, 170a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct pci_dev *dev, struct xen_pci_op *op) 171a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk{ 172a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_dev_data *dev_data; 173a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 174a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (unlikely(verbose_request)) 175a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk printk(KERN_DEBUG DRV_NAME ": %s: disable MSI\n", 176a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk pci_name(dev)); 177a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk pci_disable_msi(dev); 178a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 179a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; 180a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (unlikely(verbose_request)) 181a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk printk(KERN_DEBUG DRV_NAME ": %s: MSI: %d\n", pci_name(dev), 182a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->value); 183a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk dev_data = pci_get_drvdata(dev); 184a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (dev_data) 185a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk dev_data->ack_intr = 1; 186a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk return 0; 187a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk} 188a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 189a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic 190a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, 191a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct pci_dev *dev, struct xen_pci_op *op) 192a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk{ 193a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_dev_data *dev_data; 194a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk int i, result; 195a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct msix_entry *entries; 196a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 197a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (unlikely(verbose_request)) 198a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk printk(KERN_DEBUG DRV_NAME ": %s: enable MSI-X\n", 199a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk pci_name(dev)); 200a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (op->value > SH_INFO_MAX_VEC) 201a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk return -EINVAL; 202a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 203a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL); 204a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (entries == NULL) 205a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk return -ENOMEM; 206a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 207a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk for (i = 0; i < op->value; i++) { 208a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk entries[i].entry = op->msix_entries[i].entry; 209a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk entries[i].vector = op->msix_entries[i].vector; 210a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk } 211a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 212a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk result = pci_enable_msix(dev, entries, op->value); 213a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 214a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (result == 0) { 215a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk for (i = 0; i < op->value; i++) { 216a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->msix_entries[i].entry = entries[i].entry; 217a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (entries[i].vector) 218a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->msix_entries[i].vector = 219a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pirq_from_irq(entries[i].vector); 220a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (unlikely(verbose_request)) 221a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk printk(KERN_DEBUG DRV_NAME ": %s: " \ 222a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk "MSI-X[%d]: %d\n", 223a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk pci_name(dev), i, 224a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->msix_entries[i].vector); 225a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk } 226a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk } else { 227a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk printk(KERN_WARNING DRV_NAME ": %s: failed to enable MSI-X: err %d!\n", 228a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk pci_name(dev), result); 229a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk } 230a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk kfree(entries); 231a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 232a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->value = result; 233a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk dev_data = pci_get_drvdata(dev); 234a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (dev_data) 235a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk dev_data->ack_intr = 0; 236a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 2370ee46eca0476faf0e93c1387b1597b861b79711fJan Beulich return result > 0 ? 0 : result; 238a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk} 239a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 240a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic 241a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkint xen_pcibk_disable_msix(struct xen_pcibk_device *pdev, 242a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct pci_dev *dev, struct xen_pci_op *op) 243a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk{ 244a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_dev_data *dev_data; 245a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (unlikely(verbose_request)) 246a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk printk(KERN_DEBUG DRV_NAME ": %s: disable MSI-X\n", 247a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk pci_name(dev)); 248a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk pci_disable_msix(dev); 249a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk 250a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk /* 251a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk * SR-IOV devices (which don't have any legacy IRQ) have 252a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk * an undefined IRQ value of zero. 253a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk */ 254a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; 255a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (unlikely(verbose_request)) 256a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk printk(KERN_DEBUG DRV_NAME ": %s: MSI-X: %d\n", pci_name(dev), 257a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->value); 258a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk dev_data = pci_get_drvdata(dev); 259a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk if (dev_data) 260a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk dev_data->ack_intr = 1; 261a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk return 0; 262a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk} 263a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk#endif 26430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk/* 26530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk* Now the same evtchn is used for both pcifront conf_read_write request 26630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk* as well as pcie aer front end ack. We use a new work_queue to schedule 267a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk* xen_pcibk conf_read_write service for avoiding confict with aer_core 26830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk* do_recovery job which also use the system default work_queue 26930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk*/ 270a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkvoid xen_pcibk_test_and_schedule_op(struct xen_pcibk_device *pdev) 27130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 27230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Check that frontend is requesting an operation and that we are not 27330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * already processing a request */ 27430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (test_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags) 27530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk && !test_and_set_bit(_PDEVF_op_active, &pdev->flags)) { 276a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk queue_work(xen_pcibk_wq, &pdev->op_work); 27730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 27830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /*_XEN_PCIB_active should have been cleared by pcifront. And also make 279a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk sure xen_pcibk is waiting for ack by checking _PCIB_op_pending*/ 28030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (!test_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags) 28130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk && test_bit(_PCIB_op_pending, &pdev->flags)) { 282a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk wake_up(&xen_pcibk_aer_wait_queue); 28330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 28430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 28530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 28630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk/* Performing the configuration space reads/writes must not be done in atomic 28730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * context because some of the pci_* functions can sleep (mostly due to ACPI 28830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * use of semaphores). This function is intended to be called from a work 289a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk * queue in process context taking a struct xen_pcibk_device as a parameter */ 29030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 291a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkvoid xen_pcibk_do_op(struct work_struct *data) 29230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 293a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev = 294a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk container_of(data, struct xen_pcibk_device, op_work); 29530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk struct pci_dev *dev; 296a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_dev_data *dev_data = NULL; 29730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk struct xen_pci_op *op = &pdev->sh_info->op; 2980513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk int test_intx = 0; 29930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 300a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk dev = xen_pcibk_get_pci_dev(pdev, op->domain, op->bus, op->devfn); 30130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 30230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk if (dev == NULL) 30330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk op->err = XEN_PCI_ERR_dev_not_found; 30430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk else { 3050513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data = pci_get_drvdata(dev); 3060513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if (dev_data) 3070513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk test_intx = dev_data->enable_intx; 30830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk switch (op->cmd) { 30930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XEN_PCI_OP_conf_read: 310a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->err = xen_pcibk_config_read(dev, 31130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk op->offset, op->size, &op->value); 31230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 31330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XEN_PCI_OP_conf_write: 314a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->err = xen_pcibk_config_write(dev, 31530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk op->offset, op->size, op->value); 31630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 31730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#ifdef CONFIG_PCI_MSI 31830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XEN_PCI_OP_enable_msi: 319a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->err = xen_pcibk_enable_msi(pdev, dev, op); 32030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 32130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XEN_PCI_OP_disable_msi: 322a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->err = xen_pcibk_disable_msi(pdev, dev, op); 32330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 32430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XEN_PCI_OP_enable_msix: 325a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->err = xen_pcibk_enable_msix(pdev, dev, op); 32630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 32730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk case XEN_PCI_OP_disable_msix: 328a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk op->err = xen_pcibk_disable_msix(pdev, dev, op); 32930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 33030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk#endif 33130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk default: 33230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk op->err = XEN_PCI_ERR_not_implemented; 33330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk break; 33430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 33530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk } 3360513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if (!op->err && dev && dev_data) { 3370513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk /* Transition detected */ 3380513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if ((dev_data->enable_intx != test_intx)) 339a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_control_isr(dev, 0 /* no reset */); 3400513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk } 34130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Tell the driver domain that we're done. */ 34230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk wmb(); 34330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags); 34430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk notify_remote_via_irq(pdev->evtchn_irq); 34530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 34630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Mark that we're done. */ 34730edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk smp_mb__before_clear_bit(); /* /after/ clearing PCIF_active */ 34830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk clear_bit(_PDEVF_op_active, &pdev->flags); 34930edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk smp_mb__after_clear_bit(); /* /before/ final check for work */ 35030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 35130edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk /* Check to see if the driver domain tried to start another request in 35230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk * between clearing _XEN_PCIF_active and clearing _PDEVF_op_active. 35330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk */ 354a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_test_and_schedule_op(pdev); 35530edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 35630edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 357a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkirqreturn_t xen_pcibk_handle_event(int irq, void *dev_id) 35830edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk{ 359a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_device *pdev = dev_id; 36030edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 361a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk xen_pcibk_test_and_schedule_op(pdev); 36230edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk 36330edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk return IRQ_HANDLED; 36430edc14bf39afde24ef7db2de66c91805db80828Konrad Rzeszutek Wilk} 365a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilkstatic irqreturn_t xen_pcibk_guest_interrupt(int irq, void *dev_id) 3660513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk{ 3670513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk struct pci_dev *dev = (struct pci_dev *)dev_id; 368a92336a1176b2119eaa990a1e8bf3109665fdbc6Konrad Rzeszutek Wilk struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev); 3690513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk 3700513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if (dev_data->isr_on && dev_data->ack_intr) { 3710513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->handled++; 3720513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if ((dev_data->handled % 1000) == 0) { 3730513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk if (xen_test_irq_shared(irq)) { 3740513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk printk(KERN_INFO "%s IRQ line is not shared " 3750513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk "with other domains. Turning ISR off\n", 3760513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->irq_name); 3770513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk dev_data->ack_intr = 0; 3780513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk } 3790513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk } 3800513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk return IRQ_HANDLED; 3810513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk } 3820513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk return IRQ_NONE; 3830513fe9e5b54e47e37217ea078dd870e3825e02dKonrad Rzeszutek Wilk} 384