diff options
author | Gavin Shan <gwshan@linux.vnet.ibm.com> | 2016-05-20 02:41:41 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2016-06-21 01:30:58 -0400 |
commit | ea0d856cb26d4d78b9529de49a0f89379224e2f9 (patch) | |
tree | 3bc16ada897bb1289a663e07177a08eef5ac4a31 | |
parent | 7e19bf32c8ac977e7702a67d7392a3e0a9644bc8 (diff) |
powerpc/powernv: Functions to get/set PCI slot state
This exports 4 functions, which base on the corresponding OPAL
APIs to get/set PCI slot status. Those functions are going to
be used by PowerNV PCI hotplug driver:
pnv_pci_get_device_tree() opal_get_device_tree()
pnv_pci_get_presence_state() opal_pci_get_presence_state()
pnv_pci_get_power_state() opal_pci_get_power_state()
pnv_pci_set_power_state() opal_pci_set_power_state()
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r-- | arch/powerpc/include/asm/opal-api.h | 18 | ||||
-rw-r--r-- | arch/powerpc/include/asm/opal.h | 6 | ||||
-rw-r--r-- | arch/powerpc/include/asm/pnv-pci.h | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/opal-wrappers.S | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci.c | 82 |
5 files changed, 115 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index cd9371b33f1a..72b5f27cd0b8 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h | |||
@@ -158,7 +158,11 @@ | |||
158 | #define OPAL_LEDS_SET_INDICATOR 115 | 158 | #define OPAL_LEDS_SET_INDICATOR 115 |
159 | #define OPAL_CEC_REBOOT2 116 | 159 | #define OPAL_CEC_REBOOT2 116 |
160 | #define OPAL_CONSOLE_FLUSH 117 | 160 | #define OPAL_CONSOLE_FLUSH 117 |
161 | #define OPAL_LAST 117 | 161 | #define OPAL_GET_DEVICE_TREE 118 |
162 | #define OPAL_PCI_GET_PRESENCE_STATE 119 | ||
163 | #define OPAL_PCI_GET_POWER_STATE 120 | ||
164 | #define OPAL_PCI_SET_POWER_STATE 121 | ||
165 | #define OPAL_LAST 121 | ||
162 | 166 | ||
163 | /* Device tree flags */ | 167 | /* Device tree flags */ |
164 | 168 | ||
@@ -344,6 +348,18 @@ enum OpalPciResetState { | |||
344 | OPAL_ASSERT_RESET = 1 | 348 | OPAL_ASSERT_RESET = 1 |
345 | }; | 349 | }; |
346 | 350 | ||
351 | enum OpalPciSlotPresence { | ||
352 | OPAL_PCI_SLOT_EMPTY = 0, | ||
353 | OPAL_PCI_SLOT_PRESENT = 1 | ||
354 | }; | ||
355 | |||
356 | enum OpalPciSlotPower { | ||
357 | OPAL_PCI_SLOT_POWER_OFF = 0, | ||
358 | OPAL_PCI_SLOT_POWER_ON = 1, | ||
359 | OPAL_PCI_SLOT_OFFLINE = 2, | ||
360 | OPAL_PCI_SLOT_ONLINE = 3 | ||
361 | }; | ||
362 | |||
347 | enum OpalSlotLedType { | 363 | enum OpalSlotLedType { |
348 | OPAL_SLOT_LED_TYPE_ID = 0, /* IDENTIFY LED */ | 364 | OPAL_SLOT_LED_TYPE_ID = 0, /* IDENTIFY LED */ |
349 | OPAL_SLOT_LED_TYPE_FAULT = 1, /* FAULT LED */ | 365 | OPAL_SLOT_LED_TYPE_FAULT = 1, /* FAULT LED */ |
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 348132c00601..fa71fea3b6ee 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h | |||
@@ -209,6 +209,12 @@ int64_t opal_flash_write(uint64_t id, uint64_t offset, uint64_t buf, | |||
209 | uint64_t size, uint64_t token); | 209 | uint64_t size, uint64_t token); |
210 | int64_t opal_flash_erase(uint64_t id, uint64_t offset, uint64_t size, | 210 | int64_t opal_flash_erase(uint64_t id, uint64_t offset, uint64_t size, |
211 | uint64_t token); | 211 | uint64_t token); |
212 | int64_t opal_get_device_tree(uint32_t phandle, uint64_t buf, uint64_t len); | ||
213 | int64_t opal_pci_get_presence_state(uint64_t id, uint64_t data); | ||
214 | int64_t opal_pci_get_power_state(uint64_t id, uint64_t data); | ||
215 | int64_t opal_pci_set_power_state(uint64_t async_token, uint64_t id, | ||
216 | uint64_t data); | ||
217 | int64_t opal_pci_poll2(uint64_t id, uint64_t data); | ||
212 | 218 | ||
213 | /* Internal functions */ | 219 | /* Internal functions */ |
214 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, | 220 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, |
diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h index 810cc9a8169f..791db1bbd4b9 100644 --- a/arch/powerpc/include/asm/pnv-pci.h +++ b/arch/powerpc/include/asm/pnv-pci.h | |||
@@ -12,12 +12,18 @@ | |||
12 | 12 | ||
13 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
14 | #include <misc/cxl-base.h> | 14 | #include <misc/cxl-base.h> |
15 | #include <asm/opal-api.h> | ||
15 | 16 | ||
16 | #define PCI_SLOT_ID_PREFIX 0x8000000000000000 | 17 | #define PCI_SLOT_ID_PREFIX 0x8000000000000000 |
17 | #define PCI_SLOT_ID(phb_id, bdfn) \ | 18 | #define PCI_SLOT_ID(phb_id, bdfn) \ |
18 | (PCI_SLOT_ID_PREFIX | ((uint64_t)(bdfn) << 16) | (phb_id)) | 19 | (PCI_SLOT_ID_PREFIX | ((uint64_t)(bdfn) << 16) | (phb_id)) |
19 | 20 | ||
20 | extern int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id); | 21 | extern int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id); |
22 | extern int pnv_pci_get_device_tree(uint32_t phandle, void *buf, uint64_t len); | ||
23 | extern int pnv_pci_get_presence_state(uint64_t id, uint8_t *state); | ||
24 | extern int pnv_pci_get_power_state(uint64_t id, uint8_t *state); | ||
25 | extern int pnv_pci_set_power_state(uint64_t id, uint8_t state, | ||
26 | struct opal_msg *msg); | ||
21 | 27 | ||
22 | int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode); | 28 | int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode); |
23 | int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, | 29 | int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, |
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index e45b88a5d7e0..3ea1a8559035 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S | |||
@@ -302,3 +302,7 @@ OPAL_CALL(opal_prd_msg, OPAL_PRD_MSG); | |||
302 | OPAL_CALL(opal_leds_get_ind, OPAL_LEDS_GET_INDICATOR); | 302 | OPAL_CALL(opal_leds_get_ind, OPAL_LEDS_GET_INDICATOR); |
303 | OPAL_CALL(opal_leds_set_ind, OPAL_LEDS_SET_INDICATOR); | 303 | OPAL_CALL(opal_leds_set_ind, OPAL_LEDS_SET_INDICATOR); |
304 | OPAL_CALL(opal_console_flush, OPAL_CONSOLE_FLUSH); | 304 | OPAL_CALL(opal_console_flush, OPAL_CONSOLE_FLUSH); |
305 | OPAL_CALL(opal_get_device_tree, OPAL_GET_DEVICE_TREE); | ||
306 | OPAL_CALL(opal_pci_get_presence_state, OPAL_PCI_GET_PRESENCE_STATE); | ||
307 | OPAL_CALL(opal_pci_get_power_state, OPAL_PCI_GET_POWER_STATE); | ||
308 | OPAL_CALL(opal_pci_set_power_state, OPAL_PCI_SET_POWER_STATE); | ||
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 2607d2923b80..62c7637d4831 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c | |||
@@ -74,6 +74,88 @@ int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id) | |||
74 | } | 74 | } |
75 | EXPORT_SYMBOL_GPL(pnv_pci_get_slot_id); | 75 | EXPORT_SYMBOL_GPL(pnv_pci_get_slot_id); |
76 | 76 | ||
77 | int pnv_pci_get_device_tree(uint32_t phandle, void *buf, uint64_t len) | ||
78 | { | ||
79 | int64_t rc; | ||
80 | |||
81 | if (!opal_check_token(OPAL_GET_DEVICE_TREE)) | ||
82 | return -ENXIO; | ||
83 | |||
84 | rc = opal_get_device_tree(phandle, (uint64_t)buf, len); | ||
85 | if (rc < OPAL_SUCCESS) | ||
86 | return -EIO; | ||
87 | |||
88 | return rc; | ||
89 | } | ||
90 | EXPORT_SYMBOL_GPL(pnv_pci_get_device_tree); | ||
91 | |||
92 | int pnv_pci_get_presence_state(uint64_t id, uint8_t *state) | ||
93 | { | ||
94 | int64_t rc; | ||
95 | |||
96 | if (!opal_check_token(OPAL_PCI_GET_PRESENCE_STATE)) | ||
97 | return -ENXIO; | ||
98 | |||
99 | rc = opal_pci_get_presence_state(id, (uint64_t)state); | ||
100 | if (rc != OPAL_SUCCESS) | ||
101 | return -EIO; | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | EXPORT_SYMBOL_GPL(pnv_pci_get_presence_state); | ||
106 | |||
107 | int pnv_pci_get_power_state(uint64_t id, uint8_t *state) | ||
108 | { | ||
109 | int64_t rc; | ||
110 | |||
111 | if (!opal_check_token(OPAL_PCI_GET_POWER_STATE)) | ||
112 | return -ENXIO; | ||
113 | |||
114 | rc = opal_pci_get_power_state(id, (uint64_t)state); | ||
115 | if (rc != OPAL_SUCCESS) | ||
116 | return -EIO; | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | EXPORT_SYMBOL_GPL(pnv_pci_get_power_state); | ||
121 | |||
122 | int pnv_pci_set_power_state(uint64_t id, uint8_t state, struct opal_msg *msg) | ||
123 | { | ||
124 | struct opal_msg m; | ||
125 | int token, ret; | ||
126 | int64_t rc; | ||
127 | |||
128 | if (!opal_check_token(OPAL_PCI_SET_POWER_STATE)) | ||
129 | return -ENXIO; | ||
130 | |||
131 | token = opal_async_get_token_interruptible(); | ||
132 | if (unlikely(token < 0)) | ||
133 | return token; | ||
134 | |||
135 | rc = opal_pci_set_power_state(token, id, (uint64_t)&state); | ||
136 | if (rc == OPAL_SUCCESS) { | ||
137 | ret = 0; | ||
138 | goto exit; | ||
139 | } else if (rc != OPAL_ASYNC_COMPLETION) { | ||
140 | ret = -EIO; | ||
141 | goto exit; | ||
142 | } | ||
143 | |||
144 | ret = opal_async_wait_response(token, &m); | ||
145 | if (ret < 0) | ||
146 | goto exit; | ||
147 | |||
148 | if (msg) { | ||
149 | ret = 1; | ||
150 | memcpy(msg, &m, sizeof(m)); | ||
151 | } | ||
152 | |||
153 | exit: | ||
154 | opal_async_release_token(token); | ||
155 | return ret; | ||
156 | } | ||
157 | EXPORT_SYMBOL_GPL(pnv_pci_set_power_state); | ||
158 | |||
77 | #ifdef CONFIG_PCI_MSI | 159 | #ifdef CONFIG_PCI_MSI |
78 | int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | 160 | int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) |
79 | { | 161 | { |