diff options
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r-- | drivers/pci/pcie/portdrv.h | 1 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_pci.c | 66 |
2 files changed, 4 insertions, 63 deletions
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index a63bd8f72601..1d317d22ee89 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h | |||
@@ -29,7 +29,6 @@ | |||
29 | 29 | ||
30 | struct pcie_port_device_ext { | 30 | struct pcie_port_device_ext { |
31 | int interrupt_mode; /* [0:INTx | 1:MSI | 2:MSI-X] */ | 31 | int interrupt_mode; /* [0:INTx | 1:MSI | 2:MSI-X] */ |
32 | unsigned int saved_msi_config_space[5]; | ||
33 | }; | 32 | }; |
34 | 33 | ||
35 | extern struct bus_type pcie_port_bus_type; | 34 | extern struct bus_type pcie_port_bus_type; |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 02260141dc81..50bfc1b2f3bf 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
@@ -30,75 +30,16 @@ MODULE_LICENSE("GPL"); | |||
30 | /* global data */ | 30 | /* global data */ |
31 | static const char device_name[] = "pcieport-driver"; | 31 | static const char device_name[] = "pcieport-driver"; |
32 | 32 | ||
33 | static void pci_save_msi_state(struct pci_dev *dev) | 33 | static int pcie_portdrv_save_config(struct pci_dev *dev) |
34 | { | 34 | { |
35 | struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); | 35 | return pci_save_state(dev); |
36 | int i = 0, pos; | ||
37 | u16 control; | ||
38 | |||
39 | if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0) | ||
40 | return; | ||
41 | |||
42 | pci_read_config_dword(dev, pos, &p_ext->saved_msi_config_space[i++]); | ||
43 | control = p_ext->saved_msi_config_space[0] >> 16; | ||
44 | pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, | ||
45 | &p_ext->saved_msi_config_space[i++]); | ||
46 | if (control & PCI_MSI_FLAGS_64BIT) { | ||
47 | pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, | ||
48 | &p_ext->saved_msi_config_space[i++]); | ||
49 | pci_read_config_dword(dev, pos + PCI_MSI_DATA_64, | ||
50 | &p_ext->saved_msi_config_space[i++]); | ||
51 | } else | ||
52 | pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, | ||
53 | &p_ext->saved_msi_config_space[i++]); | ||
54 | if (control & PCI_MSI_FLAGS_MASKBIT) | ||
55 | pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, | ||
56 | &p_ext->saved_msi_config_space[i++]); | ||
57 | } | ||
58 | |||
59 | static void pci_restore_msi_state(struct pci_dev *dev) | ||
60 | { | ||
61 | struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); | ||
62 | int i = 0, pos; | ||
63 | u16 control; | ||
64 | |||
65 | if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0) | ||
66 | return; | ||
67 | |||
68 | control = p_ext->saved_msi_config_space[i++] >> 16; | ||
69 | pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); | ||
70 | pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, | ||
71 | p_ext->saved_msi_config_space[i++]); | ||
72 | if (control & PCI_MSI_FLAGS_64BIT) { | ||
73 | pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, | ||
74 | p_ext->saved_msi_config_space[i++]); | ||
75 | pci_write_config_dword(dev, pos + PCI_MSI_DATA_64, | ||
76 | p_ext->saved_msi_config_space[i++]); | ||
77 | } else | ||
78 | pci_write_config_dword(dev, pos + PCI_MSI_DATA_32, | ||
79 | p_ext->saved_msi_config_space[i++]); | ||
80 | if (control & PCI_MSI_FLAGS_MASKBIT) | ||
81 | pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT, | ||
82 | p_ext->saved_msi_config_space[i++]); | ||
83 | } | ||
84 | |||
85 | static void pcie_portdrv_save_config(struct pci_dev *dev) | ||
86 | { | ||
87 | struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); | ||
88 | |||
89 | pci_save_state(dev); | ||
90 | if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE) | ||
91 | pci_save_msi_state(dev); | ||
92 | } | 36 | } |
93 | 37 | ||
94 | static int pcie_portdrv_restore_config(struct pci_dev *dev) | 38 | static int pcie_portdrv_restore_config(struct pci_dev *dev) |
95 | { | 39 | { |
96 | struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev); | ||
97 | int retval; | 40 | int retval; |
98 | 41 | ||
99 | pci_restore_state(dev); | 42 | pci_restore_state(dev); |
100 | if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE) | ||
101 | pci_restore_msi_state(dev); | ||
102 | retval = pci_enable_device(dev); | 43 | retval = pci_enable_device(dev); |
103 | if (retval) | 44 | if (retval) |
104 | return retval; | 45 | return retval; |
@@ -149,7 +90,8 @@ static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state) | |||
149 | { | 90 | { |
150 | int ret = pcie_port_device_suspend(dev, state); | 91 | int ret = pcie_port_device_suspend(dev, state); |
151 | 92 | ||
152 | pcie_portdrv_save_config(dev); | 93 | if (!ret) |
94 | ret = pcie_portdrv_save_config(dev); | ||
153 | return ret; | 95 | return ret; |
154 | } | 96 | } |
155 | 97 | ||