diff options
Diffstat (limited to 'drivers/xen/xen-pciback')
-rw-r--r-- | drivers/xen/xen-pciback/conf_space_capability_msi.c | 17 | ||||
-rw-r--r-- | drivers/xen/xen-pciback/conf_space_header.c | 6 | ||||
-rw-r--r-- | drivers/xen/xen-pciback/pci_stub.c | 90 | ||||
-rw-r--r-- | drivers/xen/xen-pciback/pciback.h | 13 | ||||
-rw-r--r-- | drivers/xen/xen-pciback/pciback_ops.c | 102 |
5 files changed, 223 insertions, 5 deletions
diff --git a/drivers/xen/xen-pciback/conf_space_capability_msi.c b/drivers/xen/xen-pciback/conf_space_capability_msi.c index 78f74b1852d4..d0d2255b5da9 100644 --- a/drivers/xen/xen-pciback/conf_space_capability_msi.c +++ b/drivers/xen/xen-pciback/conf_space_capability_msi.c | |||
@@ -12,6 +12,7 @@ | |||
12 | int pciback_enable_msi(struct pciback_device *pdev, | 12 | int pciback_enable_msi(struct pciback_device *pdev, |
13 | struct pci_dev *dev, struct xen_pci_op *op) | 13 | struct pci_dev *dev, struct xen_pci_op *op) |
14 | { | 14 | { |
15 | struct pciback_dev_data *dev_data; | ||
15 | int otherend = pdev->xdev->otherend_id; | 16 | int otherend = pdev->xdev->otherend_id; |
16 | int status; | 17 | int status; |
17 | 18 | ||
@@ -28,21 +29,29 @@ int pciback_enable_msi(struct pciback_device *pdev, | |||
28 | * the local domain's IRQ number. */ | 29 | * the local domain's IRQ number. */ |
29 | 30 | ||
30 | op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; | 31 | op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; |
32 | dev_data = pci_get_drvdata(dev); | ||
33 | if (dev_data) | ||
34 | dev_data->ack_intr = 0; | ||
31 | return 0; | 35 | return 0; |
32 | } | 36 | } |
33 | 37 | ||
34 | int pciback_disable_msi(struct pciback_device *pdev, | 38 | int pciback_disable_msi(struct pciback_device *pdev, |
35 | struct pci_dev *dev, struct xen_pci_op *op) | 39 | struct pci_dev *dev, struct xen_pci_op *op) |
36 | { | 40 | { |
41 | struct pciback_dev_data *dev_data; | ||
37 | pci_disable_msi(dev); | 42 | pci_disable_msi(dev); |
38 | 43 | ||
39 | op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; | 44 | op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; |
45 | dev_data = pci_get_drvdata(dev); | ||
46 | if (dev_data) | ||
47 | dev_data->ack_intr = 1; | ||
40 | return 0; | 48 | return 0; |
41 | } | 49 | } |
42 | 50 | ||
43 | int pciback_enable_msix(struct pciback_device *pdev, | 51 | int pciback_enable_msix(struct pciback_device *pdev, |
44 | struct pci_dev *dev, struct xen_pci_op *op) | 52 | struct pci_dev *dev, struct xen_pci_op *op) |
45 | { | 53 | { |
54 | struct pciback_dev_data *dev_data; | ||
46 | int i, result; | 55 | int i, result; |
47 | struct msix_entry *entries; | 56 | struct msix_entry *entries; |
48 | 57 | ||
@@ -74,6 +83,9 @@ int pciback_enable_msix(struct pciback_device *pdev, | |||
74 | kfree(entries); | 83 | kfree(entries); |
75 | 84 | ||
76 | op->value = result; | 85 | op->value = result; |
86 | dev_data = pci_get_drvdata(dev); | ||
87 | if (dev_data) | ||
88 | dev_data->ack_intr = 0; | ||
77 | 89 | ||
78 | return result; | 90 | return result; |
79 | } | 91 | } |
@@ -81,6 +93,7 @@ int pciback_enable_msix(struct pciback_device *pdev, | |||
81 | int pciback_disable_msix(struct pciback_device *pdev, | 93 | int pciback_disable_msix(struct pciback_device *pdev, |
82 | struct pci_dev *dev, struct xen_pci_op *op) | 94 | struct pci_dev *dev, struct xen_pci_op *op) |
83 | { | 95 | { |
96 | struct pciback_dev_data *dev_data; | ||
84 | 97 | ||
85 | pci_disable_msix(dev); | 98 | pci_disable_msix(dev); |
86 | 99 | ||
@@ -89,6 +102,10 @@ int pciback_disable_msix(struct pciback_device *pdev, | |||
89 | * an undefined IRQ value of zero. | 102 | * an undefined IRQ value of zero. |
90 | */ | 103 | */ |
91 | op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; | 104 | op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; |
105 | dev_data = pci_get_drvdata(dev); | ||
106 | if (dev_data) | ||
107 | dev_data->ack_intr = 1; | ||
108 | |||
92 | return 0; | 109 | return 0; |
93 | } | 110 | } |
94 | 111 | ||
diff --git a/drivers/xen/xen-pciback/conf_space_header.c b/drivers/xen/xen-pciback/conf_space_header.c index dcd6dd964e3b..22ad0f560669 100644 --- a/drivers/xen/xen-pciback/conf_space_header.c +++ b/drivers/xen/xen-pciback/conf_space_header.c | |||
@@ -39,8 +39,10 @@ static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data) | |||
39 | 39 | ||
40 | static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) | 40 | static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) |
41 | { | 41 | { |
42 | struct pciback_dev_data *dev_data; | ||
42 | int err; | 43 | int err; |
43 | 44 | ||
45 | dev_data = pci_get_drvdata(dev); | ||
44 | if (!pci_is_enabled(dev) && is_enable_cmd(value)) { | 46 | if (!pci_is_enabled(dev) && is_enable_cmd(value)) { |
45 | if (unlikely(verbose_request)) | 47 | if (unlikely(verbose_request)) |
46 | printk(KERN_DEBUG "pciback: %s: enable\n", | 48 | printk(KERN_DEBUG "pciback: %s: enable\n", |
@@ -48,11 +50,15 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) | |||
48 | err = pci_enable_device(dev); | 50 | err = pci_enable_device(dev); |
49 | if (err) | 51 | if (err) |
50 | return err; | 52 | return err; |
53 | if (dev_data) | ||
54 | dev_data->enable_intx = 1; | ||
51 | } else if (pci_is_enabled(dev) && !is_enable_cmd(value)) { | 55 | } else if (pci_is_enabled(dev) && !is_enable_cmd(value)) { |
52 | if (unlikely(verbose_request)) | 56 | if (unlikely(verbose_request)) |
53 | printk(KERN_DEBUG "pciback: %s: disable\n", | 57 | printk(KERN_DEBUG "pciback: %s: disable\n", |
54 | pci_name(dev)); | 58 | pci_name(dev)); |
55 | pci_disable_device(dev); | 59 | pci_disable_device(dev); |
60 | if (dev_data) | ||
61 | dev_data->enable_intx = 0; | ||
56 | } | 62 | } |
57 | 63 | ||
58 | if (!dev->is_busmaster && is_master_cmd(value)) { | 64 | if (!dev->is_busmaster && is_master_cmd(value)) { |
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index ac8396d8206b..c4d1071ebbe6 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include "conf_space.h" | 21 | #include "conf_space.h" |
22 | #include "conf_space_quirks.h" | 22 | #include "conf_space_quirks.h" |
23 | 23 | ||
24 | #define DRV_NAME "pciback" | ||
25 | |||
24 | static char *pci_devs_to_hide; | 26 | static char *pci_devs_to_hide; |
25 | wait_queue_head_t aer_wait_queue; | 27 | wait_queue_head_t aer_wait_queue; |
26 | /*Add sem for sync AER handling and pciback remove/reconfigue ops, | 28 | /*Add sem for sync AER handling and pciback remove/reconfigue ops, |
@@ -290,13 +292,20 @@ static int __devinit pcistub_init_device(struct pci_dev *dev) | |||
290 | * would need to be called somewhere to free the memory allocated | 292 | * would need to be called somewhere to free the memory allocated |
291 | * here and then to call kfree(pci_get_drvdata(psdev->dev)). | 293 | * here and then to call kfree(pci_get_drvdata(psdev->dev)). |
292 | */ | 294 | */ |
293 | dev_data = kzalloc(sizeof(*dev_data), GFP_ATOMIC); | 295 | dev_data = kzalloc(sizeof(*dev_data) + strlen(DRV_NAME "[]") |
296 | + strlen(pci_name(dev)) + 1, GFP_ATOMIC); | ||
294 | if (!dev_data) { | 297 | if (!dev_data) { |
295 | err = -ENOMEM; | 298 | err = -ENOMEM; |
296 | goto out; | 299 | goto out; |
297 | } | 300 | } |
298 | pci_set_drvdata(dev, dev_data); | 301 | pci_set_drvdata(dev, dev_data); |
299 | 302 | ||
303 | /* | ||
304 | * Setup name for fake IRQ handler. It will only be enabled | ||
305 | * once the device is turned on by the guest. | ||
306 | */ | ||
307 | sprintf(dev_data->irq_name, DRV_NAME "[%s]", pci_name(dev)); | ||
308 | |||
300 | dev_dbg(&dev->dev, "initializing config\n"); | 309 | dev_dbg(&dev->dev, "initializing config\n"); |
301 | 310 | ||
302 | init_waitqueue_head(&aer_wait_queue); | 311 | init_waitqueue_head(&aer_wait_queue); |
@@ -837,7 +846,7 @@ static struct pci_error_handlers pciback_error_handler = { | |||
837 | */ | 846 | */ |
838 | 847 | ||
839 | static struct pci_driver pciback_pci_driver = { | 848 | static struct pci_driver pciback_pci_driver = { |
840 | .name = "pciback", | 849 | .name = DRV_NAME, |
841 | .id_table = pcistub_ids, | 850 | .id_table = pcistub_ids, |
842 | .probe = pcistub_probe, | 851 | .probe = pcistub_probe, |
843 | .remove = pcistub_remove, | 852 | .remove = pcistub_remove, |
@@ -1029,6 +1038,72 @@ static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf) | |||
1029 | 1038 | ||
1030 | DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL); | 1039 | DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL); |
1031 | 1040 | ||
1041 | static ssize_t pcistub_irq_handler_show(struct device_driver *drv, char *buf) | ||
1042 | { | ||
1043 | struct pcistub_device *psdev; | ||
1044 | struct pciback_dev_data *dev_data; | ||
1045 | size_t count = 0; | ||
1046 | unsigned long flags; | ||
1047 | |||
1048 | spin_lock_irqsave(&pcistub_devices_lock, flags); | ||
1049 | list_for_each_entry(psdev, &pcistub_devices, dev_list) { | ||
1050 | if (count >= PAGE_SIZE) | ||
1051 | break; | ||
1052 | if (!psdev->dev) | ||
1053 | continue; | ||
1054 | dev_data = pci_get_drvdata(psdev->dev); | ||
1055 | if (!dev_data) | ||
1056 | continue; | ||
1057 | count += | ||
1058 | scnprintf(buf + count, PAGE_SIZE - count, | ||
1059 | "%s:%s:%sing:%ld\n", | ||
1060 | pci_name(psdev->dev), | ||
1061 | dev_data->isr_on ? "on" : "off", | ||
1062 | dev_data->ack_intr ? "ack" : "not ack", | ||
1063 | dev_data->handled); | ||
1064 | } | ||
1065 | spin_unlock_irqrestore(&pcistub_devices_lock, flags); | ||
1066 | return count; | ||
1067 | } | ||
1068 | |||
1069 | DRIVER_ATTR(irq_handlers, S_IRUSR, pcistub_irq_handler_show, NULL); | ||
1070 | |||
1071 | static ssize_t pcistub_irq_handler_switch(struct device_driver *drv, | ||
1072 | const char *buf, | ||
1073 | size_t count) | ||
1074 | { | ||
1075 | struct pcistub_device *psdev; | ||
1076 | struct pciback_dev_data *dev_data; | ||
1077 | int domain, bus, slot, func; | ||
1078 | int err = -ENOENT; | ||
1079 | |||
1080 | err = str_to_slot(buf, &domain, &bus, &slot, &func); | ||
1081 | if (err) | ||
1082 | goto out; | ||
1083 | |||
1084 | psdev = pcistub_device_find(domain, bus, slot, func); | ||
1085 | |||
1086 | if (!psdev) | ||
1087 | goto out; | ||
1088 | |||
1089 | dev_data = pci_get_drvdata(psdev->dev); | ||
1090 | if (!dev_data) | ||
1091 | goto out; | ||
1092 | |||
1093 | dev_dbg(&psdev->dev->dev, "%s fake irq handler: %d->%d\n", | ||
1094 | dev_data->irq_name, dev_data->isr_on, | ||
1095 | !dev_data->isr_on); | ||
1096 | |||
1097 | dev_data->isr_on = !(dev_data->isr_on); | ||
1098 | if (dev_data->isr_on) | ||
1099 | dev_data->ack_intr = 1; | ||
1100 | out: | ||
1101 | if (!err) | ||
1102 | err = count; | ||
1103 | return err; | ||
1104 | } | ||
1105 | DRIVER_ATTR(irq_handler_state, S_IWUSR, NULL, pcistub_irq_handler_switch); | ||
1106 | |||
1032 | static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf, | 1107 | static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf, |
1033 | size_t count) | 1108 | size_t count) |
1034 | { | 1109 | { |
@@ -1168,7 +1243,10 @@ static void pcistub_exit(void) | |||
1168 | driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots); | 1243 | driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots); |
1169 | driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks); | 1244 | driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks); |
1170 | driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive); | 1245 | driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive); |
1171 | 1246 | driver_remove_file(&pciback_pci_driver.driver, | |
1247 | &driver_attr_irq_handlers); | ||
1248 | driver_remove_file(&pciback_pci_driver.driver, | ||
1249 | &driver_attr_irq_handler_state); | ||
1172 | pci_unregister_driver(&pciback_pci_driver); | 1250 | pci_unregister_driver(&pciback_pci_driver); |
1173 | } | 1251 | } |
1174 | 1252 | ||
@@ -1227,6 +1305,12 @@ static int __init pcistub_init(void) | |||
1227 | err = driver_create_file(&pciback_pci_driver.driver, | 1305 | err = driver_create_file(&pciback_pci_driver.driver, |
1228 | &driver_attr_permissive); | 1306 | &driver_attr_permissive); |
1229 | 1307 | ||
1308 | if (!err) | ||
1309 | err = driver_create_file(&pciback_pci_driver.driver, | ||
1310 | &driver_attr_irq_handlers); | ||
1311 | if (!err) | ||
1312 | err = driver_create_file(&pciback_pci_driver.driver, | ||
1313 | &driver_attr_irq_handler_state); | ||
1230 | if (err) | 1314 | if (err) |
1231 | pcistub_exit(); | 1315 | pcistub_exit(); |
1232 | 1316 | ||
diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h index c1e95e88ee9e..5c140200a5ea 100644 --- a/drivers/xen/xen-pciback/pciback.h +++ b/drivers/xen/xen-pciback/pciback.h | |||
@@ -45,8 +45,14 @@ struct pciback_device { | |||
45 | 45 | ||
46 | struct pciback_dev_data { | 46 | struct pciback_dev_data { |
47 | struct list_head config_fields; | 47 | struct list_head config_fields; |
48 | int permissive; | 48 | unsigned int permissive:1; |
49 | int warned_on_write; | 49 | unsigned int warned_on_write:1; |
50 | unsigned int enable_intx:1; | ||
51 | unsigned int isr_on:1; /* Whether the IRQ handler is installed. */ | ||
52 | unsigned int ack_intr:1; /* .. and ACK-ing */ | ||
53 | unsigned long handled; | ||
54 | unsigned int irq; /* Saved in case device transitions to MSI/MSI-X */ | ||
55 | char irq_name[0]; /* pciback[000:04:00.0] */ | ||
50 | }; | 56 | }; |
51 | 57 | ||
52 | /* Used by XenBus and pciback_ops.c */ | 58 | /* Used by XenBus and pciback_ops.c */ |
@@ -131,3 +137,6 @@ extern int verbose_request; | |||
131 | void test_and_schedule_op(struct pciback_device *pdev); | 137 | void test_and_schedule_op(struct pciback_device *pdev); |
132 | #endif | 138 | #endif |
133 | 139 | ||
140 | /* Handles shared IRQs that can to device domain and control domain. */ | ||
141 | void pciback_irq_handler(struct pci_dev *dev, int reset); | ||
142 | irqreturn_t pciback_guest_interrupt(int irq, void *dev_id); | ||
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 011db675e437..6c398fde7a83 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c | |||
@@ -13,6 +13,77 @@ | |||
13 | int verbose_request; | 13 | int verbose_request; |
14 | module_param(verbose_request, int, 0644); | 14 | module_param(verbose_request, int, 0644); |
15 | 15 | ||
16 | /* Ensure a device is has the fake IRQ handler "turned on/off" and is | ||
17 | * ready to be exported. This MUST be run after pciback_reset_device | ||
18 | * which does the actual PCI device enable/disable. | ||
19 | */ | ||
20 | void pciback_control_isr(struct pci_dev *dev, int reset) | ||
21 | { | ||
22 | struct pciback_dev_data *dev_data; | ||
23 | int rc; | ||
24 | int enable = 0; | ||
25 | |||
26 | dev_data = pci_get_drvdata(dev); | ||
27 | if (!dev_data) | ||
28 | return; | ||
29 | |||
30 | /* We don't deal with bridges */ | ||
31 | if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) | ||
32 | return; | ||
33 | |||
34 | if (reset) { | ||
35 | dev_data->enable_intx = 0; | ||
36 | dev_data->ack_intr = 0; | ||
37 | } | ||
38 | enable = dev_data->enable_intx; | ||
39 | |||
40 | /* Asked to disable, but ISR isn't runnig */ | ||
41 | if (!enable && !dev_data->isr_on) | ||
42 | return; | ||
43 | |||
44 | /* Squirrel away the IRQs in the dev_data. We need this | ||
45 | * b/c when device transitions to MSI, the dev->irq is | ||
46 | * overwritten with the MSI vector. | ||
47 | */ | ||
48 | if (enable) | ||
49 | dev_data->irq = dev->irq; | ||
50 | |||
51 | dev_dbg(&dev->dev, "%s: #%d %s %s%s %s-> %s\n", | ||
52 | dev_data->irq_name, | ||
53 | dev_data->irq, | ||
54 | pci_is_enabled(dev) ? "on" : "off", | ||
55 | dev->msi_enabled ? "MSI" : "", | ||
56 | dev->msix_enabled ? "MSI/X" : "", | ||
57 | dev_data->isr_on ? "enable" : "disable", | ||
58 | enable ? "enable" : "disable"); | ||
59 | |||
60 | if (enable) { | ||
61 | rc = request_irq(dev_data->irq, | ||
62 | pciback_guest_interrupt, IRQF_SHARED, | ||
63 | dev_data->irq_name, dev); | ||
64 | if (rc) { | ||
65 | dev_err(&dev->dev, "%s: failed to install fake IRQ " \ | ||
66 | "handler for IRQ %d! (rc:%d)\n", | ||
67 | dev_data->irq_name, dev_data->irq, rc); | ||
68 | goto out; | ||
69 | } | ||
70 | } else { | ||
71 | free_irq(dev_data->irq, dev); | ||
72 | dev_data->irq = 0; | ||
73 | } | ||
74 | dev_data->isr_on = enable; | ||
75 | dev_data->ack_intr = enable; | ||
76 | out: | ||
77 | dev_dbg(&dev->dev, "%s: #%d %s %s%s %s\n", | ||
78 | dev_data->irq_name, | ||
79 | dev_data->irq, | ||
80 | pci_is_enabled(dev) ? "on" : "off", | ||
81 | dev->msi_enabled ? "MSI" : "", | ||
82 | dev->msix_enabled ? "MSI/X" : "", | ||
83 | enable ? (dev_data->isr_on ? "enabled" : "failed to enable") : | ||
84 | (dev_data->isr_on ? "failed to disable" : "disabled")); | ||
85 | } | ||
86 | |||
16 | /* Ensure a device is "turned off" and ready to be exported. | 87 | /* Ensure a device is "turned off" and ready to be exported. |
17 | * (Also see pciback_config_reset to ensure virtual configuration space is | 88 | * (Also see pciback_config_reset to ensure virtual configuration space is |
18 | * ready to be re-exported) | 89 | * ready to be re-exported) |
@@ -21,6 +92,8 @@ void pciback_reset_device(struct pci_dev *dev) | |||
21 | { | 92 | { |
22 | u16 cmd; | 93 | u16 cmd; |
23 | 94 | ||
95 | pciback_control_isr(dev, 1 /* reset device */); | ||
96 | |||
24 | /* Disable devices (but not bridges) */ | 97 | /* Disable devices (but not bridges) */ |
25 | if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) { | 98 | if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) { |
26 | #ifdef CONFIG_PCI_MSI | 99 | #ifdef CONFIG_PCI_MSI |
@@ -78,13 +151,18 @@ void pciback_do_op(struct work_struct *data) | |||
78 | struct pciback_device *pdev = | 151 | struct pciback_device *pdev = |
79 | container_of(data, struct pciback_device, op_work); | 152 | container_of(data, struct pciback_device, op_work); |
80 | struct pci_dev *dev; | 153 | struct pci_dev *dev; |
154 | struct pciback_dev_data *dev_data = NULL; | ||
81 | struct xen_pci_op *op = &pdev->sh_info->op; | 155 | struct xen_pci_op *op = &pdev->sh_info->op; |
156 | int test_intx = 0; | ||
82 | 157 | ||
83 | dev = pciback_get_pci_dev(pdev, op->domain, op->bus, op->devfn); | 158 | dev = pciback_get_pci_dev(pdev, op->domain, op->bus, op->devfn); |
84 | 159 | ||
85 | if (dev == NULL) | 160 | if (dev == NULL) |
86 | op->err = XEN_PCI_ERR_dev_not_found; | 161 | op->err = XEN_PCI_ERR_dev_not_found; |
87 | else { | 162 | else { |
163 | dev_data = pci_get_drvdata(dev); | ||
164 | if (dev_data) | ||
165 | test_intx = dev_data->enable_intx; | ||
88 | switch (op->cmd) { | 166 | switch (op->cmd) { |
89 | case XEN_PCI_OP_conf_read: | 167 | case XEN_PCI_OP_conf_read: |
90 | op->err = pciback_config_read(dev, | 168 | op->err = pciback_config_read(dev, |
@@ -113,6 +191,11 @@ void pciback_do_op(struct work_struct *data) | |||
113 | break; | 191 | break; |
114 | } | 192 | } |
115 | } | 193 | } |
194 | if (!op->err && dev && dev_data) { | ||
195 | /* Transition detected */ | ||
196 | if ((dev_data->enable_intx != test_intx)) | ||
197 | pciback_control_isr(dev, 0 /* no reset */); | ||
198 | } | ||
116 | /* Tell the driver domain that we're done. */ | 199 | /* Tell the driver domain that we're done. */ |
117 | wmb(); | 200 | wmb(); |
118 | clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags); | 201 | clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags); |
@@ -137,3 +220,22 @@ irqreturn_t pciback_handle_event(int irq, void *dev_id) | |||
137 | 220 | ||
138 | return IRQ_HANDLED; | 221 | return IRQ_HANDLED; |
139 | } | 222 | } |
223 | irqreturn_t pciback_guest_interrupt(int irq, void *dev_id) | ||
224 | { | ||
225 | struct pci_dev *dev = (struct pci_dev *)dev_id; | ||
226 | struct pciback_dev_data *dev_data = pci_get_drvdata(dev); | ||
227 | |||
228 | if (dev_data->isr_on && dev_data->ack_intr) { | ||
229 | dev_data->handled++; | ||
230 | if ((dev_data->handled % 1000) == 0) { | ||
231 | if (xen_test_irq_shared(irq)) { | ||
232 | printk(KERN_INFO "%s IRQ line is not shared " | ||
233 | "with other domains. Turning ISR off\n", | ||
234 | dev_data->irq_name); | ||
235 | dev_data->ack_intr = 0; | ||
236 | } | ||
237 | } | ||
238 | return IRQ_HANDLED; | ||
239 | } | ||
240 | return IRQ_NONE; | ||
241 | } | ||