aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/msi.c144
1 files changed, 64 insertions, 80 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index fd1068b59b0c..c43e7d22e180 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -38,6 +38,36 @@ static int msi_cache_init(void)
38 return 0; 38 return 0;
39} 39}
40 40
41static void msi_set_enable(struct pci_dev *dev, int enable)
42{
43 int pos;
44 u16 control;
45
46 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
47 if (pos) {
48 pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
49 control &= ~PCI_MSI_FLAGS_ENABLE;
50 if (enable)
51 control |= PCI_MSI_FLAGS_ENABLE;
52 pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
53 }
54}
55
56static void msix_set_enable(struct pci_dev *dev, int enable)
57{
58 int pos;
59 u16 control;
60
61 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
62 if (pos) {
63 pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
64 control &= ~PCI_MSIX_FLAGS_ENABLE;
65 if (enable)
66 control |= PCI_MSIX_FLAGS_ENABLE;
67 pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
68 }
69}
70
41static void msi_set_mask_bit(unsigned int irq, int flag) 71static void msi_set_mask_bit(unsigned int irq, int flag)
42{ 72{
43 struct msi_desc *entry; 73 struct msi_desc *entry;
@@ -192,44 +222,6 @@ static struct msi_desc* alloc_msi_entry(void)
192 return entry; 222 return entry;
193} 223}
194 224
195static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
196{
197 u16 control;
198
199 pci_read_config_word(dev, msi_control_reg(pos), &control);
200 if (type == PCI_CAP_ID_MSI) {
201 /* Set enabled bits to single MSI & enable MSI_enable bit */
202 msi_enable(control, 1);
203 pci_write_config_word(dev, msi_control_reg(pos), control);
204 dev->msi_enabled = 1;
205 } else {
206 msix_enable(control);
207 pci_write_config_word(dev, msi_control_reg(pos), control);
208 dev->msix_enabled = 1;
209 }
210
211 pci_intx(dev, 0); /* disable intx */
212}
213
214static void disable_msi_mode(struct pci_dev *dev, int pos, int type)
215{
216 u16 control;
217
218 pci_read_config_word(dev, msi_control_reg(pos), &control);
219 if (type == PCI_CAP_ID_MSI) {
220 /* Set enabled bits to single MSI & enable MSI_enable bit */
221 msi_disable(control);
222 pci_write_config_word(dev, msi_control_reg(pos), control);
223 dev->msi_enabled = 0;
224 } else {
225 msix_disable(control);
226 pci_write_config_word(dev, msi_control_reg(pos), control);
227 dev->msix_enabled = 0;
228 }
229
230 pci_intx(dev, 1); /* enable intx */
231}
232
233#ifdef CONFIG_PM 225#ifdef CONFIG_PM
234static int __pci_save_msi_state(struct pci_dev *dev) 226static int __pci_save_msi_state(struct pci_dev *dev)
235{ 227{
@@ -238,12 +230,11 @@ static int __pci_save_msi_state(struct pci_dev *dev)
238 struct pci_cap_saved_state *save_state; 230 struct pci_cap_saved_state *save_state;
239 u32 *cap; 231 u32 *cap;
240 232
241 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 233 if (!dev->msi_enabled)
242 if (pos <= 0 || dev->no_msi)
243 return 0; 234 return 0;
244 235
245 pci_read_config_word(dev, msi_control_reg(pos), &control); 236 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
246 if (!(control & PCI_MSI_FLAGS_ENABLE)) 237 if (pos <= 0)
247 return 0; 238 return 0;
248 239
249 save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5, 240 save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5,
@@ -276,13 +267,18 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
276 struct pci_cap_saved_state *save_state; 267 struct pci_cap_saved_state *save_state;
277 u32 *cap; 268 u32 *cap;
278 269
270 if (!dev->msi_enabled)
271 return;
272
279 save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI); 273 save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI);
280 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 274 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
281 if (!save_state || pos <= 0) 275 if (!save_state || pos <= 0)
282 return; 276 return;
283 cap = &save_state->data[0]; 277 cap = &save_state->data[0];
284 278
279 pci_intx(dev, 0); /* disable intx */
285 control = cap[i++] >> 16; 280 control = cap[i++] >> 16;
281 msi_set_enable(dev, 0);
286 pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]); 282 pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]);
287 if (control & PCI_MSI_FLAGS_64BIT) { 283 if (control & PCI_MSI_FLAGS_64BIT) {
288 pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]); 284 pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]);
@@ -292,7 +288,6 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
292 if (control & PCI_MSI_FLAGS_MASKBIT) 288 if (control & PCI_MSI_FLAGS_MASKBIT)
293 pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]); 289 pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]);
294 pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); 290 pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
295 enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
296 pci_remove_saved_cap(save_state); 291 pci_remove_saved_cap(save_state);
297 kfree(save_state); 292 kfree(save_state);
298} 293}
@@ -308,13 +303,11 @@ static int __pci_save_msix_state(struct pci_dev *dev)
308 return 0; 303 return 0;
309 304
310 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); 305 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
311 if (pos <= 0 || dev->no_msi) 306 if (pos <= 0)
312 return 0; 307 return 0;
313 308
314 /* save the capability */ 309 /* save the capability */
315 pci_read_config_word(dev, msi_control_reg(pos), &control); 310 pci_read_config_word(dev, msi_control_reg(pos), &control);
316 if (!(control & PCI_MSIX_FLAGS_ENABLE))
317 return 0;
318 save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16), 311 save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
319 GFP_KERNEL); 312 GFP_KERNEL);
320 if (!save_state) { 313 if (!save_state) {
@@ -376,6 +369,8 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
376 return; 369 return;
377 370
378 /* route the table */ 371 /* route the table */
372 pci_intx(dev, 0); /* disable intx */
373 msix_set_enable(dev, 0);
379 irq = head = dev->first_msi_irq; 374 irq = head = dev->first_msi_irq;
380 while (head != tail) { 375 while (head != tail) {
381 entry = get_irq_msi(irq); 376 entry = get_irq_msi(irq);
@@ -386,7 +381,6 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
386 } 381 }
387 382
388 pci_write_config_word(dev, msi_control_reg(pos), save); 383 pci_write_config_word(dev, msi_control_reg(pos), save);
389 enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
390} 384}
391 385
392void pci_restore_msi_state(struct pci_dev *dev) 386void pci_restore_msi_state(struct pci_dev *dev)
@@ -411,6 +405,8 @@ static int msi_capability_init(struct pci_dev *dev)
411 int pos, irq; 405 int pos, irq;
412 u16 control; 406 u16 control;
413 407
408 msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */
409
414 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 410 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
415 pci_read_config_word(dev, msi_control_reg(pos), &control); 411 pci_read_config_word(dev, msi_control_reg(pos), &control);
416 /* MSI Entry Initialization */ 412 /* MSI Entry Initialization */
@@ -454,7 +450,9 @@ static int msi_capability_init(struct pci_dev *dev)
454 set_irq_msi(irq, entry); 450 set_irq_msi(irq, entry);
455 451
456 /* Set MSI enabled bits */ 452 /* Set MSI enabled bits */
457 enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); 453 pci_intx(dev, 0); /* disable intx */
454 msi_set_enable(dev, 1);
455 dev->msi_enabled = 1;
458 456
459 dev->irq = irq; 457 dev->irq = irq;
460 return 0; 458 return 0;
@@ -481,6 +479,8 @@ static int msix_capability_init(struct pci_dev *dev,
481 u8 bir; 479 u8 bir;
482 void __iomem *base; 480 void __iomem *base;
483 481
482 msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */
483
484 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); 484 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
485 /* Request & Map MSI-X table region */ 485 /* Request & Map MSI-X table region */
486 pci_read_config_word(dev, msi_control_reg(pos), &control); 486 pci_read_config_word(dev, msi_control_reg(pos), &control);
@@ -549,7 +549,9 @@ static int msix_capability_init(struct pci_dev *dev,
549 } 549 }
550 dev->first_msi_irq = entries[0].vector; 550 dev->first_msi_irq = entries[0].vector;
551 /* Set MSI-X enabled bits */ 551 /* Set MSI-X enabled bits */
552 enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); 552 pci_intx(dev, 0); /* disable intx */
553 msix_set_enable(dev, 1);
554 dev->msix_enabled = 1;
553 555
554 return 0; 556 return 0;
555} 557}
@@ -611,12 +613,11 @@ int pci_enable_msi(struct pci_dev* dev)
611 WARN_ON(!!dev->msi_enabled); 613 WARN_ON(!!dev->msi_enabled);
612 614
613 /* Check whether driver already requested for MSI-X irqs */ 615 /* Check whether driver already requested for MSI-X irqs */
614 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); 616 if (dev->msix_enabled) {
615 if (pos > 0 && dev->msix_enabled) { 617 printk(KERN_INFO "PCI: %s: Can't enable MSI. "
616 printk(KERN_INFO "PCI: %s: Can't enable MSI. " 618 "Device already has MSI-X enabled\n",
617 "Device already has MSI-X enabled\n", 619 pci_name(dev));
618 pci_name(dev)); 620 return -EINVAL;
619 return -EINVAL;
620 } 621 }
621 status = msi_capability_init(dev); 622 status = msi_capability_init(dev);
622 return status; 623 return status;
@@ -625,8 +626,7 @@ int pci_enable_msi(struct pci_dev* dev)
625void pci_disable_msi(struct pci_dev* dev) 626void pci_disable_msi(struct pci_dev* dev)
626{ 627{
627 struct msi_desc *entry; 628 struct msi_desc *entry;
628 int pos, default_irq; 629 int default_irq;
629 u16 control;
630 630
631 if (!pci_msi_enable) 631 if (!pci_msi_enable)
632 return; 632 return;
@@ -636,16 +636,9 @@ void pci_disable_msi(struct pci_dev* dev)
636 if (!dev->msi_enabled) 636 if (!dev->msi_enabled)
637 return; 637 return;
638 638
639 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 639 msi_set_enable(dev, 0);
640 if (!pos) 640 pci_intx(dev, 1); /* enable intx */
641 return; 641 dev->msi_enabled = 0;
642
643 pci_read_config_word(dev, msi_control_reg(pos), &control);
644 if (!(control & PCI_MSI_FLAGS_ENABLE))
645 return;
646
647
648 disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
649 642
650 entry = get_irq_msi(dev->first_msi_irq); 643 entry = get_irq_msi(dev->first_msi_irq);
651 if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { 644 if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
@@ -746,8 +739,7 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
746 WARN_ON(!!dev->msix_enabled); 739 WARN_ON(!!dev->msix_enabled);
747 740
748 /* Check whether driver already requested for MSI irq */ 741 /* Check whether driver already requested for MSI irq */
749 if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 && 742 if (dev->msi_enabled) {
750 dev->msi_enabled) {
751 printk(KERN_INFO "PCI: %s: Can't enable MSI-X. " 743 printk(KERN_INFO "PCI: %s: Can't enable MSI-X. "
752 "Device already has an MSI irq assigned\n", 744 "Device already has an MSI irq assigned\n",
753 pci_name(dev)); 745 pci_name(dev));
@@ -760,8 +752,6 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
760void pci_disable_msix(struct pci_dev* dev) 752void pci_disable_msix(struct pci_dev* dev)
761{ 753{
762 int irq, head, tail = 0, warning = 0; 754 int irq, head, tail = 0, warning = 0;
763 int pos;
764 u16 control;
765 755
766 if (!pci_msi_enable) 756 if (!pci_msi_enable)
767 return; 757 return;
@@ -771,15 +761,9 @@ void pci_disable_msix(struct pci_dev* dev)
771 if (!dev->msix_enabled) 761 if (!dev->msix_enabled)
772 return; 762 return;
773 763
774 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); 764 msix_set_enable(dev, 0);
775 if (!pos) 765 pci_intx(dev, 1); /* enable intx */
776 return; 766 dev->msix_enabled = 0;
777
778 pci_read_config_word(dev, msi_control_reg(pos), &control);
779 if (!(control & PCI_MSIX_FLAGS_ENABLE))
780 return;
781
782 disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
783 767
784 irq = head = dev->first_msi_irq; 768 irq = head = dev->first_msi_irq;
785 while (head != tail) { 769 while (head != tail) {