summaryrefslogtreecommitdiff
path: root/drivers/xen/xen-pciback/pci_stub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/xen-pciback/pci_stub.c')
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c299
1 files changed, 204 insertions, 95 deletions
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 6331a95691a4..045e74847fe6 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -6,6 +6,7 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define dev_fmt pr_fmt
#include <linux/module.h>
#include <linux/init.h>
@@ -18,7 +19,11 @@
#include <linux/sched.h>
#include <linux/atomic.h>
#include <xen/events.h>
-#include <asm/xen/pci.h>
+#include <xen/pci.h>
+#include <xen/xen.h>
+#ifdef CONFIG_XEN_ACPI
+#include <xen/acpi.h>
+#endif
#include <asm/xen/hypervisor.h>
#include <xen/interface/physdev.h>
#include "pciback.h"
@@ -51,6 +56,9 @@ struct pcistub_device {
struct pci_dev *dev;
struct xen_pcibk_device *pdev;/* non-NULL if struct pci_dev is in use */
+#ifdef CONFIG_XEN_ACPI
+ int gsi;
+#endif
};
/* Access to pcistub_devices & seized_devices lists and the initialize_devices
@@ -71,7 +79,7 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
dev_dbg(&dev->dev, "pcistub_device_alloc\n");
- psdev = kzalloc(sizeof(*psdev), GFP_ATOMIC);
+ psdev = kzalloc(sizeof(*psdev), GFP_KERNEL);
if (!psdev)
return NULL;
@@ -83,10 +91,23 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
kref_init(&psdev->kref);
spin_lock_init(&psdev->lock);
+#ifdef CONFIG_XEN_ACPI
+ psdev->gsi = -1;
+#endif
return psdev;
}
+static int pcistub_reset_device_state(struct pci_dev *dev)
+{
+ __pci_reset_function_locked(dev);
+
+ if (!xen_pv_domain())
+ return xen_reset_device(dev);
+ else
+ return 0;
+}
+
/* Don't call this directly as it's called by pcistub_device_put */
static void pcistub_device_release(struct kref *kref)
{
@@ -105,8 +126,9 @@ static void pcistub_device_release(struct kref *kref)
/* Call the reset function which does not take lock as this
* is called from "unbind" which takes a device_lock mutex.
*/
- __pci_reset_function_locked(dev);
- if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state))
+ pcistub_reset_device_state(dev);
+ if (dev_data &&
+ pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state))
dev_info(&dev->dev, "Could not reload PCI state\n");
else
pci_restore_state(dev);
@@ -191,8 +213,6 @@ static struct pci_dev *pcistub_device_get_pci_dev(struct xen_pcibk_device *pdev,
struct pci_dev *pci_dev = NULL;
unsigned long flags;
- pcistub_device_get(psdev);
-
spin_lock_irqsave(&psdev->lock, flags);
if (!psdev->pdev) {
psdev->pdev = pdev;
@@ -200,32 +220,33 @@ static struct pci_dev *pcistub_device_get_pci_dev(struct xen_pcibk_device *pdev,
}
spin_unlock_irqrestore(&psdev->lock, flags);
- if (!pci_dev)
- pcistub_device_put(psdev);
+ if (pci_dev)
+ pcistub_device_get(psdev);
return pci_dev;
}
-struct pci_dev *pcistub_get_pci_dev_by_slot(struct xen_pcibk_device *pdev,
- int domain, int bus,
- int slot, int func)
+#ifdef CONFIG_XEN_ACPI
+static int pcistub_get_gsi_from_sbdf(unsigned int sbdf)
{
struct pcistub_device *psdev;
- struct pci_dev *found_dev = NULL;
- unsigned long flags;
+ int domain = (sbdf >> 16) & 0xffff;
+ int bus = PCI_BUS_NUM(sbdf);
+ int slot = PCI_SLOT(sbdf);
+ int func = PCI_FUNC(sbdf);
- spin_lock_irqsave(&pcistub_devices_lock, flags);
+ psdev = pcistub_device_find(domain, bus, slot, func);
- psdev = pcistub_device_find_locked(domain, bus, slot, func);
- if (psdev)
- found_dev = pcistub_device_get_pci_dev(pdev, psdev);
+ if (!psdev)
+ return -ENODEV;
- spin_unlock_irqrestore(&pcistub_devices_lock, flags);
- return found_dev;
+ return psdev->gsi;
}
+#endif
-struct pci_dev *pcistub_get_pci_dev(struct xen_pcibk_device *pdev,
- struct pci_dev *dev)
+struct pci_dev *pcistub_get_pci_dev_by_slot(struct xen_pcibk_device *pdev,
+ int domain, int bus,
+ int slot, int func)
{
struct pcistub_device *psdev;
struct pci_dev *found_dev = NULL;
@@ -233,12 +254,9 @@ struct pci_dev *pcistub_get_pci_dev(struct xen_pcibk_device *pdev,
spin_lock_irqsave(&pcistub_devices_lock, flags);
- list_for_each_entry(psdev, &pcistub_devices, dev_list) {
- if (psdev->dev == dev) {
- found_dev = pcistub_device_get_pci_dev(pdev, psdev);
- break;
- }
- }
+ psdev = pcistub_device_find_locked(domain, bus, slot, func);
+ if (psdev)
+ found_dev = pcistub_device_get_pci_dev(pdev, psdev);
spin_unlock_irqrestore(&pcistub_devices_lock, flags);
return found_dev;
@@ -283,7 +301,7 @@ void pcistub_put_pci_dev(struct pci_dev *dev)
* (so it's ready for the next domain)
*/
device_lock_assert(&dev->dev);
- __pci_reset_function_locked(dev);
+ pcistub_reset_device_state(dev);
dev_data = pci_get_drvdata(dev);
ret = pci_load_saved_state(dev, dev_data->pci_saved_state);
@@ -303,6 +321,8 @@ void pcistub_put_pci_dev(struct pci_dev *dev)
xen_pcibk_config_reset_dev(dev);
xen_pcibk_config_free_dyn_fields(dev);
+ dev_data->allow_interrupt_control = 0;
+
xen_unregister_device_domain_owner(dev);
spin_lock_irqsave(&found_psdev->lock, flags);
@@ -351,11 +371,20 @@ static int pcistub_match(struct pci_dev *dev)
return found;
}
-static int pcistub_init_device(struct pci_dev *dev)
+static int pcistub_init_device(struct pcistub_device *psdev)
{
struct xen_pcibk_dev_data *dev_data;
+ struct pci_dev *dev;
+#ifdef CONFIG_XEN_ACPI
+ int gsi, trigger, polarity;
+#endif
int err = 0;
+ if (!psdev)
+ return -EINVAL;
+
+ dev = psdev->dev;
+
dev_dbg(&dev->dev, "initializing...\n");
/* The PCI backend is not intended to be a module (or to work with
@@ -364,7 +393,7 @@ static int pcistub_init_device(struct pci_dev *dev)
* here and then to call kfree(pci_get_drvdata(psdev->dev)).
*/
dev_data = kzalloc(sizeof(*dev_data) + strlen(DRV_NAME "[]")
- + strlen(pci_name(dev)) + 1, GFP_ATOMIC);
+ + strlen(pci_name(dev)) + 1, GFP_KERNEL);
if (!dev_data) {
err = -ENOMEM;
goto out;
@@ -417,9 +446,26 @@ static int pcistub_init_device(struct pci_dev *dev)
dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
else {
dev_dbg(&dev->dev, "resetting (FLR, D3, etc) the device\n");
- __pci_reset_function_locked(dev);
+ err = pcistub_reset_device_state(dev);
+ if (err)
+ goto config_release;
pci_restore_state(dev);
}
+
+#ifdef CONFIG_XEN_ACPI
+ if (xen_initial_domain() && xen_pvh_domain()) {
+ err = xen_acpi_get_gsi_info(dev, &gsi, &trigger, &polarity);
+ if (err) {
+ dev_err(&dev->dev, "Fail to get gsi info!\n");
+ goto config_release;
+ }
+ err = xen_pvh_setup_gsi(gsi, trigger, polarity);
+ if (err)
+ goto config_release;
+ psdev->gsi = gsi;
+ }
+#endif
+
/* Now disable the device (this also ensures some private device
* data is setup before we export)
*/
@@ -459,7 +505,7 @@ static int __init pcistub_init_devices_late(void)
spin_unlock_irqrestore(&pcistub_devices_lock, flags);
- err = pcistub_init_device(psdev->dev);
+ err = pcistub_init_device(psdev);
if (err) {
dev_err(&psdev->dev->dev,
"error %d initializing device\n", err);
@@ -529,7 +575,7 @@ static int pcistub_seize(struct pci_dev *dev,
spin_unlock_irqrestore(&pcistub_devices_lock, flags);
/* don't want irqs disabled when calling pcistub_init_device */
- err = pcistub_init_device(psdev->dev);
+ err = pcistub_init_device(psdev);
spin_lock_irqsave(&pcistub_devices_lock, flags);
@@ -577,7 +623,7 @@ static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id)
}
if (!match) {
- pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_ATOMIC);
+ pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
if (!pci_dev_id) {
err = -ENOMEM;
goto out;
@@ -623,11 +669,11 @@ static void pcistub_remove(struct pci_dev *dev)
if (found_psdev->pdev) {
int domid = xen_find_device_domain_owner(dev);
- pr_warn("****** removing device %s while still in-use by domain %d! ******\n",
+ dev_warn(&dev->dev, "****** removing device %s while still in-use by domain %d! ******\n",
pci_name(found_psdev->dev), domid);
- pr_warn("****** driver domain may still access this device's i/o resources!\n");
- pr_warn("****** shutdown driver domain before binding device\n");
- pr_warn("****** to other drivers or domains\n");
+ dev_warn(&dev->dev, "****** driver domain may still access this device's i/o resources!\n");
+ dev_warn(&dev->dev, "****** shutdown driver domain before binding device\n");
+ dev_warn(&dev->dev, "****** to other drivers or domains\n");
/* N.B. This ends up calling pcistub_put_pci_dev which ends up
* doing the FLR. */
@@ -708,14 +754,12 @@ static pci_ers_result_t common_process(struct pcistub_device *psdev,
ret = xen_pcibk_get_pcifront_dev(psdev->dev, psdev->pdev,
&aer_op->domain, &aer_op->bus, &aer_op->devfn);
if (!ret) {
- dev_err(&psdev->dev->dev,
- DRV_NAME ": failed to get pcifront device\n");
+ dev_err(&psdev->dev->dev, "failed to get pcifront device\n");
return PCI_ERS_RESULT_NONE;
}
wmb();
- dev_dbg(&psdev->dev->dev,
- DRV_NAME ": aer_op %x dom %x bus %x devfn %x\n",
+ dev_dbg(&psdev->dev->dev, "aer_op %x dom %x bus %x devfn %x\n",
aer_cmd, aer_op->domain, aer_op->bus, aer_op->devfn);
/*local flag to mark there's aer request, xen_pcibk callback will use
* this flag to judge whether we need to check pci-front give aer
@@ -732,10 +776,17 @@ static pci_ers_result_t common_process(struct pcistub_device *psdev,
wmb();
notify_remote_via_irq(pdev->evtchn_irq);
+ /* Enable IRQ to signal "request done". */
+ xen_pcibk_lateeoi(pdev, 0);
+
ret = wait_event_timeout(xen_pcibk_aer_wait_queue,
!(test_bit(_XEN_PCIB_active, (unsigned long *)
&sh_info->flags)), 300*HZ);
+ /* Enable IRQ for pcifront request if not already active. */
+ if (!test_bit(_PDEVF_op_active, &pdev->flags))
+ xen_pcibk_lateeoi(pdev, 0);
+
if (!ret) {
if (test_bit(_XEN_PCIB_active,
(unsigned long *)&sh_info->flags)) {
@@ -749,14 +800,7 @@ static pci_ers_result_t common_process(struct pcistub_device *psdev,
}
clear_bit(_PCIB_op_pending, (unsigned long *)&pdev->flags);
- if (test_bit(_XEN_PCIF_active,
- (unsigned long *)&sh_info->flags)) {
- dev_dbg(&psdev->dev->dev,
- "schedule pci_conf service in " DRV_NAME "\n");
- xen_pcibk_test_and_schedule_op(psdev->pdev);
- }
-
- res = (pci_ers_result_t)aer_op->err;
+ res = (__force pci_ers_result_t)aer_op->err;
return res;
}
@@ -783,13 +827,12 @@ static pci_ers_result_t xen_pcibk_slot_reset(struct pci_dev *dev)
PCI_FUNC(dev->devfn));
if (!psdev || !psdev->pdev) {
- dev_err(&dev->dev,
- DRV_NAME " device is not found/assigned\n");
+ dev_err(&dev->dev, "device is not found/assigned\n");
goto end;
}
if (!psdev->pdev->sh_info) {
- dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
+ dev_err(&dev->dev, "device is not connected or owned"
" by HVM, kill it\n");
kill_domain_by_device(psdev);
goto end;
@@ -801,7 +844,7 @@ static pci_ers_result_t xen_pcibk_slot_reset(struct pci_dev *dev)
"guest with no AER driver should have been killed\n");
goto end;
}
- result = common_process(psdev, 1, XEN_PCI_OP_aer_slotreset, result);
+ result = common_process(psdev, pci_channel_io_normal, XEN_PCI_OP_aer_slotreset, result);
if (result == PCI_ERS_RESULT_NONE ||
result == PCI_ERS_RESULT_DISCONNECT) {
@@ -841,13 +884,12 @@ static pci_ers_result_t xen_pcibk_mmio_enabled(struct pci_dev *dev)
PCI_FUNC(dev->devfn));
if (!psdev || !psdev->pdev) {
- dev_err(&dev->dev,
- DRV_NAME " device is not found/assigned\n");
+ dev_err(&dev->dev, "device is not found/assigned\n");
goto end;
}
if (!psdev->pdev->sh_info) {
- dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
+ dev_err(&dev->dev, "device is not connected or owned"
" by HVM, kill it\n");
kill_domain_by_device(psdev);
goto end;
@@ -859,7 +901,7 @@ static pci_ers_result_t xen_pcibk_mmio_enabled(struct pci_dev *dev)
"guest with no AER driver should have been killed\n");
goto end;
}
- result = common_process(psdev, 1, XEN_PCI_OP_aer_mmio, result);
+ result = common_process(psdev, pci_channel_io_normal, XEN_PCI_OP_aer_mmio, result);
if (result == PCI_ERS_RESULT_NONE ||
result == PCI_ERS_RESULT_DISCONNECT) {
@@ -899,13 +941,12 @@ static pci_ers_result_t xen_pcibk_error_detected(struct pci_dev *dev,
PCI_FUNC(dev->devfn));
if (!psdev || !psdev->pdev) {
- dev_err(&dev->dev,
- DRV_NAME " device is not found/assigned\n");
+ dev_err(&dev->dev, "device is not found/assigned\n");
goto end;
}
if (!psdev->pdev->sh_info) {
- dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
+ dev_err(&dev->dev, "device is not connected or owned"
" by HVM, kill it\n");
kill_domain_by_device(psdev);
goto end;
@@ -953,13 +994,12 @@ static void xen_pcibk_error_resume(struct pci_dev *dev)
PCI_FUNC(dev->devfn));
if (!psdev || !psdev->pdev) {
- dev_err(&dev->dev,
- DRV_NAME " device is not found/assigned\n");
+ dev_err(&dev->dev, "device is not found/assigned\n");
goto end;
}
if (!psdev->pdev->sh_info) {
- dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
+ dev_err(&dev->dev, "device is not connected or owned"
" by HVM, kill it\n");
kill_domain_by_device(psdev);
goto end;
@@ -972,7 +1012,7 @@ static void xen_pcibk_error_resume(struct pci_dev *dev)
kill_domain_by_device(psdev);
goto end;
}
- common_process(psdev, 1, XEN_PCI_OP_aer_resume,
+ common_process(psdev, pci_channel_io_normal, XEN_PCI_OP_aer_resume,
PCI_ERS_RESULT_RECOVERED);
end:
if (psdev)
@@ -1149,7 +1189,7 @@ static int pcistub_reg_add(int domain, int bus, int slot, int func,
}
dev = psdev->dev;
- field = kzalloc(sizeof(*field), GFP_ATOMIC);
+ field = kzalloc(sizeof(*field), GFP_KERNEL);
if (!field) {
err = -ENOMEM;
goto out;
@@ -1172,8 +1212,8 @@ out:
return err;
}
-static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
- size_t count)
+static ssize_t new_slot_store(struct device_driver *drv, const char *buf,
+ size_t count)
{
int domain, bus, slot, func;
int err;
@@ -1189,10 +1229,10 @@ out:
err = count;
return err;
}
-static DRIVER_ATTR(new_slot, S_IWUSR, NULL, pcistub_slot_add);
+static DRIVER_ATTR_WO(new_slot);
-static ssize_t pcistub_slot_remove(struct device_driver *drv, const char *buf,
- size_t count)
+static ssize_t remove_slot_store(struct device_driver *drv, const char *buf,
+ size_t count)
{
int domain, bus, slot, func;
int err;
@@ -1208,9 +1248,9 @@ out:
err = count;
return err;
}
-static DRIVER_ATTR(remove_slot, S_IWUSR, NULL, pcistub_slot_remove);
+static DRIVER_ATTR_WO(remove_slot);
-static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf)
+static ssize_t slots_show(struct device_driver *drv, char *buf)
{
struct pcistub_device_id *pci_dev_id;
size_t count = 0;
@@ -1221,7 +1261,7 @@ static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf)
if (count >= PAGE_SIZE)
break;
- count += scnprintf(buf + count, PAGE_SIZE - count,
+ count += sysfs_emit_at(buf, count,
"%04x:%02x:%02x.%d\n",
pci_dev_id->domain, pci_dev_id->bus,
PCI_SLOT(pci_dev_id->devfn),
@@ -1231,9 +1271,9 @@ static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf)
return count;
}
-static DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);
+static DRIVER_ATTR_RO(slots);
-static ssize_t pcistub_irq_handler_show(struct device_driver *drv, char *buf)
+static ssize_t irq_handlers_show(struct device_driver *drv, char *buf)
{
struct pcistub_device *psdev;
struct xen_pcibk_dev_data *dev_data;
@@ -1250,7 +1290,7 @@ static ssize_t pcistub_irq_handler_show(struct device_driver *drv, char *buf)
if (!dev_data)
continue;
count +=
- scnprintf(buf + count, PAGE_SIZE - count,
+ sysfs_emit_at(buf, count,
"%s:%s:%sing:%ld\n",
pci_name(psdev->dev),
dev_data->isr_on ? "on" : "off",
@@ -1260,11 +1300,10 @@ static ssize_t pcistub_irq_handler_show(struct device_driver *drv, char *buf)
spin_unlock_irqrestore(&pcistub_devices_lock, flags);
return count;
}
-static DRIVER_ATTR(irq_handlers, S_IRUSR, pcistub_irq_handler_show, NULL);
+static DRIVER_ATTR_RO(irq_handlers);
-static ssize_t pcistub_irq_handler_switch(struct device_driver *drv,
- const char *buf,
- size_t count)
+static ssize_t irq_handler_state_store(struct device_driver *drv,
+ const char *buf, size_t count)
{
struct pcistub_device *psdev;
struct xen_pcibk_dev_data *dev_data;
@@ -1301,11 +1340,10 @@ out:
err = count;
return err;
}
-static DRIVER_ATTR(irq_handler_state, S_IWUSR, NULL,
- pcistub_irq_handler_switch);
+static DRIVER_ATTR_WO(irq_handler_state);
-static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf,
- size_t count)
+static ssize_t quirks_store(struct device_driver *drv, const char *buf,
+ size_t count)
{
int domain, bus, slot, func, reg, size, mask;
int err;
@@ -1323,7 +1361,7 @@ out:
return err;
}
-static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
+static ssize_t quirks_show(struct device_driver *drv, char *buf)
{
int count = 0;
unsigned long flags;
@@ -1337,7 +1375,7 @@ static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
if (count >= PAGE_SIZE)
goto out;
- count += scnprintf(buf + count, PAGE_SIZE - count,
+ count += sysfs_emit_at(buf, count,
"%02x:%02x.%01x\n\t%04x:%04x:%04x:%04x\n",
quirk->pdev->bus->number,
PCI_SLOT(quirk->pdev->devfn),
@@ -1353,7 +1391,7 @@ static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
if (count >= PAGE_SIZE)
goto out;
- count += scnprintf(buf + count, PAGE_SIZE - count,
+ count += sysfs_emit_at(buf, count,
"\t\t%08x:%01x:%08x\n",
cfg_entry->base_offset +
field->offset, field->size,
@@ -1366,11 +1404,10 @@ out:
return count;
}
-static DRIVER_ATTR(quirks, S_IRUSR | S_IWUSR, pcistub_quirk_show,
- pcistub_quirk_add);
+static DRIVER_ATTR_RW(quirks);
-static ssize_t permissive_add(struct device_driver *drv, const char *buf,
- size_t count)
+static ssize_t permissive_store(struct device_driver *drv, const char *buf,
+ size_t count)
{
int domain, bus, slot, func;
int err;
@@ -1425,14 +1462,72 @@ static ssize_t permissive_show(struct device_driver *drv, char *buf)
if (!dev_data || !dev_data->permissive)
continue;
count +=
- scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
+ sysfs_emit_at(buf, count, "%s\n",
+ pci_name(psdev->dev));
+ }
+ spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+ return count;
+}
+static DRIVER_ATTR_RW(permissive);
+
+static ssize_t allow_interrupt_control_store(struct device_driver *drv,
+ const char *buf, size_t count)
+{
+ int domain, bus, slot, func;
+ int err;
+ struct pcistub_device *psdev;
+ struct xen_pcibk_dev_data *dev_data;
+
+ err = str_to_slot(buf, &domain, &bus, &slot, &func);
+ if (err)
+ goto out;
+
+ psdev = pcistub_device_find(domain, bus, slot, func);
+ if (!psdev) {
+ err = -ENODEV;
+ goto out;
+ }
+
+ dev_data = pci_get_drvdata(psdev->dev);
+ /* the driver data for a device should never be null at this point */
+ if (!dev_data) {
+ err = -ENXIO;
+ goto release;
+ }
+ dev_data->allow_interrupt_control = 1;
+release:
+ pcistub_device_put(psdev);
+out:
+ if (!err)
+ err = count;
+ return err;
+}
+
+static ssize_t allow_interrupt_control_show(struct device_driver *drv,
+ char *buf)
+{
+ struct pcistub_device *psdev;
+ struct xen_pcibk_dev_data *dev_data;
+ size_t count = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pcistub_devices_lock, flags);
+ list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+ if (count >= PAGE_SIZE)
+ break;
+ if (!psdev->dev)
+ continue;
+ dev_data = pci_get_drvdata(psdev->dev);
+ if (!dev_data || !dev_data->allow_interrupt_control)
+ continue;
+ count +=
+ sysfs_emit_at(buf, count, "%s\n",
pci_name(psdev->dev));
}
spin_unlock_irqrestore(&pcistub_devices_lock, flags);
return count;
}
-static DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show,
- permissive_add);
+static DRIVER_ATTR_RW(allow_interrupt_control);
static void pcistub_exit(void)
{
@@ -1444,6 +1539,8 @@ static void pcistub_exit(void)
driver_remove_file(&xen_pcibk_pci_driver.driver,
&driver_attr_permissive);
driver_remove_file(&xen_pcibk_pci_driver.driver,
+ &driver_attr_allow_interrupt_control);
+ driver_remove_file(&xen_pcibk_pci_driver.driver,
&driver_attr_irq_handlers);
driver_remove_file(&xen_pcibk_pci_driver.driver,
&driver_attr_irq_handler_state);
@@ -1533,6 +1630,9 @@ static int __init pcistub_init(void)
if (!err)
err = driver_create_file(&xen_pcibk_pci_driver.driver,
&driver_attr_permissive);
+ if (!err)
+ err = driver_create_file(&xen_pcibk_pci_driver.driver,
+ &driver_attr_allow_interrupt_control);
if (!err)
err = driver_create_file(&xen_pcibk_pci_driver.driver,
@@ -1636,11 +1736,19 @@ static int __init xen_pcibk_init(void)
bus_register_notifier(&pci_bus_type, &pci_stub_nb);
#endif
+#ifdef CONFIG_XEN_ACPI
+ xen_acpi_register_get_gsi_func(pcistub_get_gsi_from_sbdf);
+#endif
+
return err;
}
static void __exit xen_pcibk_cleanup(void)
{
+#ifdef CONFIG_XEN_ACPI
+ xen_acpi_register_get_gsi_func(NULL);
+#endif
+
#ifdef CONFIG_PCI_IOV
bus_unregister_notifier(&pci_bus_type, &pci_stub_nb);
#endif
@@ -1651,5 +1759,6 @@ static void __exit xen_pcibk_cleanup(void)
module_init(xen_pcibk_init);
module_exit(xen_pcibk_cleanup);
+MODULE_DESCRIPTION("Xen PCI-device stub driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("xen-backend:pci");