106 lines
3.2 KiB
Diff
106 lines
3.2 KiB
Diff
From 59a403750d3796b45376041a4843fcde436ae37e Mon Sep 17 00:00:00 2001
|
|
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
|
Date: Wed, 1 Apr 2015 10:49:47 -0400
|
|
Subject: [PATCH v2 XSA157 4/5] xen/pciback: For XEN_PCI_OP_disable_msi[|x]
|
|
only disable if device has MSI(X) enabled.
|
|
|
|
Otherwise just continue on, returning the same values as
|
|
previously (return of 0, and op->result has the PIRQ value).
|
|
|
|
This does not change the behavior of XEN_PCI_OP_disable_msi[|x].
|
|
|
|
The pci_disable_msi or pci_disable_msix have the checks for
|
|
msi_enabled or msix_enabled so they will error out immediately.
|
|
|
|
However the guest can still call these operations and cause
|
|
us to disable the 'ack_intr'. That means the backend IRQ handler
|
|
for the legacy interrupt will not respond to interrupts anymore.
|
|
|
|
This will lead to (if the device is causing an interrupt storm)
|
|
for the Linux generic code to disable the interrupt line.
|
|
|
|
Naturally this will only happen if the device in question
|
|
is plugged in on the motherboard on shared level interrupt GSI.
|
|
|
|
This is part of XSA-157
|
|
|
|
CC: stable@vger.kernel.org
|
|
Reviewed-by: David Vrabel <david.vrabel@citrix.com>
|
|
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
|
---
|
|
drivers/xen/xen-pciback/pciback_ops.c | 33 ++++++++++++++++++++-------------
|
|
1 file changed, 20 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c
|
|
index 5bb76c0..648c09c 100644
|
|
--- a/drivers/xen/xen-pciback/pciback_ops.c
|
|
+++ b/drivers/xen/xen-pciback/pciback_ops.c
|
|
@@ -185,20 +185,23 @@ static
|
|
int xen_pcibk_disable_msi(struct xen_pcibk_device *pdev,
|
|
struct pci_dev *dev, struct xen_pci_op *op)
|
|
{
|
|
- struct xen_pcibk_dev_data *dev_data;
|
|
-
|
|
if (unlikely(verbose_request))
|
|
printk(KERN_DEBUG DRV_NAME ": %s: disable MSI\n",
|
|
pci_name(dev));
|
|
- pci_disable_msi(dev);
|
|
|
|
+ if (dev->msi_enabled) {
|
|
+ struct xen_pcibk_dev_data *dev_data;
|
|
+
|
|
+ pci_disable_msi(dev);
|
|
+
|
|
+ dev_data = pci_get_drvdata(dev);
|
|
+ if (dev_data)
|
|
+ dev_data->ack_intr = 1;
|
|
+ }
|
|
op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
|
|
if (unlikely(verbose_request))
|
|
printk(KERN_DEBUG DRV_NAME ": %s: MSI: %d\n", pci_name(dev),
|
|
op->value);
|
|
- dev_data = pci_get_drvdata(dev);
|
|
- if (dev_data)
|
|
- dev_data->ack_intr = 1;
|
|
return 0;
|
|
}
|
|
|
|
@@ -264,23 +267,27 @@ static
|
|
int xen_pcibk_disable_msix(struct xen_pcibk_device *pdev,
|
|
struct pci_dev *dev, struct xen_pci_op *op)
|
|
{
|
|
- struct xen_pcibk_dev_data *dev_data;
|
|
if (unlikely(verbose_request))
|
|
printk(KERN_DEBUG DRV_NAME ": %s: disable MSI-X\n",
|
|
pci_name(dev));
|
|
- pci_disable_msix(dev);
|
|
|
|
+ if (dev->msix_enabled) {
|
|
+ struct xen_pcibk_dev_data *dev_data;
|
|
+
|
|
+ pci_disable_msix(dev);
|
|
+
|
|
+ dev_data = pci_get_drvdata(dev);
|
|
+ if (dev_data)
|
|
+ dev_data->ack_intr = 1;
|
|
+ }
|
|
/*
|
|
* SR-IOV devices (which don't have any legacy IRQ) have
|
|
* an undefined IRQ value of zero.
|
|
*/
|
|
op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
|
|
if (unlikely(verbose_request))
|
|
- printk(KERN_DEBUG DRV_NAME ": %s: MSI-X: %d\n", pci_name(dev),
|
|
- op->value);
|
|
- dev_data = pci_get_drvdata(dev);
|
|
- if (dev_data)
|
|
- dev_data->ack_intr = 1;
|
|
+ printk(KERN_DEBUG DRV_NAME ": %s: MSI-X: %d\n",
|
|
+ pci_name(dev), op->value);
|
|
return 0;
|
|
}
|
|
#endif
|
|
--
|
|
2.1.0
|
|
|