]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: jbeulich@novell.com |
2 | Subject: fix Dom0 resume from S3 when MSI is in use | |
3 | Patch-mainline: obsolete | |
4 | References: bnc#435596 | |
5 | ||
6 | --- sle11-2009-04-20.orig/drivers/pci/msi-xen.c 2009-01-09 11:10:27.000000000 +0100 | |
7 | +++ sle11-2009-04-20/drivers/pci/msi-xen.c 2009-04-24 13:37:37.000000000 +0200 | |
8 | @@ -234,8 +234,8 @@ static int msi_unmap_pirq(struct pci_dev | |
9 | int rc; | |
10 | ||
11 | unmap.domid = msi_get_dev_owner(dev); | |
12 | - /* See comments in msi_map_pirq_to_vector, input parameter pirq | |
13 | - * mean irq number only if the device belongs to dom0 itself. | |
14 | + /* See comments in msi_map_vector, input parameter pirq means | |
15 | + * irq number only if the device belongs to dom0 itself. | |
16 | */ | |
17 | unmap.pirq = (unmap.domid != DOMID_SELF) | |
18 | ? pirq : evtchn_get_xen_pirq(pirq); | |
19 | @@ -271,8 +271,7 @@ static u64 find_table_base(struct pci_de | |
20 | /* | |
21 | * Protected by msi_lock | |
22 | */ | |
23 | -static int msi_map_pirq_to_vector(struct pci_dev *dev, int pirq, | |
24 | - int entry_nr, u64 table_base) | |
25 | +static int msi_map_vector(struct pci_dev *dev, int entry_nr, u64 table_base) | |
26 | { | |
27 | struct physdev_map_pirq map_irq; | |
28 | int rc; | |
29 | @@ -283,7 +282,7 @@ static int msi_map_pirq_to_vector(struct | |
30 | map_irq.domid = domid; | |
31 | map_irq.type = MAP_PIRQ_TYPE_MSI; | |
32 | map_irq.index = -1; | |
33 | - map_irq.pirq = pirq < 0 ? -1 : evtchn_get_xen_pirq(pirq); | |
34 | + map_irq.pirq = -1; | |
35 | map_irq.bus = dev->bus->number; | |
36 | map_irq.devfn = dev->devfn; | |
37 | map_irq.entry_nr = entry_nr; | |
38 | @@ -294,7 +293,7 @@ static int msi_map_pirq_to_vector(struct | |
39 | ||
40 | if (rc < 0) | |
41 | return rc; | |
42 | - /* This happens when MSI support is not enabled in Xen. */ | |
43 | + /* This happens when MSI support is not enabled in older Xen. */ | |
44 | if (rc == 0 && map_irq.pirq < 0) | |
45 | return -ENOSYS; | |
46 | ||
47 | @@ -306,12 +305,7 @@ static int msi_map_pirq_to_vector(struct | |
48 | * to another domain, and will be 'Linux irq' if it belongs to dom0. | |
49 | */ | |
50 | return ((domid != DOMID_SELF) ? | |
51 | - map_irq.pirq : evtchn_map_pirq(pirq, map_irq.pirq)); | |
52 | -} | |
53 | - | |
54 | -static int msi_map_vector(struct pci_dev *dev, int entry_nr, u64 table_base) | |
55 | -{ | |
56 | - return msi_map_pirq_to_vector(dev, -1, entry_nr, table_base); | |
57 | + map_irq.pirq : evtchn_map_pirq(-1, map_irq.pirq)); | |
58 | } | |
59 | ||
60 | static void pci_intx_for_msi(struct pci_dev *dev, int enable) | |
61 | @@ -320,62 +314,24 @@ static void pci_intx_for_msi(struct pci_ | |
62 | pci_intx(dev, enable); | |
63 | } | |
64 | ||
65 | -static void __pci_restore_msi_state(struct pci_dev *dev) | |
66 | -{ | |
67 | - int pirq; | |
68 | - | |
69 | - if (!dev->msi_enabled) | |
70 | - return; | |
71 | - | |
72 | - pci_intx_for_msi(dev, 0); | |
73 | - msi_set_enable(dev, 0); | |
74 | - | |
75 | - pirq = msi_map_pirq_to_vector(dev, dev->irq, 0, 0); | |
76 | - if (pirq < 0) | |
77 | - return; | |
78 | -} | |
79 | - | |
80 | -static void __pci_restore_msix_state(struct pci_dev *dev) | |
81 | +void pci_restore_msi_state(struct pci_dev *dev) | |
82 | { | |
83 | - int pos; | |
84 | - unsigned long flags; | |
85 | - u64 table_base; | |
86 | - struct msi_dev_list *msi_dev_entry; | |
87 | - struct msi_pirq_entry *pirq_entry, *tmp; | |
88 | + int rc; | |
89 | + struct physdev_restore_msi restore; | |
90 | ||
91 | - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | |
92 | - if (pos <= 0) | |
93 | - return; | |
94 | - | |
95 | - if (!dev->msix_enabled) | |
96 | + if (!dev->msi_enabled && !dev->msix_enabled) | |
97 | return; | |
98 | ||
99 | pci_intx_for_msi(dev, 0); | |
100 | - msix_set_enable(dev, 0); | |
101 | - | |
102 | - msi_dev_entry = get_msi_dev_pirq_list(dev); | |
103 | - table_base = find_table_base(dev, pos); | |
104 | - if (!table_base) | |
105 | - return; | |
106 | - | |
107 | - spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags); | |
108 | - list_for_each_entry_safe(pirq_entry, tmp, | |
109 | - &msi_dev_entry->pirq_list_head, list) { | |
110 | - int rc = msi_map_pirq_to_vector(dev, pirq_entry->pirq, | |
111 | - pirq_entry->entry_nr, table_base); | |
112 | - if (rc < 0) | |
113 | - printk(KERN_WARNING | |
114 | - "%s: re-mapping irq #%d (pirq%d) failed: %d\n", | |
115 | - pci_name(dev), pirq_entry->entry_nr, | |
116 | - pirq_entry->pirq, rc); | |
117 | - } | |
118 | - spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags); | |
119 | -} | |
120 | - | |
121 | -void pci_restore_msi_state(struct pci_dev *dev) | |
122 | -{ | |
123 | - __pci_restore_msi_state(dev); | |
124 | - __pci_restore_msix_state(dev); | |
125 | + if (dev->msi_enabled) | |
126 | + msi_set_enable(dev, 0); | |
127 | + if (dev->msix_enabled) | |
128 | + msix_set_enable(dev, 0); | |
129 | + | |
130 | + restore.bus = dev->bus->number; | |
131 | + restore.devfn = dev->devfn; | |
132 | + rc = HYPERVISOR_physdev_op(PHYSDEVOP_restore_msi, &restore); | |
133 | + WARN(rc && rc != -ENOSYS, "restore_msi -> %d\n", rc); | |
134 | } | |
135 | EXPORT_SYMBOL_GPL(pci_restore_msi_state); | |
136 | ||
137 | --- sle11-2009-04-20.orig/include/xen/interface/physdev.h 2009-04-24 13:28:45.000000000 +0200 | |
138 | +++ sle11-2009-04-20/include/xen/interface/physdev.h 2009-01-05 15:11:37.000000000 +0100 | |
139 | @@ -183,6 +183,15 @@ struct physdev_manage_pci { | |
140 | typedef struct physdev_manage_pci physdev_manage_pci_t; | |
141 | DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_t); | |
142 | ||
143 | +#define PHYSDEVOP_restore_msi 19 | |
144 | +struct physdev_restore_msi { | |
145 | + /* IN */ | |
146 | + uint8_t bus; | |
147 | + uint8_t devfn; | |
148 | +}; | |
149 | +typedef struct physdev_restore_msi physdev_restore_msi_t; | |
150 | +DEFINE_XEN_GUEST_HANDLE(physdev_restore_msi_t); | |
151 | + | |
152 | /* | |
153 | * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op() | |
154 | * hypercall since 0x00030202. |