diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/msi.c | 115 |
1 files changed, 39 insertions, 76 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index dceea56f7342..b3db4388f974 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -111,20 +111,10 @@ static void msix_flush_writes(struct irq_desc *desc) | |||
111 | 111 | ||
112 | entry = get_irq_desc_msi(desc); | 112 | entry = get_irq_desc_msi(desc); |
113 | BUG_ON(!entry || !entry->dev); | 113 | BUG_ON(!entry || !entry->dev); |
114 | switch (entry->msi_attrib.type) { | 114 | if (entry->msi_attrib.is_msix) { |
115 | case PCI_CAP_ID_MSI: | ||
116 | /* nothing to do */ | ||
117 | break; | ||
118 | case PCI_CAP_ID_MSIX: | ||
119 | { | ||
120 | int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | 115 | int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + |
121 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; | 116 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; |
122 | readl(entry->mask_base + offset); | 117 | readl(entry->mask_base + offset); |
123 | break; | ||
124 | } | ||
125 | default: | ||
126 | BUG(); | ||
127 | break; | ||
128 | } | 118 | } |
129 | } | 119 | } |
130 | 120 | ||
@@ -143,32 +133,23 @@ static int msi_set_mask_bits(struct irq_desc *desc, u32 mask, u32 flag) | |||
143 | 133 | ||
144 | entry = get_irq_desc_msi(desc); | 134 | entry = get_irq_desc_msi(desc); |
145 | BUG_ON(!entry || !entry->dev); | 135 | BUG_ON(!entry || !entry->dev); |
146 | switch (entry->msi_attrib.type) { | 136 | if (entry->msi_attrib.is_msix) { |
147 | case PCI_CAP_ID_MSI: | ||
148 | if (entry->msi_attrib.maskbit) { | ||
149 | int pos; | ||
150 | u32 mask_bits; | ||
151 | |||
152 | pos = (long)entry->mask_base; | ||
153 | pci_read_config_dword(entry->dev, pos, &mask_bits); | ||
154 | mask_bits &= ~(mask); | ||
155 | mask_bits |= flag & mask; | ||
156 | pci_write_config_dword(entry->dev, pos, mask_bits); | ||
157 | } else { | ||
158 | return 0; | ||
159 | } | ||
160 | break; | ||
161 | case PCI_CAP_ID_MSIX: | ||
162 | { | ||
163 | int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | 137 | int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + |
164 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; | 138 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; |
165 | writel(flag, entry->mask_base + offset); | 139 | writel(flag, entry->mask_base + offset); |
166 | readl(entry->mask_base + offset); | 140 | readl(entry->mask_base + offset); |
167 | break; | 141 | } else { |
168 | } | 142 | int pos; |
169 | default: | 143 | u32 mask_bits; |
170 | BUG(); | 144 | |
171 | break; | 145 | if (!entry->msi_attrib.maskbit) |
146 | return 0; | ||
147 | |||
148 | pos = (long)entry->mask_base; | ||
149 | pci_read_config_dword(entry->dev, pos, &mask_bits); | ||
150 | mask_bits &= ~mask; | ||
151 | mask_bits |= flag & mask; | ||
152 | pci_write_config_dword(entry->dev, pos, mask_bits); | ||
172 | } | 153 | } |
173 | entry->msi_attrib.masked = !!flag; | 154 | entry->msi_attrib.masked = !!flag; |
174 | return 1; | 155 | return 1; |
@@ -177,9 +158,14 @@ static int msi_set_mask_bits(struct irq_desc *desc, u32 mask, u32 flag) | |||
177 | void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | 158 | void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) |
178 | { | 159 | { |
179 | struct msi_desc *entry = get_irq_desc_msi(desc); | 160 | struct msi_desc *entry = get_irq_desc_msi(desc); |
180 | switch(entry->msi_attrib.type) { | 161 | if (entry->msi_attrib.is_msix) { |
181 | case PCI_CAP_ID_MSI: | 162 | void __iomem *base = entry->mask_base + |
182 | { | 163 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
164 | |||
165 | msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
166 | msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
167 | msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET); | ||
168 | } else { | ||
183 | struct pci_dev *dev = entry->dev; | 169 | struct pci_dev *dev = entry->dev; |
184 | int pos = entry->msi_attrib.pos; | 170 | int pos = entry->msi_attrib.pos; |
185 | u16 data; | 171 | u16 data; |
@@ -195,21 +181,6 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
195 | pci_read_config_word(dev, msi_data_reg(pos, 0), &data); | 181 | pci_read_config_word(dev, msi_data_reg(pos, 0), &data); |
196 | } | 182 | } |
197 | msg->data = data; | 183 | msg->data = data; |
198 | break; | ||
199 | } | ||
200 | case PCI_CAP_ID_MSIX: | ||
201 | { | ||
202 | void __iomem *base; | ||
203 | base = entry->mask_base + | ||
204 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | ||
205 | |||
206 | msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
207 | msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
208 | msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET); | ||
209 | break; | ||
210 | } | ||
211 | default: | ||
212 | BUG(); | ||
213 | } | 184 | } |
214 | } | 185 | } |
215 | 186 | ||
@@ -223,9 +194,17 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg) | |||
223 | void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | 194 | void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) |
224 | { | 195 | { |
225 | struct msi_desc *entry = get_irq_desc_msi(desc); | 196 | struct msi_desc *entry = get_irq_desc_msi(desc); |
226 | switch (entry->msi_attrib.type) { | 197 | if (entry->msi_attrib.is_msix) { |
227 | case PCI_CAP_ID_MSI: | 198 | void __iomem *base; |
228 | { | 199 | base = entry->mask_base + |
200 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | ||
201 | |||
202 | writel(msg->address_lo, | ||
203 | base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
204 | writel(msg->address_hi, | ||
205 | base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
206 | writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET); | ||
207 | } else { | ||
229 | struct pci_dev *dev = entry->dev; | 208 | struct pci_dev *dev = entry->dev; |
230 | int pos = entry->msi_attrib.pos; | 209 | int pos = entry->msi_attrib.pos; |
231 | 210 | ||
@@ -240,23 +219,6 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
240 | pci_write_config_word(dev, msi_data_reg(pos, 0), | 219 | pci_write_config_word(dev, msi_data_reg(pos, 0), |
241 | msg->data); | 220 | msg->data); |
242 | } | 221 | } |
243 | break; | ||
244 | } | ||
245 | case PCI_CAP_ID_MSIX: | ||
246 | { | ||
247 | void __iomem *base; | ||
248 | base = entry->mask_base + | ||
249 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | ||
250 | |||
251 | writel(msg->address_lo, | ||
252 | base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
253 | writel(msg->address_hi, | ||
254 | base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
255 | writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET); | ||
256 | break; | ||
257 | } | ||
258 | default: | ||
259 | BUG(); | ||
260 | } | 222 | } |
261 | entry->msg = *msg; | 223 | entry->msg = *msg; |
262 | } | 224 | } |
@@ -393,7 +355,7 @@ static int msi_capability_init(struct pci_dev *dev) | |||
393 | if (!entry) | 355 | if (!entry) |
394 | return -ENOMEM; | 356 | return -ENOMEM; |
395 | 357 | ||
396 | entry->msi_attrib.type = PCI_CAP_ID_MSI; | 358 | entry->msi_attrib.is_msix = 0; |
397 | entry->msi_attrib.is_64 = is_64bit_address(control); | 359 | entry->msi_attrib.is_64 = is_64bit_address(control); |
398 | entry->msi_attrib.entry_nr = 0; | 360 | entry->msi_attrib.entry_nr = 0; |
399 | entry->msi_attrib.maskbit = is_mask_bit_support(control); | 361 | entry->msi_attrib.maskbit = is_mask_bit_support(control); |
@@ -475,7 +437,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
475 | break; | 437 | break; |
476 | 438 | ||
477 | j = entries[i].entry; | 439 | j = entries[i].entry; |
478 | entry->msi_attrib.type = PCI_CAP_ID_MSIX; | 440 | entry->msi_attrib.is_msix = 1; |
479 | entry->msi_attrib.is_64 = 1; | 441 | entry->msi_attrib.is_64 = 1; |
480 | entry->msi_attrib.entry_nr = j; | 442 | entry->msi_attrib.entry_nr = j; |
481 | entry->msi_attrib.maskbit = 1; | 443 | entry->msi_attrib.maskbit = 1; |
@@ -619,12 +581,13 @@ void pci_msi_shutdown(struct pci_dev* dev) | |||
619 | struct irq_desc *desc = irq_to_desc(dev->irq); | 581 | struct irq_desc *desc = irq_to_desc(dev->irq); |
620 | msi_set_mask_bits(desc, mask, ~mask); | 582 | msi_set_mask_bits(desc, mask, ~mask); |
621 | } | 583 | } |
622 | if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) | 584 | if (!entry->dev || entry->msi_attrib.is_msix) |
623 | return; | 585 | return; |
624 | 586 | ||
625 | /* Restore dev->irq to its default pin-assertion irq */ | 587 | /* Restore dev->irq to its default pin-assertion irq */ |
626 | dev->irq = entry->msi_attrib.default_irq; | 588 | dev->irq = entry->msi_attrib.default_irq; |
627 | } | 589 | } |
590 | |||
628 | void pci_disable_msi(struct pci_dev* dev) | 591 | void pci_disable_msi(struct pci_dev* dev) |
629 | { | 592 | { |
630 | struct msi_desc *entry; | 593 | struct msi_desc *entry; |
@@ -635,7 +598,7 @@ void pci_disable_msi(struct pci_dev* dev) | |||
635 | pci_msi_shutdown(dev); | 598 | pci_msi_shutdown(dev); |
636 | 599 | ||
637 | entry = list_entry(dev->msi_list.next, struct msi_desc, list); | 600 | entry = list_entry(dev->msi_list.next, struct msi_desc, list); |
638 | if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) | 601 | if (!entry->dev || entry->msi_attrib.is_msix) |
639 | return; | 602 | return; |
640 | 603 | ||
641 | msi_free_irqs(dev); | 604 | msi_free_irqs(dev); |
@@ -654,7 +617,7 @@ static int msi_free_irqs(struct pci_dev* dev) | |||
654 | arch_teardown_msi_irqs(dev); | 617 | arch_teardown_msi_irqs(dev); |
655 | 618 | ||
656 | list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { | 619 | list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { |
657 | if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) { | 620 | if (entry->msi_attrib.is_msix) { |
658 | writel(1, entry->mask_base + entry->msi_attrib.entry_nr | 621 | writel(1, entry->mask_base + entry->msi_attrib.entry_nr |
659 | * PCI_MSIX_ENTRY_SIZE | 622 | * PCI_MSIX_ENTRY_SIZE |
660 | + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); | 623 | + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); |