diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-01 22:29:33 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-01 22:29:33 -0500 |
commit | 215e871aaa3d94540121a3809d80d0c5e5686e4f (patch) | |
tree | 0ed6469c5ad04db8cfa0edb58c676d5155df20cd /drivers/pci/pci.c | |
parent | b6cf160c4b788a31f6a4017a469b956ca77febf4 (diff) | |
parent | fd7d1ced29e5beb88c9068801da7a362606d8273 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/pci-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/pci-2.6: (64 commits)
PCI: make pci_bus a struct device
PCI: fix codingstyle issues in include/linux/pci.h
PCI: fix codingstyle issues in drivers/pci/pci.h
PCI: PCIE ASPM support
PCI: Fix fakephp deadlock
PCI: modify SB700 SATA MSI quirk
PCI: Run ACPI _OSC method on root bridges only
PCI ACPI: AER driver should only register PCIe devices with _OSC
PCI ACPI: Added a function to register _OSC with only PCIe devices.
PCI: constify function pointer tables
PCI: Convert drivers/pci/proc.c to use unlocked_ioctl
pciehp: block new requests from the device before power off
pciehp: workaround against Bad DLLP during power off
pciehp: wait for 1000ms before LED operation after power off
PCI: Remove pci_enable_device_bars() from documentation
PCI: Remove pci_enable_device_bars()
PCI: Remove users of pci_enable_device_bars()
PCI: Add pci_enable_device_{io,mem} intefaces
PCI: avoid save the same type of cap multiple times
PCI: correctly initialize a structure for pcie_save_pcix_state()
...
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 93 |
1 files changed, 75 insertions, 18 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7d4ce906d207..b3e9294e4a0e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/log2.h> | 20 | #include <linux/log2.h> |
21 | #include <linux/aspm.h> | ||
21 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | 22 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ |
22 | #include "pci.h" | 23 | #include "pci.h" |
23 | 24 | ||
@@ -314,6 +315,24 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap) | |||
314 | } | 315 | } |
315 | EXPORT_SYMBOL_GPL(pci_find_ht_capability); | 316 | EXPORT_SYMBOL_GPL(pci_find_ht_capability); |
316 | 317 | ||
318 | void pcie_wait_pending_transaction(struct pci_dev *dev) | ||
319 | { | ||
320 | int pos; | ||
321 | u16 reg16; | ||
322 | |||
323 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
324 | if (!pos) | ||
325 | return; | ||
326 | while (1) { | ||
327 | pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, ®16); | ||
328 | if (!(reg16 & PCI_EXP_DEVSTA_TRPND)) | ||
329 | break; | ||
330 | cpu_relax(); | ||
331 | } | ||
332 | |||
333 | } | ||
334 | EXPORT_SYMBOL_GPL(pcie_wait_pending_transaction); | ||
335 | |||
317 | /** | 336 | /** |
318 | * pci_find_parent_resource - return resource region of parent bus of given region | 337 | * pci_find_parent_resource - return resource region of parent bus of given region |
319 | * @dev: PCI device structure contains resources to be searched | 338 | * @dev: PCI device structure contains resources to be searched |
@@ -353,7 +372,7 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) | |||
353 | * Restore the BAR values for a given device, so as to make it | 372 | * Restore the BAR values for a given device, so as to make it |
354 | * accessible by its driver. | 373 | * accessible by its driver. |
355 | */ | 374 | */ |
356 | void | 375 | static void |
357 | pci_restore_bars(struct pci_dev *dev) | 376 | pci_restore_bars(struct pci_dev *dev) |
358 | { | 377 | { |
359 | int i, numres; | 378 | int i, numres; |
@@ -501,6 +520,9 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
501 | if (need_restore) | 520 | if (need_restore) |
502 | pci_restore_bars(dev); | 521 | pci_restore_bars(dev); |
503 | 522 | ||
523 | if (dev->bus->self) | ||
524 | pcie_aspm_pm_state_change(dev->bus->self); | ||
525 | |||
504 | return 0; | 526 | return 0; |
505 | } | 527 | } |
506 | 528 | ||
@@ -551,6 +573,7 @@ static int pci_save_pcie_state(struct pci_dev *dev) | |||
551 | int pos, i = 0; | 573 | int pos, i = 0; |
552 | struct pci_cap_saved_state *save_state; | 574 | struct pci_cap_saved_state *save_state; |
553 | u16 *cap; | 575 | u16 *cap; |
576 | int found = 0; | ||
554 | 577 | ||
555 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | 578 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); |
556 | if (pos <= 0) | 579 | if (pos <= 0) |
@@ -559,6 +582,8 @@ static int pci_save_pcie_state(struct pci_dev *dev) | |||
559 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); | 582 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); |
560 | if (!save_state) | 583 | if (!save_state) |
561 | save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL); | 584 | save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL); |
585 | else | ||
586 | found = 1; | ||
562 | if (!save_state) { | 587 | if (!save_state) { |
563 | dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n"); | 588 | dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n"); |
564 | return -ENOMEM; | 589 | return -ENOMEM; |
@@ -569,7 +594,9 @@ static int pci_save_pcie_state(struct pci_dev *dev) | |||
569 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); | 594 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); |
570 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); | 595 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); |
571 | pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); | 596 | pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); |
572 | pci_add_saved_cap(dev, save_state); | 597 | save_state->cap_nr = PCI_CAP_ID_EXP; |
598 | if (!found) | ||
599 | pci_add_saved_cap(dev, save_state); | ||
573 | return 0; | 600 | return 0; |
574 | } | 601 | } |
575 | 602 | ||
@@ -597,14 +624,17 @@ static int pci_save_pcix_state(struct pci_dev *dev) | |||
597 | int pos, i = 0; | 624 | int pos, i = 0; |
598 | struct pci_cap_saved_state *save_state; | 625 | struct pci_cap_saved_state *save_state; |
599 | u16 *cap; | 626 | u16 *cap; |
627 | int found = 0; | ||
600 | 628 | ||
601 | pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); | 629 | pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); |
602 | if (pos <= 0) | 630 | if (pos <= 0) |
603 | return 0; | 631 | return 0; |
604 | 632 | ||
605 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); | 633 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); |
606 | if (!save_state) | 634 | if (!save_state) |
607 | save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL); | 635 | save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL); |
636 | else | ||
637 | found = 1; | ||
608 | if (!save_state) { | 638 | if (!save_state) { |
609 | dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n"); | 639 | dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n"); |
610 | return -ENOMEM; | 640 | return -ENOMEM; |
@@ -612,7 +642,9 @@ static int pci_save_pcix_state(struct pci_dev *dev) | |||
612 | cap = (u16 *)&save_state->data[0]; | 642 | cap = (u16 *)&save_state->data[0]; |
613 | 643 | ||
614 | pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]); | 644 | pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]); |
615 | pci_add_saved_cap(dev, save_state); | 645 | save_state->cap_nr = PCI_CAP_ID_PCIX; |
646 | if (!found) | ||
647 | pci_add_saved_cap(dev, save_state); | ||
616 | return 0; | 648 | return 0; |
617 | } | 649 | } |
618 | 650 | ||
@@ -713,23 +745,19 @@ int pci_reenable_device(struct pci_dev *dev) | |||
713 | return 0; | 745 | return 0; |
714 | } | 746 | } |
715 | 747 | ||
716 | /** | 748 | static int __pci_enable_device_flags(struct pci_dev *dev, |
717 | * pci_enable_device_bars - Initialize some of a device for use | 749 | resource_size_t flags) |
718 | * @dev: PCI device to be initialized | ||
719 | * @bars: bitmask of BAR's that must be configured | ||
720 | * | ||
721 | * Initialize device before it's used by a driver. Ask low-level code | ||
722 | * to enable selected I/O and memory resources. Wake up the device if it | ||
723 | * was suspended. Beware, this function can fail. | ||
724 | */ | ||
725 | int | ||
726 | pci_enable_device_bars(struct pci_dev *dev, int bars) | ||
727 | { | 750 | { |
728 | int err; | 751 | int err; |
752 | int i, bars = 0; | ||
729 | 753 | ||
730 | if (atomic_add_return(1, &dev->enable_cnt) > 1) | 754 | if (atomic_add_return(1, &dev->enable_cnt) > 1) |
731 | return 0; /* already enabled */ | 755 | return 0; /* already enabled */ |
732 | 756 | ||
757 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) | ||
758 | if (dev->resource[i].flags & flags) | ||
759 | bars |= (1 << i); | ||
760 | |||
733 | err = do_pci_enable_device(dev, bars); | 761 | err = do_pci_enable_device(dev, bars); |
734 | if (err < 0) | 762 | if (err < 0) |
735 | atomic_dec(&dev->enable_cnt); | 763 | atomic_dec(&dev->enable_cnt); |
@@ -737,6 +765,32 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) | |||
737 | } | 765 | } |
738 | 766 | ||
739 | /** | 767 | /** |
768 | * pci_enable_device_io - Initialize a device for use with IO space | ||
769 | * @dev: PCI device to be initialized | ||
770 | * | ||
771 | * Initialize device before it's used by a driver. Ask low-level code | ||
772 | * to enable I/O resources. Wake up the device if it was suspended. | ||
773 | * Beware, this function can fail. | ||
774 | */ | ||
775 | int pci_enable_device_io(struct pci_dev *dev) | ||
776 | { | ||
777 | return __pci_enable_device_flags(dev, IORESOURCE_IO); | ||
778 | } | ||
779 | |||
780 | /** | ||
781 | * pci_enable_device_mem - Initialize a device for use with Memory space | ||
782 | * @dev: PCI device to be initialized | ||
783 | * | ||
784 | * Initialize device before it's used by a driver. Ask low-level code | ||
785 | * to enable Memory resources. Wake up the device if it was suspended. | ||
786 | * Beware, this function can fail. | ||
787 | */ | ||
788 | int pci_enable_device_mem(struct pci_dev *dev) | ||
789 | { | ||
790 | return __pci_enable_device_flags(dev, IORESOURCE_MEM); | ||
791 | } | ||
792 | |||
793 | /** | ||
740 | * pci_enable_device - Initialize device before it's used by a driver. | 794 | * pci_enable_device - Initialize device before it's used by a driver. |
741 | * @dev: PCI device to be initialized | 795 | * @dev: PCI device to be initialized |
742 | * | 796 | * |
@@ -749,7 +803,7 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) | |||
749 | */ | 803 | */ |
750 | int pci_enable_device(struct pci_dev *dev) | 804 | int pci_enable_device(struct pci_dev *dev) |
751 | { | 805 | { |
752 | return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); | 806 | return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO); |
753 | } | 807 | } |
754 | 808 | ||
755 | /* | 809 | /* |
@@ -885,6 +939,9 @@ pci_disable_device(struct pci_dev *dev) | |||
885 | if (atomic_sub_return(1, &dev->enable_cnt) != 0) | 939 | if (atomic_sub_return(1, &dev->enable_cnt) != 0) |
886 | return; | 940 | return; |
887 | 941 | ||
942 | /* Wait for all transactions are finished before disabling the device */ | ||
943 | pcie_wait_pending_transaction(dev); | ||
944 | |||
888 | pci_read_config_word(dev, PCI_COMMAND, &pci_command); | 945 | pci_read_config_word(dev, PCI_COMMAND, &pci_command); |
889 | if (pci_command & PCI_COMMAND_MASTER) { | 946 | if (pci_command & PCI_COMMAND_MASTER) { |
890 | pci_command &= ~PCI_COMMAND_MASTER; | 947 | pci_command &= ~PCI_COMMAND_MASTER; |
@@ -1619,9 +1676,9 @@ early_param("pci", pci_setup); | |||
1619 | 1676 | ||
1620 | device_initcall(pci_init); | 1677 | device_initcall(pci_init); |
1621 | 1678 | ||
1622 | EXPORT_SYMBOL_GPL(pci_restore_bars); | ||
1623 | EXPORT_SYMBOL(pci_reenable_device); | 1679 | EXPORT_SYMBOL(pci_reenable_device); |
1624 | EXPORT_SYMBOL(pci_enable_device_bars); | 1680 | EXPORT_SYMBOL(pci_enable_device_io); |
1681 | EXPORT_SYMBOL(pci_enable_device_mem); | ||
1625 | EXPORT_SYMBOL(pci_enable_device); | 1682 | EXPORT_SYMBOL(pci_enable_device); |
1626 | EXPORT_SYMBOL(pcim_enable_device); | 1683 | EXPORT_SYMBOL(pcim_enable_device); |
1627 | EXPORT_SYMBOL(pcim_pin_device); | 1684 | EXPORT_SYMBOL(pcim_pin_device); |