diff options
author | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-06-10 14:47:26 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-06-10 14:47:26 -0400 |
commit | f0cd91a68acdc9b49d7f6738b514a426da627649 (patch) | |
tree | 8ad73564015794197583b094217ae0a71e71e753 /drivers/pci | |
parent | 60eef25701d25e99c991dd0f4a9f3832a0c3ad3e (diff) | |
parent | 128e6ced247cda88f96fa9f2e4ba8b2c4a681560 (diff) |
Merge ../linux-2.6
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/rpaphp_core.c | 3 | ||||
-rw-r--r-- | drivers/pci/msi.c | 231 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 60 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci.c | 12 | ||||
-rw-r--r-- | drivers/pci/pci.h | 11 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 55 |
7 files changed, 312 insertions, 66 deletions
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 6e79f5675b0d..638004546700 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c | |||
@@ -360,9 +360,6 @@ static int __init rpaphp_init(void) | |||
360 | while ((dn = of_find_node_by_type(dn, "pci"))) | 360 | while ((dn = of_find_node_by_type(dn, "pci"))) |
361 | rpaphp_add_slot(dn); | 361 | rpaphp_add_slot(dn); |
362 | 362 | ||
363 | if (!num_slots) | ||
364 | return -ENODEV; | ||
365 | |||
366 | return 0; | 363 | return 0; |
367 | } | 364 | } |
368 | 365 | ||
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a77e79c8c82e..9855c4c920b8 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -504,6 +504,201 @@ void pci_scan_msi_device(struct pci_dev *dev) | |||
504 | nr_reserved_vectors++; | 504 | nr_reserved_vectors++; |
505 | } | 505 | } |
506 | 506 | ||
507 | #ifdef CONFIG_PM | ||
508 | int pci_save_msi_state(struct pci_dev *dev) | ||
509 | { | ||
510 | int pos, i = 0; | ||
511 | u16 control; | ||
512 | struct pci_cap_saved_state *save_state; | ||
513 | u32 *cap; | ||
514 | |||
515 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | ||
516 | if (pos <= 0 || dev->no_msi) | ||
517 | return 0; | ||
518 | |||
519 | pci_read_config_word(dev, msi_control_reg(pos), &control); | ||
520 | if (!(control & PCI_MSI_FLAGS_ENABLE)) | ||
521 | return 0; | ||
522 | |||
523 | save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u32) * 5, | ||
524 | GFP_KERNEL); | ||
525 | if (!save_state) { | ||
526 | printk(KERN_ERR "Out of memory in pci_save_msi_state\n"); | ||
527 | return -ENOMEM; | ||
528 | } | ||
529 | cap = &save_state->data[0]; | ||
530 | |||
531 | pci_read_config_dword(dev, pos, &cap[i++]); | ||
532 | control = cap[0] >> 16; | ||
533 | pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, &cap[i++]); | ||
534 | if (control & PCI_MSI_FLAGS_64BIT) { | ||
535 | pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &cap[i++]); | ||
536 | pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, &cap[i++]); | ||
537 | } else | ||
538 | pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]); | ||
539 | if (control & PCI_MSI_FLAGS_MASKBIT) | ||
540 | pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]); | ||
541 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | ||
542 | save_state->cap_nr = PCI_CAP_ID_MSI; | ||
543 | pci_add_saved_cap(dev, save_state); | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | void pci_restore_msi_state(struct pci_dev *dev) | ||
548 | { | ||
549 | int i = 0, pos; | ||
550 | u16 control; | ||
551 | struct pci_cap_saved_state *save_state; | ||
552 | u32 *cap; | ||
553 | |||
554 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSI); | ||
555 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | ||
556 | if (!save_state || pos <= 0) | ||
557 | return; | ||
558 | cap = &save_state->data[0]; | ||
559 | |||
560 | control = cap[i++] >> 16; | ||
561 | pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, cap[i++]); | ||
562 | if (control & PCI_MSI_FLAGS_64BIT) { | ||
563 | pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, cap[i++]); | ||
564 | pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, cap[i++]); | ||
565 | } else | ||
566 | pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, cap[i++]); | ||
567 | if (control & PCI_MSI_FLAGS_MASKBIT) | ||
568 | pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, cap[i++]); | ||
569 | pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); | ||
570 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | ||
571 | pci_remove_saved_cap(save_state); | ||
572 | kfree(save_state); | ||
573 | } | ||
574 | |||
575 | int pci_save_msix_state(struct pci_dev *dev) | ||
576 | { | ||
577 | int pos; | ||
578 | u16 control; | ||
579 | struct pci_cap_saved_state *save_state; | ||
580 | |||
581 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | ||
582 | if (pos <= 0 || dev->no_msi) | ||
583 | return 0; | ||
584 | |||
585 | pci_read_config_word(dev, msi_control_reg(pos), &control); | ||
586 | if (!(control & PCI_MSIX_FLAGS_ENABLE)) | ||
587 | return 0; | ||
588 | save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16), | ||
589 | GFP_KERNEL); | ||
590 | if (!save_state) { | ||
591 | printk(KERN_ERR "Out of memory in pci_save_msix_state\n"); | ||
592 | return -ENOMEM; | ||
593 | } | ||
594 | *((u16 *)&save_state->data[0]) = control; | ||
595 | |||
596 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); | ||
597 | save_state->cap_nr = PCI_CAP_ID_MSIX; | ||
598 | pci_add_saved_cap(dev, save_state); | ||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | void pci_restore_msix_state(struct pci_dev *dev) | ||
603 | { | ||
604 | u16 save; | ||
605 | int pos; | ||
606 | int vector, head, tail = 0; | ||
607 | void __iomem *base; | ||
608 | int j; | ||
609 | struct msg_address address; | ||
610 | struct msg_data data; | ||
611 | struct msi_desc *entry; | ||
612 | int temp; | ||
613 | struct pci_cap_saved_state *save_state; | ||
614 | |||
615 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX); | ||
616 | if (!save_state) | ||
617 | return; | ||
618 | save = *((u16 *)&save_state->data[0]); | ||
619 | pci_remove_saved_cap(save_state); | ||
620 | kfree(save_state); | ||
621 | |||
622 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | ||
623 | if (pos <= 0) | ||
624 | return; | ||
625 | |||
626 | /* route the table */ | ||
627 | temp = dev->irq; | ||
628 | if (msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) | ||
629 | return; | ||
630 | vector = head = dev->irq; | ||
631 | while (head != tail) { | ||
632 | entry = msi_desc[vector]; | ||
633 | base = entry->mask_base; | ||
634 | j = entry->msi_attrib.entry_nr; | ||
635 | |||
636 | msi_address_init(&address); | ||
637 | msi_data_init(&data, vector); | ||
638 | |||
639 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; | ||
640 | address.lo_address.value |= entry->msi_attrib.current_cpu << | ||
641 | MSI_TARGET_CPU_SHIFT; | ||
642 | |||
643 | writel(address.lo_address.value, | ||
644 | base + j * PCI_MSIX_ENTRY_SIZE + | ||
645 | PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
646 | writel(address.hi_address, | ||
647 | base + j * PCI_MSIX_ENTRY_SIZE + | ||
648 | PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
649 | writel(*(u32*)&data, | ||
650 | base + j * PCI_MSIX_ENTRY_SIZE + | ||
651 | PCI_MSIX_ENTRY_DATA_OFFSET); | ||
652 | |||
653 | tail = msi_desc[vector]->link.tail; | ||
654 | vector = tail; | ||
655 | } | ||
656 | dev->irq = temp; | ||
657 | |||
658 | pci_write_config_word(dev, msi_control_reg(pos), save); | ||
659 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); | ||
660 | } | ||
661 | #endif | ||
662 | |||
663 | static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry) | ||
664 | { | ||
665 | struct msg_address address; | ||
666 | struct msg_data data; | ||
667 | int pos, vector = dev->irq; | ||
668 | u16 control; | ||
669 | |||
670 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | ||
671 | pci_read_config_word(dev, msi_control_reg(pos), &control); | ||
672 | /* Configure MSI capability structure */ | ||
673 | msi_address_init(&address); | ||
674 | msi_data_init(&data, vector); | ||
675 | entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >> | ||
676 | MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK); | ||
677 | pci_write_config_dword(dev, msi_lower_address_reg(pos), | ||
678 | address.lo_address.value); | ||
679 | if (is_64bit_address(control)) { | ||
680 | pci_write_config_dword(dev, | ||
681 | msi_upper_address_reg(pos), address.hi_address); | ||
682 | pci_write_config_word(dev, | ||
683 | msi_data_reg(pos, 1), *((u32*)&data)); | ||
684 | } else | ||
685 | pci_write_config_word(dev, | ||
686 | msi_data_reg(pos, 0), *((u32*)&data)); | ||
687 | if (entry->msi_attrib.maskbit) { | ||
688 | unsigned int maskbits, temp; | ||
689 | /* All MSIs are unmasked by default, Mask them all */ | ||
690 | pci_read_config_dword(dev, | ||
691 | msi_mask_bits_reg(pos, is_64bit_address(control)), | ||
692 | &maskbits); | ||
693 | temp = (1 << multi_msi_capable(control)); | ||
694 | temp = ((temp - 1) & ~temp); | ||
695 | maskbits |= temp; | ||
696 | pci_write_config_dword(dev, | ||
697 | msi_mask_bits_reg(pos, is_64bit_address(control)), | ||
698 | maskbits); | ||
699 | } | ||
700 | } | ||
701 | |||
507 | /** | 702 | /** |
508 | * msi_capability_init - configure device's MSI capability structure | 703 | * msi_capability_init - configure device's MSI capability structure |
509 | * @dev: pointer to the pci_dev data structure of MSI device function | 704 | * @dev: pointer to the pci_dev data structure of MSI device function |
@@ -516,8 +711,6 @@ void pci_scan_msi_device(struct pci_dev *dev) | |||
516 | static int msi_capability_init(struct pci_dev *dev) | 711 | static int msi_capability_init(struct pci_dev *dev) |
517 | { | 712 | { |
518 | struct msi_desc *entry; | 713 | struct msi_desc *entry; |
519 | struct msg_address address; | ||
520 | struct msg_data data; | ||
521 | int pos, vector; | 714 | int pos, vector; |
522 | u16 control; | 715 | u16 control; |
523 | 716 | ||
@@ -549,33 +742,8 @@ static int msi_capability_init(struct pci_dev *dev) | |||
549 | /* Replace with MSI handler */ | 742 | /* Replace with MSI handler */ |
550 | irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit); | 743 | irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit); |
551 | /* Configure MSI capability structure */ | 744 | /* Configure MSI capability structure */ |
552 | msi_address_init(&address); | 745 | msi_register_init(dev, entry); |
553 | msi_data_init(&data, vector); | 746 | |
554 | entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >> | ||
555 | MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK); | ||
556 | pci_write_config_dword(dev, msi_lower_address_reg(pos), | ||
557 | address.lo_address.value); | ||
558 | if (is_64bit_address(control)) { | ||
559 | pci_write_config_dword(dev, | ||
560 | msi_upper_address_reg(pos), address.hi_address); | ||
561 | pci_write_config_word(dev, | ||
562 | msi_data_reg(pos, 1), *((u32*)&data)); | ||
563 | } else | ||
564 | pci_write_config_word(dev, | ||
565 | msi_data_reg(pos, 0), *((u32*)&data)); | ||
566 | if (entry->msi_attrib.maskbit) { | ||
567 | unsigned int maskbits, temp; | ||
568 | /* All MSIs are unmasked by default, Mask them all */ | ||
569 | pci_read_config_dword(dev, | ||
570 | msi_mask_bits_reg(pos, is_64bit_address(control)), | ||
571 | &maskbits); | ||
572 | temp = (1 << multi_msi_capable(control)); | ||
573 | temp = ((temp - 1) & ~temp); | ||
574 | maskbits |= temp; | ||
575 | pci_write_config_dword(dev, | ||
576 | msi_mask_bits_reg(pos, is_64bit_address(control)), | ||
577 | maskbits); | ||
578 | } | ||
579 | attach_msi_entry(entry, vector); | 747 | attach_msi_entry(entry, vector); |
580 | /* Set MSI enabled bits */ | 748 | /* Set MSI enabled bits */ |
581 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | 749 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
@@ -625,8 +793,10 @@ static int msix_capability_init(struct pci_dev *dev, | |||
625 | if (!entry) | 793 | if (!entry) |
626 | break; | 794 | break; |
627 | vector = get_msi_vector(dev); | 795 | vector = get_msi_vector(dev); |
628 | if (vector < 0) | 796 | if (vector < 0) { |
797 | kmem_cache_free(msi_cachep, entry); | ||
629 | break; | 798 | break; |
799 | } | ||
630 | 800 | ||
631 | j = entries[i].entry; | 801 | j = entries[i].entry; |
632 | entries[i].vector = vector; | 802 | entries[i].vector = vector; |
@@ -731,6 +901,7 @@ int pci_enable_msi(struct pci_dev* dev) | |||
731 | vector_irq[dev->irq] = -1; | 901 | vector_irq[dev->irq] = -1; |
732 | nr_released_vectors--; | 902 | nr_released_vectors--; |
733 | spin_unlock_irqrestore(&msi_lock, flags); | 903 | spin_unlock_irqrestore(&msi_lock, flags); |
904 | msi_register_init(dev, msi_desc[dev->irq]); | ||
734 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | 905 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
735 | return 0; | 906 | return 0; |
736 | } | 907 | } |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 6917c6cb0912..c2ecae5ff0c1 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -33,13 +33,10 @@ acpi_query_osc ( | |||
33 | acpi_status status; | 33 | acpi_status status; |
34 | struct acpi_object_list input; | 34 | struct acpi_object_list input; |
35 | union acpi_object in_params[4]; | 35 | union acpi_object in_params[4]; |
36 | struct acpi_buffer output; | 36 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; |
37 | union acpi_object out_obj; | 37 | union acpi_object *out_obj; |
38 | u32 osc_dw0; | 38 | u32 osc_dw0; |
39 | 39 | ||
40 | /* Setting up output buffer */ | ||
41 | output.length = sizeof(out_obj) + 3*sizeof(u32); | ||
42 | output.pointer = &out_obj; | ||
43 | 40 | ||
44 | /* Setting up input parameters */ | 41 | /* Setting up input parameters */ |
45 | input.count = 4; | 42 | input.count = 4; |
@@ -61,12 +58,15 @@ acpi_query_osc ( | |||
61 | "Evaluate _OSC Set fails. Status = 0x%04x\n", status); | 58 | "Evaluate _OSC Set fails. Status = 0x%04x\n", status); |
62 | return status; | 59 | return status; |
63 | } | 60 | } |
64 | if (out_obj.type != ACPI_TYPE_BUFFER) { | 61 | out_obj = output.pointer; |
62 | |||
63 | if (out_obj->type != ACPI_TYPE_BUFFER) { | ||
65 | printk(KERN_DEBUG | 64 | printk(KERN_DEBUG |
66 | "Evaluate _OSC returns wrong type\n"); | 65 | "Evaluate _OSC returns wrong type\n"); |
67 | return AE_TYPE; | 66 | status = AE_TYPE; |
67 | goto query_osc_out; | ||
68 | } | 68 | } |
69 | osc_dw0 = *((u32 *) out_obj.buffer.pointer); | 69 | osc_dw0 = *((u32 *) out_obj->buffer.pointer); |
70 | if (osc_dw0) { | 70 | if (osc_dw0) { |
71 | if (osc_dw0 & OSC_REQUEST_ERROR) | 71 | if (osc_dw0 & OSC_REQUEST_ERROR) |
72 | printk(KERN_DEBUG "_OSC request fails\n"); | 72 | printk(KERN_DEBUG "_OSC request fails\n"); |
@@ -76,15 +76,21 @@ acpi_query_osc ( | |||
76 | printk(KERN_DEBUG "_OSC invalid revision\n"); | 76 | printk(KERN_DEBUG "_OSC invalid revision\n"); |
77 | if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { | 77 | if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { |
78 | /* Update Global Control Set */ | 78 | /* Update Global Control Set */ |
79 | global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8)); | 79 | global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8)); |
80 | return AE_OK; | 80 | status = AE_OK; |
81 | goto query_osc_out; | ||
81 | } | 82 | } |
82 | return AE_ERROR; | 83 | status = AE_ERROR; |
84 | goto query_osc_out; | ||
83 | } | 85 | } |
84 | 86 | ||
85 | /* Update Global Control Set */ | 87 | /* Update Global Control Set */ |
86 | global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8)); | 88 | global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); |
87 | return AE_OK; | 89 | status = AE_OK; |
90 | |||
91 | query_osc_out: | ||
92 | kfree(output.pointer); | ||
93 | return status; | ||
88 | } | 94 | } |
89 | 95 | ||
90 | 96 | ||
@@ -96,14 +102,10 @@ acpi_run_osc ( | |||
96 | acpi_status status; | 102 | acpi_status status; |
97 | struct acpi_object_list input; | 103 | struct acpi_object_list input; |
98 | union acpi_object in_params[4]; | 104 | union acpi_object in_params[4]; |
99 | struct acpi_buffer output; | 105 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; |
100 | union acpi_object out_obj; | 106 | union acpi_object *out_obj; |
101 | u32 osc_dw0; | 107 | u32 osc_dw0; |
102 | 108 | ||
103 | /* Setting up output buffer */ | ||
104 | output.length = sizeof(out_obj) + 3*sizeof(u32); | ||
105 | output.pointer = &out_obj; | ||
106 | |||
107 | /* Setting up input parameters */ | 109 | /* Setting up input parameters */ |
108 | input.count = 4; | 110 | input.count = 4; |
109 | input.pointer = in_params; | 111 | input.pointer = in_params; |
@@ -124,12 +126,14 @@ acpi_run_osc ( | |||
124 | "Evaluate _OSC Set fails. Status = 0x%04x\n", status); | 126 | "Evaluate _OSC Set fails. Status = 0x%04x\n", status); |
125 | return status; | 127 | return status; |
126 | } | 128 | } |
127 | if (out_obj.type != ACPI_TYPE_BUFFER) { | 129 | out_obj = output.pointer; |
130 | if (out_obj->type != ACPI_TYPE_BUFFER) { | ||
128 | printk(KERN_DEBUG | 131 | printk(KERN_DEBUG |
129 | "Evaluate _OSC returns wrong type\n"); | 132 | "Evaluate _OSC returns wrong type\n"); |
130 | return AE_TYPE; | 133 | status = AE_TYPE; |
134 | goto run_osc_out; | ||
131 | } | 135 | } |
132 | osc_dw0 = *((u32 *) out_obj.buffer.pointer); | 136 | osc_dw0 = *((u32 *) out_obj->buffer.pointer); |
133 | if (osc_dw0) { | 137 | if (osc_dw0) { |
134 | if (osc_dw0 & OSC_REQUEST_ERROR) | 138 | if (osc_dw0 & OSC_REQUEST_ERROR) |
135 | printk(KERN_DEBUG "_OSC request fails\n"); | 139 | printk(KERN_DEBUG "_OSC request fails\n"); |
@@ -139,11 +143,17 @@ acpi_run_osc ( | |||
139 | printk(KERN_DEBUG "_OSC invalid revision\n"); | 143 | printk(KERN_DEBUG "_OSC invalid revision\n"); |
140 | if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { | 144 | if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { |
141 | printk(KERN_DEBUG "_OSC FW not grant req. control\n"); | 145 | printk(KERN_DEBUG "_OSC FW not grant req. control\n"); |
142 | return AE_SUPPORT; | 146 | status = AE_SUPPORT; |
147 | goto run_osc_out; | ||
143 | } | 148 | } |
144 | return AE_ERROR; | 149 | status = AE_ERROR; |
150 | goto run_osc_out; | ||
145 | } | 151 | } |
146 | return AE_OK; | 152 | status = AE_OK; |
153 | |||
154 | run_osc_out: | ||
155 | kfree(output.pointer); | ||
156 | return status; | ||
147 | } | 157 | } |
148 | 158 | ||
149 | /** | 159 | /** |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index f22f69ac6445..1456759936c5 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -271,10 +271,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state) | |||
271 | struct pci_driver * drv = pci_dev->driver; | 271 | struct pci_driver * drv = pci_dev->driver; |
272 | int i = 0; | 272 | int i = 0; |
273 | 273 | ||
274 | if (drv && drv->suspend) | 274 | if (drv && drv->suspend) { |
275 | i = drv->suspend(pci_dev, state); | 275 | i = drv->suspend(pci_dev, state); |
276 | else | 276 | suspend_report_result(drv->suspend, i); |
277 | } else { | ||
277 | pci_save_state(pci_dev); | 278 | pci_save_state(pci_dev); |
279 | } | ||
278 | return i; | 280 | return i; |
279 | } | 281 | } |
280 | 282 | ||
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bea1ad1ad5ba..2329f941a0dc 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -307,9 +307,11 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
307 | * Can enter D0 from any state, but if we can only go deeper | 307 | * Can enter D0 from any state, but if we can only go deeper |
308 | * to sleep if we're already in a low power state | 308 | * to sleep if we're already in a low power state |
309 | */ | 309 | */ |
310 | if (state != PCI_D0 && dev->current_state > state) | 310 | if (state != PCI_D0 && dev->current_state > state) { |
311 | printk(KERN_ERR "%s(): %s: state=%d, current state=%d\n", | ||
312 | __FUNCTION__, pci_name(dev), state, dev->current_state); | ||
311 | return -EINVAL; | 313 | return -EINVAL; |
312 | else if (dev->current_state == state) | 314 | } else if (dev->current_state == state) |
313 | return 0; /* we're already there */ | 315 | return 0; /* we're already there */ |
314 | 316 | ||
315 | /* find PCI PM capability in list */ | 317 | /* find PCI PM capability in list */ |
@@ -444,6 +446,10 @@ pci_save_state(struct pci_dev *dev) | |||
444 | /* XXX: 100% dword access ok here? */ | 446 | /* XXX: 100% dword access ok here? */ |
445 | for (i = 0; i < 16; i++) | 447 | for (i = 0; i < 16; i++) |
446 | pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); | 448 | pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); |
449 | if ((i = pci_save_msi_state(dev)) != 0) | ||
450 | return i; | ||
451 | if ((i = pci_save_msix_state(dev)) != 0) | ||
452 | return i; | ||
447 | return 0; | 453 | return 0; |
448 | } | 454 | } |
449 | 455 | ||
@@ -458,6 +464,8 @@ pci_restore_state(struct pci_dev *dev) | |||
458 | 464 | ||
459 | for (i = 0; i < 16; i++) | 465 | for (i = 0; i < 16; i++) |
460 | pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]); | 466 | pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]); |
467 | pci_restore_msi_state(dev); | ||
468 | pci_restore_msix_state(dev); | ||
461 | return 0; | 469 | return 0; |
462 | } | 470 | } |
463 | 471 | ||
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 8f3fb47ea671..30630cbe2fe3 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -55,6 +55,17 @@ void pci_no_msi(void); | |||
55 | static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { } | 55 | static inline void disable_msi_mode(struct pci_dev *dev, int pos, int type) { } |
56 | static inline void pci_no_msi(void) { } | 56 | static inline void pci_no_msi(void) { } |
57 | #endif | 57 | #endif |
58 | #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM) | ||
59 | int pci_save_msi_state(struct pci_dev *dev); | ||
60 | int pci_save_msix_state(struct pci_dev *dev); | ||
61 | void pci_restore_msi_state(struct pci_dev *dev); | ||
62 | void pci_restore_msix_state(struct pci_dev *dev); | ||
63 | #else | ||
64 | static inline int pci_save_msi_state(struct pci_dev *dev) { return 0; } | ||
65 | static inline int pci_save_msix_state(struct pci_dev *dev) { return 0; } | ||
66 | static inline void pci_restore_msi_state(struct pci_dev *dev) {} | ||
67 | static inline void pci_restore_msix_state(struct pci_dev *dev) {} | ||
68 | #endif | ||
58 | 69 | ||
59 | extern int pcie_mch_quirk; | 70 | extern int pcie_mch_quirk; |
60 | extern struct device_attribute pci_dev_attrs[]; | 71 | extern struct device_attribute pci_dev_attrs[]; |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4970f47be72c..d378478612fb 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -592,7 +592,7 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) | |||
592 | pci_write_config_byte( dev, AMD8131_MISC, tmp); | 592 | pci_write_config_byte( dev, AMD8131_MISC, tmp); |
593 | } | 593 | } |
594 | } | 594 | } |
595 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, quirk_amd_8131_ioapic ); | 595 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); |
596 | 596 | ||
597 | static void __init quirk_svw_msi(struct pci_dev *dev) | 597 | static void __init quirk_svw_msi(struct pci_dev *dev) |
598 | { | 598 | { |
@@ -634,6 +634,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vi | |||
634 | * non-x86 architectures (yes Via exists on PPC among other places), | 634 | * non-x86 architectures (yes Via exists on PPC among other places), |
635 | * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get | 635 | * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get |
636 | * interrupts delivered properly. | 636 | * interrupts delivered properly. |
637 | * | ||
638 | * Some of the on-chip devices are actually '586 devices' so they are | ||
639 | * listed here. | ||
637 | */ | 640 | */ |
638 | static void quirk_via_irq(struct pci_dev *dev) | 641 | static void quirk_via_irq(struct pci_dev *dev) |
639 | { | 642 | { |
@@ -642,13 +645,19 @@ static void quirk_via_irq(struct pci_dev *dev) | |||
642 | new_irq = dev->irq & 0xf; | 645 | new_irq = dev->irq & 0xf; |
643 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); | 646 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); |
644 | if (new_irq != irq) { | 647 | if (new_irq != irq) { |
645 | printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n", | 648 | printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n", |
646 | pci_name(dev), irq, new_irq); | 649 | pci_name(dev), irq, new_irq); |
647 | udelay(15); /* unknown if delay really needed */ | 650 | udelay(15); /* unknown if delay really needed */ |
648 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); | 651 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); |
649 | } | 652 | } |
650 | } | 653 | } |
651 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq); | 654 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_via_irq); |
655 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq); | ||
656 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq); | ||
657 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq); | ||
658 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq); | ||
659 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq); | ||
660 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq); | ||
652 | 661 | ||
653 | /* | 662 | /* |
654 | * VIA VT82C598 has its device ID settable and many BIOSes | 663 | * VIA VT82C598 has its device ID settable and many BIOSes |
@@ -865,6 +874,36 @@ static void __init quirk_eisa_bridge(struct pci_dev *dev) | |||
865 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge ); | 874 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge ); |
866 | 875 | ||
867 | /* | 876 | /* |
877 | * On the MSI-K8T-Neo2Fir Board, the internal Soundcard is disabled | ||
878 | * when a PCI-Soundcard is added. The BIOS only gives Options | ||
879 | * "Disabled" and "AUTO". This Quirk Sets the corresponding | ||
880 | * Register-Value to enable the Soundcard. | ||
881 | */ | ||
882 | static void __init k8t_sound_hostbridge(struct pci_dev *dev) | ||
883 | { | ||
884 | unsigned char val; | ||
885 | |||
886 | printk(KERN_INFO "PCI: Quirk-MSI-K8T Soundcard On\n"); | ||
887 | pci_read_config_byte(dev, 0x50, &val); | ||
888 | if (val == 0x88 || val == 0xc8) { | ||
889 | pci_write_config_byte(dev, 0x50, val & (~0x40)); | ||
890 | |||
891 | /* Verify the Change for Status output */ | ||
892 | pci_read_config_byte(dev, 0x50, &val); | ||
893 | if (val & 0x40) | ||
894 | printk(KERN_INFO "PCI: MSI-K8T soundcard still off\n"); | ||
895 | else | ||
896 | printk(KERN_INFO "PCI: MSI-K8T soundcard on\n"); | ||
897 | } else { | ||
898 | printk(KERN_INFO "PCI: Unexpected Value in PCI-Register: " | ||
899 | "no Change!\n"); | ||
900 | } | ||
901 | |||
902 | } | ||
903 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge); | ||
904 | |||
905 | #ifndef CONFIG_ACPI_SLEEP | ||
906 | /* | ||
868 | * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge | 907 | * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge |
869 | * is not activated. The myth is that Asus said that they do not want the | 908 | * is not activated. The myth is that Asus said that they do not want the |
870 | * users to be irritated by just another PCI Device in the Win98 device | 909 | * users to be irritated by just another PCI Device in the Win98 device |
@@ -875,8 +914,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_e | |||
875 | * bridge. Unfortunately, this device has no subvendor/subdevice ID. So it | 914 | * bridge. Unfortunately, this device has no subvendor/subdevice ID. So it |
876 | * becomes necessary to do this tweak in two steps -- I've chosen the Host | 915 | * becomes necessary to do this tweak in two steps -- I've chosen the Host |
877 | * bridge as trigger. | 916 | * bridge as trigger. |
917 | * | ||
918 | * Actually, leaving it unhidden and not redoing the quirk over suspend2ram | ||
919 | * will cause thermal management to break down, and causing machine to | ||
920 | * overheat. | ||
878 | */ | 921 | */ |
879 | static int __initdata asus_hides_smbus = 0; | 922 | static int __initdata asus_hides_smbus; |
880 | 923 | ||
881 | static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) | 924 | static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) |
882 | { | 925 | { |
@@ -921,6 +964,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) | |||
921 | if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) { | 964 | if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) { |
922 | switch (dev->subsystem_device) { | 965 | switch (dev->subsystem_device) { |
923 | case 0x1882: /* M6V notebook */ | 966 | case 0x1882: /* M6V notebook */ |
967 | case 0x1977: /* A6VA notebook */ | ||
924 | asus_hides_smbus = 1; | 968 | asus_hides_smbus = 1; |
925 | } | 969 | } |
926 | } | 970 | } |
@@ -999,6 +1043,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asu | |||
999 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc ); | 1043 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc ); |
1000 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc ); | 1044 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc ); |
1001 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc ); | 1045 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc ); |
1046 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc ); | ||
1002 | 1047 | ||
1003 | static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev) | 1048 | static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev) |
1004 | { | 1049 | { |
@@ -1017,6 +1062,8 @@ static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev) | |||
1017 | } | 1062 | } |
1018 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 ); | 1063 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 ); |
1019 | 1064 | ||
1065 | #endif | ||
1066 | |||
1020 | /* | 1067 | /* |
1021 | * SiS 96x south bridge: BIOS typically hides SMBus device... | 1068 | * SiS 96x south bridge: BIOS typically hides SMBus device... |
1022 | */ | 1069 | */ |