Commit | Line | Data |
---|---|---|
736759ef | 1 | // SPDX-License-Identifier: GPL-2.0+ |
1da177e4 LT |
2 | /* |
3 | * PCI Express PCI Hot Plug Driver | |
4 | * | |
5 | * Copyright (C) 1995,2001 Compaq Computer Corporation | |
6 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) | |
7 | * Copyright (C) 2001 IBM Corp. | |
8 | * Copyright (C) 2003-2004 Intel Corporation | |
9 | * | |
10 | * All rights reserved. | |
11 | * | |
8cf4c195 | 12 | * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com> |
1da177e4 LT |
13 | */ |
14 | ||
94dbc956 FL |
15 | #define dev_fmt(fmt) "pciehp: " fmt |
16 | ||
abaaac48 | 17 | #include <linux/bitfield.h> |
0b382546 | 18 | #include <linux/dmi.h> |
1da177e4 | 19 | #include <linux/kernel.h> |
1da177e4 | 20 | #include <linux/types.h> |
de25968c | 21 | #include <linux/jiffies.h> |
ec07a447 | 22 | #include <linux/kthread.h> |
1da177e4 | 23 | #include <linux/pci.h> |
6b08c385 | 24 | #include <linux/pm_runtime.h> |
5d1b8c9e | 25 | #include <linux/interrupt.h> |
5a0e3ad6 | 26 | #include <linux/slab.h> |
5d1b8c9e | 27 | |
1da177e4 LT |
28 | #include "../pci.h" |
29 | #include "pciehp.h" | |
1da177e4 | 30 | |
0b382546 SH |
31 | static const struct dmi_system_id inband_presence_disabled_dmi_table[] = { |
32 | /* | |
33 | * Match all Dell systems, as some Dell systems have inband | |
34 | * presence disabled on NVMe slots (but don't support the bit to | |
35 | * report it). Setting inband presence disabled should have no | |
36 | * negative effect, except on broken hotplug slots that never | |
37 | * assert presence detect--and those will still work, they will | |
38 | * just have a bit of extra delay before being probed. | |
39 | */ | |
40 | { | |
41 | .ident = "Dell System", | |
42 | .matches = { | |
43 | DMI_MATCH(DMI_OEM_STRING, "Dell System"), | |
44 | }, | |
45 | }, | |
46 | {} | |
47 | }; | |
48 | ||
cd84d340 | 49 | static inline struct pci_dev *ctrl_dev(struct controller *ctrl) |
a0f018da | 50 | { |
cd84d340 | 51 | return ctrl->pcie->port; |
a0f018da | 52 | } |
1da177e4 | 53 | |
7b4ce26b LW |
54 | static irqreturn_t pciehp_isr(int irq, void *dev_id); |
55 | static irqreturn_t pciehp_ist(int irq, void *dev_id); | |
ec07a447 | 56 | static int pciehp_poll(void *data); |
1da177e4 | 57 | |
2aeeef11 KK |
58 | static inline int pciehp_request_irq(struct controller *ctrl) |
59 | { | |
f7a10e32 | 60 | int retval, irq = ctrl->pcie->irq; |
2aeeef11 | 61 | |
2aeeef11 | 62 | if (pciehp_poll_mode) { |
ec07a447 LW |
63 | ctrl->poll_thread = kthread_run(&pciehp_poll, ctrl, |
64 | "pciehp_poll-%s", | |
5790a9c7 | 65 | slot_name(ctrl)); |
ec07a447 | 66 | return PTR_ERR_OR_ZERO(ctrl->poll_thread); |
2aeeef11 KK |
67 | } |
68 | ||
69 | /* Installs the interrupt handler */ | |
7b4ce26b | 70 | retval = request_threaded_irq(irq, pciehp_isr, pciehp_ist, |
e07ca82a | 71 | IRQF_SHARED, "pciehp", ctrl); |
2aeeef11 | 72 | if (retval) |
7f2feec1 TI |
73 | ctrl_err(ctrl, "Cannot get irq %d for the hotplug controller\n", |
74 | irq); | |
2aeeef11 KK |
75 | return retval; |
76 | } | |
77 | ||
78 | static inline void pciehp_free_irq(struct controller *ctrl) | |
79 | { | |
80 | if (pciehp_poll_mode) | |
ec07a447 | 81 | kthread_stop(ctrl->poll_thread); |
2aeeef11 | 82 | else |
f7a10e32 | 83 | free_irq(ctrl->pcie->irq, ctrl); |
2aeeef11 KK |
84 | } |
85 | ||
40b96083 | 86 | static int pcie_poll_cmd(struct controller *ctrl, int timeout) |
6592e02a | 87 | { |
cd84d340 | 88 | struct pci_dev *pdev = ctrl_dev(ctrl); |
6592e02a | 89 | u16 slot_status; |
6592e02a | 90 | |
b94ec12d | 91 | do { |
1a84b99c | 92 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
a3b0f10d | 93 | if (PCI_POSSIBLE_ERROR(slot_status)) { |
1469d17d JW |
94 | ctrl_info(ctrl, "%s: no response from device\n", |
95 | __func__); | |
96 | return 0; | |
97 | } | |
98 | ||
1a84b99c | 99 | if (slot_status & PCI_EXP_SLTSTA_CC) { |
cd84d340 BH |
100 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, |
101 | PCI_EXP_SLTSTA_CC); | |
92912b17 LZ |
102 | ctrl->cmd_busy = 0; |
103 | smp_mb(); | |
322162a7 | 104 | return 1; |
820943b6 | 105 | } |
ac10836b YW |
106 | msleep(10); |
107 | timeout -= 10; | |
b94ec12d | 108 | } while (timeout >= 0); |
6592e02a | 109 | return 0; /* timeout */ |
6592e02a KK |
110 | } |
111 | ||
4283c70e | 112 | static void pcie_wait_cmd(struct controller *ctrl) |
44ef4cef | 113 | { |
262303fe | 114 | unsigned int msecs = pciehp_poll_mode ? 2500 : 1000; |
40b96083 BH |
115 | unsigned long duration = msecs_to_jiffies(msecs); |
116 | unsigned long cmd_timeout = ctrl->cmd_started + duration; | |
117 | unsigned long now, timeout; | |
262303fe KK |
118 | int rc; |
119 | ||
4283c70e BH |
120 | /* |
121 | * If the controller does not generate notifications for command | |
122 | * completions, we never need to wait between writes. | |
123 | */ | |
6c1a32e0 | 124 | if (NO_CMD_CMPL(ctrl)) |
4283c70e BH |
125 | return; |
126 | ||
127 | if (!ctrl->cmd_busy) | |
128 | return; | |
129 | ||
40b96083 BH |
130 | /* |
131 | * Even if the command has already timed out, we want to call | |
132 | * pcie_poll_cmd() so it can clear PCI_EXP_SLTSTA_CC. | |
133 | */ | |
134 | now = jiffies; | |
135 | if (time_before_eq(cmd_timeout, now)) | |
136 | timeout = 1; | |
137 | else | |
138 | timeout = cmd_timeout - now; | |
139 | ||
4283c70e BH |
140 | if (ctrl->slot_ctrl & PCI_EXP_SLTCTL_HPIE && |
141 | ctrl->slot_ctrl & PCI_EXP_SLTCTL_CCIE) | |
d737bdc1 | 142 | rc = wait_event_timeout(ctrl->queue, !ctrl->cmd_busy, timeout); |
4283c70e | 143 | else |
7cbeb9f9 | 144 | rc = pcie_poll_cmd(ctrl, jiffies_to_msecs(timeout)); |
40b96083 | 145 | |
262303fe | 146 | if (!rc) |
d537a3ab | 147 | ctrl_info(ctrl, "Timeout on hotplug command %#06x (issued %u msec ago)\n", |
40b96083 | 148 | ctrl->slot_ctrl, |
d433889c | 149 | jiffies_to_msecs(jiffies - ctrl->cmd_started)); |
44ef4cef KK |
150 | } |
151 | ||
d22b3621 BH |
152 | #define CC_ERRATUM_MASK (PCI_EXP_SLTCTL_PCC | \ |
153 | PCI_EXP_SLTCTL_PIC | \ | |
154 | PCI_EXP_SLTCTL_AIC | \ | |
155 | PCI_EXP_SLTCTL_EIC) | |
156 | ||
a5dd4b4b AW |
157 | static void pcie_do_write_cmd(struct controller *ctrl, u16 cmd, |
158 | u16 mask, bool wait) | |
1da177e4 | 159 | { |
cd84d340 | 160 | struct pci_dev *pdev = ctrl_dev(ctrl); |
d22b3621 | 161 | u16 slot_ctrl_orig, slot_ctrl; |
1da177e4 | 162 | |
44ef4cef KK |
163 | mutex_lock(&ctrl->ctrl_lock); |
164 | ||
a5dd4b4b AW |
165 | /* |
166 | * Always wait for any previous command that might still be in progress | |
167 | */ | |
3461a068 BH |
168 | pcie_wait_cmd(ctrl); |
169 | ||
1a84b99c | 170 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); |
a3b0f10d | 171 | if (PCI_POSSIBLE_ERROR(slot_ctrl)) { |
1469d17d JW |
172 | ctrl_info(ctrl, "%s: no response from device\n", __func__); |
173 | goto out; | |
174 | } | |
175 | ||
d22b3621 | 176 | slot_ctrl_orig = slot_ctrl; |
f4778364 | 177 | slot_ctrl &= ~mask; |
b7aa1f16 | 178 | slot_ctrl |= (cmd & mask); |
f4778364 | 179 | ctrl->cmd_busy = 1; |
2d32a9ae | 180 | smp_mb(); |
25bd879e | 181 | ctrl->slot_ctrl = slot_ctrl; |
1a84b99c | 182 | pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl); |
40b96083 | 183 | ctrl->cmd_started = jiffies; |
f4778364 | 184 | |
d22b3621 BH |
185 | /* |
186 | * Controllers with the Intel CF118 and similar errata advertise | |
187 | * Command Completed support, but they only set Command Completed | |
188 | * if we change the "Control" bits for power, power indicator, | |
189 | * attention indicator, or interlock. If we only change the | |
190 | * "Enable" bits, they never set the Command Completed bit. | |
191 | */ | |
192 | if (pdev->broken_cmd_compl && | |
193 | (slot_ctrl_orig & CC_ERRATUM_MASK) == (slot_ctrl & CC_ERRATUM_MASK)) | |
194 | ctrl->cmd_busy = 0; | |
195 | ||
a5dd4b4b AW |
196 | /* |
197 | * Optionally wait for the hardware to be ready for a new command, | |
198 | * indicating completion of the above issued command. | |
199 | */ | |
200 | if (wait) | |
201 | pcie_wait_cmd(ctrl); | |
202 | ||
1469d17d | 203 | out: |
44ef4cef | 204 | mutex_unlock(&ctrl->ctrl_lock); |
1da177e4 LT |
205 | } |
206 | ||
a5dd4b4b AW |
207 | /** |
208 | * pcie_write_cmd - Issue controller command | |
209 | * @ctrl: controller to which the command is issued | |
210 | * @cmd: command value written to slot control register | |
211 | * @mask: bitmask of slot control register to be modified | |
212 | */ | |
213 | static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | |
214 | { | |
215 | pcie_do_write_cmd(ctrl, cmd, mask, true); | |
216 | } | |
217 | ||
218 | /* Same as above without waiting for the hardware to latch */ | |
219 | static void pcie_write_cmd_nowait(struct controller *ctrl, u16 cmd, u16 mask) | |
220 | { | |
221 | pcie_do_write_cmd(ctrl, cmd, mask, false); | |
222 | } | |
223 | ||
87d0f2a5 MW |
224 | /** |
225 | * pciehp_check_link_active() - Is the link active | |
226 | * @ctrl: PCIe hotplug controller | |
227 | * | |
228 | * Check whether the downstream link is currently active. Note it is | |
229 | * possible that the card is removed immediately after this so the | |
230 | * caller may need to take it into account. | |
231 | * | |
232 | * If the hotplug controller itself is not available anymore returns | |
233 | * %-ENODEV. | |
234 | */ | |
235 | int pciehp_check_link_active(struct controller *ctrl) | |
f18e9625 | 236 | { |
cd84d340 | 237 | struct pci_dev *pdev = ctrl_dev(ctrl); |
4e2ce405 | 238 | u16 lnk_status; |
87d0f2a5 | 239 | int ret; |
f18e9625 | 240 | |
87d0f2a5 | 241 | ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); |
a3b0f10d | 242 | if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status)) |
87d0f2a5 | 243 | return -ENODEV; |
4e2ce405 | 244 | |
87d0f2a5 MW |
245 | ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); |
246 | ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); | |
4e2ce405 YL |
247 | |
248 | return ret; | |
f18e9625 KK |
249 | } |
250 | ||
2f5d8e4f YL |
251 | static bool pci_bus_check_dev(struct pci_bus *bus, int devfn) |
252 | { | |
253 | u32 l; | |
254 | int count = 0; | |
255 | int delay = 1000, step = 20; | |
256 | bool found = false; | |
257 | ||
258 | do { | |
259 | found = pci_bus_read_dev_vendor_id(bus, devfn, &l, 0); | |
260 | count++; | |
261 | ||
262 | if (found) | |
263 | break; | |
264 | ||
265 | msleep(step); | |
266 | delay -= step; | |
267 | } while (delay > 0); | |
268 | ||
7e696b8a | 269 | if (count > 1) |
742ee16b | 270 | pr_debug("pci %04x:%02x:%02x.%d id reading try %d times with interval %d ms to get %08x\n", |
2f5d8e4f YL |
271 | pci_domain_nr(bus), bus->number, PCI_SLOT(devfn), |
272 | PCI_FUNC(devfn), count, step, l); | |
273 | ||
274 | return found; | |
275 | } | |
276 | ||
f496648b AG |
277 | static void pcie_wait_for_presence(struct pci_dev *pdev) |
278 | { | |
279 | int timeout = 1250; | |
280 | u16 slot_status; | |
281 | ||
282 | do { | |
283 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); | |
284 | if (slot_status & PCI_EXP_SLTSTA_PDS) | |
285 | return; | |
286 | msleep(10); | |
287 | timeout -= 10; | |
288 | } while (timeout > 0); | |
f496648b AG |
289 | } |
290 | ||
82a9e79e | 291 | int pciehp_check_link_status(struct controller *ctrl) |
1da177e4 | 292 | { |
cd84d340 | 293 | struct pci_dev *pdev = ctrl_dev(ctrl); |
1a84b99c | 294 | bool found; |
79c731e2 | 295 | u16 lnk_status, linksta2; |
1da177e4 | 296 | |
8a614499 LW |
297 | if (!pcie_wait_for_link(pdev, true)) { |
298 | ctrl_info(ctrl, "Slot(%s): No link\n", slot_name(ctrl)); | |
f0157160 | 299 | return -1; |
8a614499 | 300 | } |
f18e9625 | 301 | |
f496648b AG |
302 | if (ctrl->inband_presence_disabled) |
303 | pcie_wait_for_presence(pdev); | |
304 | ||
2f5d8e4f YL |
305 | found = pci_bus_check_dev(ctrl->pcie->port->subordinate, |
306 | PCI_DEVFN(0, 0)); | |
0027cb3e | 307 | |
6c35a1ac LW |
308 | /* ignore link or presence changes up to this point */ |
309 | if (found) | |
310 | atomic_and(~(PCI_EXP_SLTSTA_DLLSC | PCI_EXP_SLTSTA_PDC), | |
311 | &ctrl->pending_events); | |
312 | ||
1a84b99c | 313 | pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); |
7f2feec1 | 314 | ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); |
322162a7 KK |
315 | if ((lnk_status & PCI_EXP_LNKSTA_LT) || |
316 | !(lnk_status & PCI_EXP_LNKSTA_NLW)) { | |
8a614499 LW |
317 | ctrl_info(ctrl, "Slot(%s): Cannot train link: status %#06x\n", |
318 | slot_name(ctrl), lnk_status); | |
1a84b99c | 319 | return -1; |
1da177e4 LT |
320 | } |
321 | ||
79c731e2 IJ |
322 | pcie_capability_read_word(pdev, PCI_EXP_LNKSTA2, &linksta2); |
323 | __pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status, linksta2); | |
fdbd3ce9 | 324 | |
8a614499 LW |
325 | if (!found) { |
326 | ctrl_info(ctrl, "Slot(%s): No device found\n", | |
327 | slot_name(ctrl)); | |
1a84b99c | 328 | return -1; |
8a614499 | 329 | } |
2f5d8e4f | 330 | |
1a84b99c | 331 | return 0; |
1da177e4 LT |
332 | } |
333 | ||
7f822999 YL |
334 | static int __pciehp_link_set(struct controller *ctrl, bool enable) |
335 | { | |
cd84d340 | 336 | struct pci_dev *pdev = ctrl_dev(ctrl); |
7f822999 | 337 | |
5f75f96c IJ |
338 | pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, |
339 | PCI_EXP_LNKCTL_LD, | |
340 | enable ? 0 : PCI_EXP_LNKCTL_LD); | |
7f822999 | 341 | |
1a84b99c | 342 | return 0; |
7f822999 YL |
343 | } |
344 | ||
345 | static int pciehp_link_enable(struct controller *ctrl) | |
346 | { | |
347 | return __pciehp_link_set(ctrl, true); | |
348 | } | |
349 | ||
576243b3 KB |
350 | int pciehp_get_raw_indicator_status(struct hotplug_slot *hotplug_slot, |
351 | u8 *status) | |
352 | { | |
125450f8 | 353 | struct controller *ctrl = to_ctrl(hotplug_slot); |
5790a9c7 | 354 | struct pci_dev *pdev = ctrl_dev(ctrl); |
576243b3 KB |
355 | u16 slot_ctrl; |
356 | ||
4417aa45 | 357 | pci_config_pm_runtime_get(pdev); |
576243b3 | 358 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); |
4417aa45 | 359 | pci_config_pm_runtime_put(pdev); |
576243b3 KB |
360 | *status = (slot_ctrl & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6; |
361 | return 0; | |
362 | } | |
363 | ||
eee6e273 | 364 | int pciehp_get_attention_status(struct hotplug_slot *hotplug_slot, u8 *status) |
1da177e4 | 365 | { |
125450f8 | 366 | struct controller *ctrl = to_ctrl(hotplug_slot); |
cd84d340 | 367 | struct pci_dev *pdev = ctrl_dev(ctrl); |
1da177e4 | 368 | u16 slot_ctrl; |
1da177e4 | 369 | |
4417aa45 | 370 | pci_config_pm_runtime_get(pdev); |
1a84b99c | 371 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); |
4417aa45 | 372 | pci_config_pm_runtime_put(pdev); |
1518c17a KK |
373 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__, |
374 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); | |
1da177e4 | 375 | |
e7b4f0d7 BH |
376 | switch (slot_ctrl & PCI_EXP_SLTCTL_AIC) { |
377 | case PCI_EXP_SLTCTL_ATTN_IND_ON: | |
1da177e4 LT |
378 | *status = 1; /* On */ |
379 | break; | |
e7b4f0d7 | 380 | case PCI_EXP_SLTCTL_ATTN_IND_BLINK: |
1da177e4 LT |
381 | *status = 2; /* Blink */ |
382 | break; | |
e7b4f0d7 | 383 | case PCI_EXP_SLTCTL_ATTN_IND_OFF: |
1da177e4 LT |
384 | *status = 0; /* Off */ |
385 | break; | |
386 | default: | |
387 | *status = 0xFF; | |
388 | break; | |
389 | } | |
eee6e273 LW |
390 | |
391 | return 0; | |
1da177e4 LT |
392 | } |
393 | ||
5790a9c7 | 394 | void pciehp_get_power_status(struct controller *ctrl, u8 *status) |
1da177e4 | 395 | { |
cd84d340 | 396 | struct pci_dev *pdev = ctrl_dev(ctrl); |
1da177e4 | 397 | u16 slot_ctrl; |
1da177e4 | 398 | |
1a84b99c | 399 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); |
1518c17a KK |
400 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__, |
401 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); | |
1da177e4 | 402 | |
e7b4f0d7 BH |
403 | switch (slot_ctrl & PCI_EXP_SLTCTL_PCC) { |
404 | case PCI_EXP_SLTCTL_PWR_ON: | |
405 | *status = 1; /* On */ | |
1da177e4 | 406 | break; |
e7b4f0d7 BH |
407 | case PCI_EXP_SLTCTL_PWR_OFF: |
408 | *status = 0; /* Off */ | |
1da177e4 LT |
409 | break; |
410 | default: | |
411 | *status = 0xFF; | |
412 | break; | |
413 | } | |
1da177e4 LT |
414 | } |
415 | ||
5790a9c7 | 416 | void pciehp_get_latch_status(struct controller *ctrl, u8 *status) |
1da177e4 | 417 | { |
5790a9c7 | 418 | struct pci_dev *pdev = ctrl_dev(ctrl); |
1da177e4 | 419 | u16 slot_status; |
1da177e4 | 420 | |
1a84b99c | 421 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
322162a7 | 422 | *status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS); |
1da177e4 LT |
423 | } |
424 | ||
87d0f2a5 MW |
425 | /** |
426 | * pciehp_card_present() - Is the card present | |
427 | * @ctrl: PCIe hotplug controller | |
428 | * | |
429 | * Function checks whether the card is currently present in the slot and | |
430 | * in that case returns true. Note it is possible that the card is | |
431 | * removed immediately after the check so the caller may need to take | |
432 | * this into account. | |
433 | * | |
f4e026f4 | 434 | * If the hotplug controller itself is not available anymore returns |
87d0f2a5 MW |
435 | * %-ENODEV. |
436 | */ | |
437 | int pciehp_card_present(struct controller *ctrl) | |
1da177e4 | 438 | { |
80696f99 | 439 | struct pci_dev *pdev = ctrl_dev(ctrl); |
1da177e4 | 440 | u16 slot_status; |
87d0f2a5 | 441 | int ret; |
1da177e4 | 442 | |
87d0f2a5 | 443 | ret = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
a3b0f10d | 444 | if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(slot_status)) |
87d0f2a5 MW |
445 | return -ENODEV; |
446 | ||
447 | return !!(slot_status & PCI_EXP_SLTSTA_PDS); | |
80696f99 LW |
448 | } |
449 | ||
450 | /** | |
451 | * pciehp_card_present_or_link_active() - whether given slot is occupied | |
452 | * @ctrl: PCIe hotplug controller | |
453 | * | |
454 | * Unlike pciehp_card_present(), which determines presence solely from the | |
455 | * Presence Detect State bit, this helper also returns true if the Link Active | |
456 | * bit is set. This is a concession to broken hotplug ports which hardwire | |
457 | * Presence Detect State to zero, such as Wilocity's [1ae9:0200]. | |
87d0f2a5 MW |
458 | * |
459 | * Returns: %1 if the slot is occupied and %0 if it is not. If the hotplug | |
460 | * port is not present anymore returns %-ENODEV. | |
80696f99 | 461 | */ |
87d0f2a5 | 462 | int pciehp_card_present_or_link_active(struct controller *ctrl) |
80696f99 | 463 | { |
87d0f2a5 MW |
464 | int ret; |
465 | ||
466 | ret = pciehp_card_present(ctrl); | |
467 | if (ret) | |
468 | return ret; | |
469 | ||
470 | return pciehp_check_link_active(ctrl); | |
1da177e4 LT |
471 | } |
472 | ||
5790a9c7 | 473 | int pciehp_query_power_fault(struct controller *ctrl) |
1da177e4 | 474 | { |
5790a9c7 | 475 | struct pci_dev *pdev = ctrl_dev(ctrl); |
1da177e4 | 476 | u16 slot_status; |
1da177e4 | 477 | |
1a84b99c | 478 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
322162a7 | 479 | return !!(slot_status & PCI_EXP_SLTSTA_PFD); |
1da177e4 LT |
480 | } |
481 | ||
576243b3 KB |
482 | int pciehp_set_raw_indicator_status(struct hotplug_slot *hotplug_slot, |
483 | u8 status) | |
484 | { | |
125450f8 | 485 | struct controller *ctrl = to_ctrl(hotplug_slot); |
4417aa45 | 486 | struct pci_dev *pdev = ctrl_dev(ctrl); |
576243b3 | 487 | |
4417aa45 | 488 | pci_config_pm_runtime_get(pdev); |
5560a612 BK |
489 | |
490 | /* Attention and Power Indicator Control bits are supported */ | |
491 | pcie_write_cmd_nowait(ctrl, FIELD_PREP(PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC, status), | |
576243b3 | 492 | PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC); |
4417aa45 | 493 | pci_config_pm_runtime_put(pdev); |
576243b3 KB |
494 | return 0; |
495 | } | |
496 | ||
688033f5 DE |
497 | /** |
498 | * pciehp_set_indicators() - set attention indicator, power indicator, or both | |
499 | * @ctrl: PCIe hotplug controller | |
500 | * @pwr: one of: | |
501 | * PCI_EXP_SLTCTL_PWR_IND_ON | |
502 | * PCI_EXP_SLTCTL_PWR_IND_BLINK | |
503 | * PCI_EXP_SLTCTL_PWR_IND_OFF | |
504 | * @attn: one of: | |
505 | * PCI_EXP_SLTCTL_ATTN_IND_ON | |
506 | * PCI_EXP_SLTCTL_ATTN_IND_BLINK | |
507 | * PCI_EXP_SLTCTL_ATTN_IND_OFF | |
508 | * | |
509 | * Either @pwr or @attn can also be INDICATOR_NOOP to leave that indicator | |
510 | * unchanged. | |
511 | */ | |
512 | void pciehp_set_indicators(struct controller *ctrl, int pwr, int attn) | |
513 | { | |
514 | u16 cmd = 0, mask = 0; | |
515 | ||
516 | if (PWR_LED(ctrl) && pwr != INDICATOR_NOOP) { | |
517 | cmd |= (pwr & PCI_EXP_SLTCTL_PIC); | |
518 | mask |= PCI_EXP_SLTCTL_PIC; | |
519 | } | |
520 | ||
521 | if (ATTN_LED(ctrl) && attn != INDICATOR_NOOP) { | |
522 | cmd |= (attn & PCI_EXP_SLTCTL_AIC); | |
523 | mask |= PCI_EXP_SLTCTL_AIC; | |
524 | } | |
525 | ||
526 | if (cmd) { | |
527 | pcie_write_cmd_nowait(ctrl, cmd, mask); | |
528 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, | |
529 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, cmd); | |
530 | } | |
531 | } | |
532 | ||
5790a9c7 | 533 | int pciehp_power_on_slot(struct controller *ctrl) |
1da177e4 | 534 | { |
cd84d340 | 535 | struct pci_dev *pdev = ctrl_dev(ctrl); |
f4778364 | 536 | u16 slot_status; |
1a84b99c | 537 | int retval; |
1da177e4 | 538 | |
34fb6bf9 | 539 | /* Clear power-fault bit from previous power failures */ |
1a84b99c | 540 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
2f2ed41c BH |
541 | if (slot_status & PCI_EXP_SLTSTA_PFD) |
542 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, | |
543 | PCI_EXP_SLTSTA_PFD); | |
5651c48c | 544 | ctrl->power_fault_detected = 0; |
1da177e4 | 545 | |
e7b4f0d7 | 546 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_ON, PCI_EXP_SLTCTL_PCC); |
1518c17a | 547 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
e7b4f0d7 BH |
548 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, |
549 | PCI_EXP_SLTCTL_PWR_ON); | |
1da177e4 | 550 | |
2debd928 YL |
551 | retval = pciehp_link_enable(ctrl); |
552 | if (retval) | |
553 | ctrl_err(ctrl, "%s: Can not enable the link!\n", __func__); | |
554 | ||
1da177e4 LT |
555 | return retval; |
556 | } | |
557 | ||
5790a9c7 | 558 | void pciehp_power_off_slot(struct controller *ctrl) |
1da177e4 | 559 | { |
e7b4f0d7 | 560 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC); |
1518c17a | 561 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
e7b4f0d7 BH |
562 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, |
563 | PCI_EXP_SLTCTL_PWR_OFF); | |
1da177e4 LT |
564 | } |
565 | ||
c3be50f7 LW |
566 | bool pciehp_device_replaced(struct controller *ctrl) |
567 | { | |
568 | struct pci_dev *pdev __free(pci_dev_put) = NULL; | |
569 | u32 reg; | |
570 | ||
571 | if (pci_dev_is_disconnected(ctrl->pcie->port)) | |
572 | return false; | |
573 | ||
574 | pdev = pci_get_slot(ctrl->pcie->port->subordinate, PCI_DEVFN(0, 0)); | |
575 | if (!pdev) | |
576 | return true; | |
577 | ||
578 | if (pci_read_config_dword(pdev, PCI_VENDOR_ID, ®) || | |
579 | reg != (pdev->vendor | (pdev->device << 16)) || | |
580 | pci_read_config_dword(pdev, PCI_CLASS_REVISION, ®) || | |
581 | reg != (pdev->revision | (pdev->class << 8))) | |
582 | return true; | |
583 | ||
584 | if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL && | |
585 | (pci_read_config_dword(pdev, PCI_SUBSYSTEM_VENDOR_ID, ®) || | |
586 | reg != (pdev->subsystem_vendor | (pdev->subsystem_device << 16)))) | |
587 | return true; | |
588 | ||
589 | if (pci_get_dsn(pdev) != ctrl->dsn) | |
590 | return true; | |
591 | ||
592 | return false; | |
593 | } | |
594 | ||
2af781a9 LW |
595 | static void pciehp_ignore_link_change(struct controller *ctrl, |
596 | struct pci_dev *pdev, int irq, | |
597 | u16 ignored_events) | |
a97396c6 LW |
598 | { |
599 | /* | |
600 | * Ignore link changes which occurred while waiting for DPC recovery. | |
601 | * Could be several if DPC triggered multiple times consecutively. | |
2af781a9 | 602 | * Also ignore link changes caused by Secondary Bus Reset, etc. |
a97396c6 LW |
603 | */ |
604 | synchronize_hardirq(irq); | |
c3be50f7 | 605 | atomic_and(~ignored_events, &ctrl->pending_events); |
a97396c6 LW |
606 | if (pciehp_poll_mode) |
607 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, | |
c3be50f7 | 608 | ignored_events); |
2af781a9 | 609 | ctrl_info(ctrl, "Slot(%s): Link Down/Up ignored\n", slot_name(ctrl)); |
a97396c6 LW |
610 | |
611 | /* | |
612 | * If the link is unexpectedly down after successful recovery, | |
613 | * the corresponding link change may have been ignored above. | |
614 | * Synthesize it to ensure that it is acted on. | |
615 | */ | |
085a9f43 | 616 | down_read_nested(&ctrl->reset_lock, ctrl->depth); |
c3be50f7 LW |
617 | if (!pciehp_check_link_active(ctrl) || pciehp_device_replaced(ctrl)) |
618 | pciehp_request(ctrl, ignored_events); | |
a97396c6 LW |
619 | up_read(&ctrl->reset_lock); |
620 | } | |
621 | ||
fad214b0 | 622 | static irqreturn_t pciehp_isr(int irq, void *dev_id) |
1da177e4 | 623 | { |
48fe3915 | 624 | struct controller *ctrl = (struct controller *)dev_id; |
cd84d340 | 625 | struct pci_dev *pdev = ctrl_dev(ctrl); |
6b08c385 | 626 | struct device *parent = pdev->dev.parent; |
8edf5332 | 627 | u16 status, events = 0; |
1da177e4 | 628 | |
7b4ce26b | 629 | /* |
720d6a67 MW |
630 | * Interrupts only occur in D3hot or shallower and only if enabled |
631 | * in the Slot Control register (PCIe r4.0, sec 6.7.3.4). | |
7b4ce26b | 632 | */ |
720d6a67 MW |
633 | if (pdev->current_state == PCI_D3cold || |
634 | (!(ctrl->slot_ctrl & PCI_EXP_SLTCTL_HPIE) && !pciehp_poll_mode)) | |
ed91de7e LW |
635 | return IRQ_NONE; |
636 | ||
6b08c385 LW |
637 | /* |
638 | * Keep the port accessible by holding a runtime PM ref on its parent. | |
639 | * Defer resume of the parent to the IRQ thread if it's suspended. | |
640 | * Mask the interrupt until then. | |
641 | */ | |
642 | if (parent) { | |
643 | pm_runtime_get_noresume(parent); | |
644 | if (!pm_runtime_active(parent)) { | |
645 | pm_runtime_put(parent); | |
646 | disable_irq_nosync(irq); | |
647 | atomic_or(RERUN_ISR, &ctrl->pending_events); | |
648 | return IRQ_WAKE_THREAD; | |
649 | } | |
650 | } | |
651 | ||
8edf5332 | 652 | read_status: |
fad214b0 | 653 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &status); |
a3b0f10d | 654 | if (PCI_POSSIBLE_ERROR(status)) { |
fad214b0 | 655 | ctrl_info(ctrl, "%s: no response from device\n", __func__); |
6b08c385 LW |
656 | if (parent) |
657 | pm_runtime_put(parent); | |
fad214b0 MP |
658 | return IRQ_NONE; |
659 | } | |
660 | ||
c6b069e9 | 661 | /* |
fad214b0 MP |
662 | * Slot Status contains plain status bits as well as event |
663 | * notification bits; right now we only want the event bits. | |
c6b069e9 | 664 | */ |
8edf5332 SH |
665 | status &= PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | |
666 | PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_CC | | |
667 | PCI_EXP_SLTSTA_DLLSC; | |
7612b3b2 KB |
668 | |
669 | /* | |
670 | * If we've already reported a power fault, don't report it again | |
671 | * until we've done something to handle it. | |
672 | */ | |
673 | if (ctrl->power_fault_detected) | |
8edf5332 | 674 | status &= ~PCI_EXP_SLTSTA_PFD; |
23584c1e LW |
675 | else if (status & PCI_EXP_SLTSTA_PFD) |
676 | ctrl->power_fault_detected = true; | |
7612b3b2 | 677 | |
8edf5332 | 678 | events |= status; |
6b08c385 LW |
679 | if (!events) { |
680 | if (parent) | |
681 | pm_runtime_put(parent); | |
fad214b0 | 682 | return IRQ_NONE; |
6b08c385 | 683 | } |
71ad556d | 684 | |
8edf5332 | 685 | if (status) { |
23584c1e | 686 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, status); |
8edf5332 SH |
687 | |
688 | /* | |
689 | * In MSI mode, all event bits must be zero before the port | |
690 | * will send a new interrupt (PCIe Base Spec r5.0 sec 6.7.3.4). | |
691 | * So re-read the Slot Status register in case a bit was set | |
692 | * between read and write. | |
693 | */ | |
694 | if (pci_dev_msi_enabled(pdev) && !pciehp_poll_mode) | |
695 | goto read_status; | |
696 | } | |
697 | ||
a8499f20 | 698 | ctrl_dbg(ctrl, "pending interrupts %#06x from Slot Status\n", events); |
6b08c385 LW |
699 | if (parent) |
700 | pm_runtime_put(parent); | |
71ad556d | 701 | |
7b4ce26b LW |
702 | /* |
703 | * Command Completed notifications are not deferred to the | |
704 | * IRQ thread because it may be waiting for their arrival. | |
705 | */ | |
a8499f20 | 706 | if (events & PCI_EXP_SLTSTA_CC) { |
262303fe | 707 | ctrl->cmd_busy = 0; |
2d32a9ae | 708 | smp_mb(); |
d737bdc1 | 709 | wake_up(&ctrl->queue); |
7b4ce26b LW |
710 | |
711 | if (events == PCI_EXP_SLTSTA_CC) | |
712 | return IRQ_HANDLED; | |
713 | ||
714 | events &= ~PCI_EXP_SLTSTA_CC; | |
1da177e4 LT |
715 | } |
716 | ||
1204e35b LW |
717 | if (pdev->ignore_hotplug) { |
718 | ctrl_dbg(ctrl, "ignoring hotplug event %#06x\n", events); | |
719 | return IRQ_HANDLED; | |
b440bde7 BH |
720 | } |
721 | ||
7b4ce26b LW |
722 | /* Save pending events for consumption by IRQ thread. */ |
723 | atomic_or(events, &ctrl->pending_events); | |
724 | return IRQ_WAKE_THREAD; | |
725 | } | |
726 | ||
727 | static irqreturn_t pciehp_ist(int irq, void *dev_id) | |
728 | { | |
729 | struct controller *ctrl = (struct controller *)dev_id; | |
6b08c385 | 730 | struct pci_dev *pdev = ctrl_dev(ctrl); |
6b08c385 | 731 | irqreturn_t ret; |
7b4ce26b | 732 | u32 events; |
7b4ce26b | 733 | |
157c1062 | 734 | ctrl->ist_running = true; |
6b08c385 LW |
735 | pci_config_pm_runtime_get(pdev); |
736 | ||
737 | /* rerun pciehp_isr() if the port was inaccessible on interrupt */ | |
738 | if (atomic_fetch_and(~RERUN_ISR, &ctrl->pending_events) & RERUN_ISR) { | |
739 | ret = pciehp_isr(irq, dev_id); | |
740 | enable_irq(irq); | |
3e487d2e LW |
741 | if (ret != IRQ_WAKE_THREAD) |
742 | goto out; | |
6b08c385 LW |
743 | } |
744 | ||
7b4ce26b LW |
745 | synchronize_hardirq(irq); |
746 | events = atomic_xchg(&ctrl->pending_events, 0); | |
6b08c385 | 747 | if (!events) { |
3e487d2e LW |
748 | ret = IRQ_NONE; |
749 | goto out; | |
6b08c385 | 750 | } |
7b4ce26b | 751 | |
c6b069e9 | 752 | /* Check Attention Button Pressed */ |
5054133a | 753 | if (events & PCI_EXP_SLTSTA_ABP) |
5790a9c7 | 754 | pciehp_handle_button_press(ctrl); |
48fe3915 | 755 | |
34fb6bf9 | 756 | /* Check Power Fault Detected */ |
23584c1e | 757 | if (events & PCI_EXP_SLTSTA_PFD) { |
5790a9c7 | 758 | ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl)); |
94719ba0 DE |
759 | pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, |
760 | PCI_EXP_SLTCTL_ATTN_IND_ON); | |
34fb6bf9 KB |
761 | } |
762 | ||
a97396c6 LW |
763 | /* |
764 | * Ignore Link Down/Up events caused by Downstream Port Containment | |
2af781a9 LW |
765 | * if recovery succeeded, or caused by Secondary Bus Reset, |
766 | * suspend to D3cold, firmware update, FPGA reconfiguration, etc. | |
a97396c6 | 767 | */ |
2af781a9 LW |
768 | if ((events & (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC)) && |
769 | (pci_dpc_recovered(pdev) || pci_hp_spurious_link_change(pdev)) && | |
a97396c6 | 770 | ctrl->state == ON_STATE) { |
c3be50f7 LW |
771 | u16 ignored_events = PCI_EXP_SLTSTA_DLLSC; |
772 | ||
773 | if (!ctrl->inband_presence_disabled) | |
bbf10cd6 | 774 | ignored_events |= PCI_EXP_SLTSTA_PDC; |
c3be50f7 LW |
775 | |
776 | events &= ~ignored_events; | |
2af781a9 | 777 | pciehp_ignore_link_change(ctrl, pdev, irq, ignored_events); |
a97396c6 LW |
778 | } |
779 | ||
385895fe | 780 | /* |
32a8cef2 LW |
781 | * Disable requests have higher priority than Presence Detect Changed |
782 | * or Data Link Layer State Changed events. | |
385895fe | 783 | */ |
085a9f43 | 784 | down_read_nested(&ctrl->reset_lock, ctrl->depth); |
32a8cef2 | 785 | if (events & DISABLE_SLOT) |
5790a9c7 | 786 | pciehp_handle_disable_request(ctrl); |
d331710e | 787 | else if (events & (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC)) |
5790a9c7 | 788 | pciehp_handle_presence_or_link_change(ctrl, events); |
5b3f7b7d | 789 | up_read(&ctrl->reset_lock); |
48fe3915 | 790 | |
3e487d2e LW |
791 | ret = IRQ_HANDLED; |
792 | out: | |
6b08c385 | 793 | pci_config_pm_runtime_put(pdev); |
157c1062 | 794 | ctrl->ist_running = false; |
32a8cef2 | 795 | wake_up(&ctrl->requester); |
3e487d2e | 796 | return ret; |
1da177e4 LT |
797 | } |
798 | ||
ec07a447 LW |
799 | static int pciehp_poll(void *data) |
800 | { | |
801 | struct controller *ctrl = data; | |
802 | ||
803 | schedule_timeout_idle(10 * HZ); /* start with 10 sec delay */ | |
804 | ||
805 | while (!kthread_should_stop()) { | |
32a8cef2 LW |
806 | /* poll for interrupt events or user requests */ |
807 | while (pciehp_isr(IRQ_NOTCONNECTED, ctrl) == IRQ_WAKE_THREAD || | |
808 | atomic_read(&ctrl->pending_events)) | |
ec07a447 LW |
809 | pciehp_ist(IRQ_NOTCONNECTED, ctrl); |
810 | ||
811 | if (pciehp_poll_time <= 0 || pciehp_poll_time > 60) | |
812 | pciehp_poll_time = 2; /* clamp to sane value */ | |
813 | ||
814 | schedule_timeout_idle(pciehp_poll_time * HZ); | |
815 | } | |
816 | ||
817 | return 0; | |
818 | } | |
819 | ||
13c65840 | 820 | static void pcie_enable_notification(struct controller *ctrl) |
ecdde939 | 821 | { |
c27fb883 | 822 | u16 cmd, mask; |
1da177e4 | 823 | |
5651c48c KK |
824 | /* |
825 | * TBD: Power fault detected software notification support. | |
826 | * | |
827 | * Power fault detected software notification is not enabled | |
828 | * now, because it caused power fault detected interrupt storm | |
829 | * on some machines. On those machines, power fault detected | |
830 | * bit in the slot status register was set again immediately | |
831 | * when it is cleared in the interrupt service routine, and | |
832 | * next power fault detected interrupt was notified again. | |
833 | */ | |
4f854f2a RJ |
834 | |
835 | /* | |
836 | * Always enable link events: thus link-up and link-down shall | |
837 | * always be treated as hotplug and unplug respectively. Enable | |
838 | * presence detect only if Attention Button is not present. | |
839 | */ | |
840 | cmd = PCI_EXP_SLTCTL_DLLSCE; | |
ae416e6b | 841 | if (ATTN_BUTTN(ctrl)) |
322162a7 | 842 | cmd |= PCI_EXP_SLTCTL_ABPE; |
4f854f2a RJ |
843 | else |
844 | cmd |= PCI_EXP_SLTCTL_PDCE; | |
c27fb883 | 845 | if (!pciehp_poll_mode) |
6d4671b5 PR |
846 | cmd |= PCI_EXP_SLTCTL_HPIE; |
847 | if (!pciehp_poll_mode && !NO_CMD_CMPL(ctrl)) | |
848 | cmd |= PCI_EXP_SLTCTL_CCIE; | |
c27fb883 | 849 | |
322162a7 | 850 | mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | |
2db0f71f | 851 | PCI_EXP_SLTCTL_PFDE | |
4f854f2a RJ |
852 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | |
853 | PCI_EXP_SLTCTL_DLLSCE); | |
c27fb883 | 854 | |
a5dd4b4b | 855 | pcie_write_cmd_nowait(ctrl, cmd, mask); |
cf8d7b58 YL |
856 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
857 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, cmd); | |
c4635eb0 KK |
858 | } |
859 | ||
860 | static void pcie_disable_notification(struct controller *ctrl) | |
861 | { | |
862 | u16 mask; | |
6dae6202 | 863 | |
322162a7 KK |
864 | mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | |
865 | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | | |
f22daf1f KK |
866 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | |
867 | PCI_EXP_SLTCTL_DLLSCE); | |
6dae6202 | 868 | pcie_write_cmd(ctrl, 0, mask); |
cf8d7b58 YL |
869 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
870 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, 0); | |
c4635eb0 KK |
871 | } |
872 | ||
79037824 LW |
873 | void pcie_clear_hotplug_events(struct controller *ctrl) |
874 | { | |
875 | pcie_capability_write_word(ctrl_dev(ctrl), PCI_EXP_SLTSTA, | |
876 | PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC); | |
877 | } | |
878 | ||
eb34da60 MW |
879 | void pcie_enable_interrupt(struct controller *ctrl) |
880 | { | |
bbe54ea5 MW |
881 | u16 mask; |
882 | ||
527664f7 IJ |
883 | mask = PCI_EXP_SLTCTL_DLLSCE; |
884 | if (!pciehp_poll_mode) | |
885 | mask |= PCI_EXP_SLTCTL_HPIE; | |
bbe54ea5 | 886 | pcie_write_cmd(ctrl, mask, mask); |
eb34da60 MW |
887 | } |
888 | ||
889 | void pcie_disable_interrupt(struct controller *ctrl) | |
890 | { | |
bbe54ea5 MW |
891 | u16 mask; |
892 | ||
893 | /* | |
894 | * Mask hot-plug interrupt to prevent it triggering immediately | |
895 | * when the link goes inactive (we still get PME when any of the | |
896 | * enabled events is detected). Same goes with Link Layer State | |
897 | * changed event which generates PME immediately when the link goes | |
898 | * inactive so mask it as well. | |
899 | */ | |
900 | mask = PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_DLLSCE; | |
901 | pcie_write_cmd(ctrl, 0, mask); | |
eb34da60 MW |
902 | } |
903 | ||
ea401499 LW |
904 | /** |
905 | * pciehp_slot_reset() - ignore link event caused by error-induced hot reset | |
906 | * @dev: PCI Express port service device | |
907 | * | |
908 | * Called from pcie_portdrv_slot_reset() after AER or DPC initiated a reset | |
909 | * further up in the hierarchy to recover from an error. The reset was | |
910 | * propagated down to this hotplug port. Ignore the resulting link flap. | |
911 | * If the link failed to retrain successfully, synthesize the ignored event. | |
912 | * Surprise removal during reset is detected through Presence Detect Changed. | |
913 | */ | |
914 | int pciehp_slot_reset(struct pcie_device *dev) | |
915 | { | |
916 | struct controller *ctrl = get_service_data(dev); | |
917 | ||
918 | if (ctrl->state != ON_STATE) | |
919 | return 0; | |
920 | ||
921 | pcie_capability_write_word(dev->port, PCI_EXP_SLTSTA, | |
922 | PCI_EXP_SLTSTA_DLLSC); | |
923 | ||
924 | if (!pciehp_check_link_active(ctrl)) | |
925 | pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC); | |
926 | ||
927 | return 0; | |
928 | } | |
929 | ||
2e35afae AW |
930 | /* |
931 | * pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary | |
2b3940b6 RJ |
932 | * bus reset of the bridge, but at the same time we want to ensure that it is |
933 | * not seen as a hot-unplug, followed by the hot-plug of the device. Thus, | |
934 | * disable link state notification and presence detection change notification | |
935 | * momentarily, if we see that they could interfere. Also, clear any spurious | |
2e35afae AW |
936 | * events after. |
937 | */ | |
9bdc81ce | 938 | int pciehp_reset_slot(struct hotplug_slot *hotplug_slot, bool probe) |
2e35afae | 939 | { |
125450f8 | 940 | struct controller *ctrl = to_ctrl(hotplug_slot); |
cd84d340 | 941 | struct pci_dev *pdev = ctrl_dev(ctrl); |
18426238 | 942 | int rc; |
2e35afae AW |
943 | |
944 | if (probe) | |
945 | return 0; | |
946 | ||
085a9f43 | 947 | down_write_nested(&ctrl->reset_lock, ctrl->depth); |
5b3f7b7d | 948 | |
2af781a9 | 949 | pci_hp_ignore_link_change(pdev); |
2e35afae | 950 | |
381634ca | 951 | rc = pci_bridge_secondary_bus_reset(ctrl->pcie->port); |
2e35afae | 952 | |
2af781a9 | 953 | pci_hp_unignore_link_change(pdev); |
5b3f7b7d LW |
954 | |
955 | up_write(&ctrl->reset_lock); | |
18426238 | 956 | return rc; |
2e35afae AW |
957 | } |
958 | ||
dbc7e1e5 | 959 | int pcie_init_notification(struct controller *ctrl) |
c4635eb0 KK |
960 | { |
961 | if (pciehp_request_irq(ctrl)) | |
962 | return -1; | |
6dae6202 | 963 | pcie_enable_notification(ctrl); |
dbc7e1e5 | 964 | ctrl->notification_enabled = 1; |
c4635eb0 KK |
965 | return 0; |
966 | } | |
967 | ||
281e878e | 968 | void pcie_shutdown_notification(struct controller *ctrl) |
c4635eb0 | 969 | { |
dbc7e1e5 EB |
970 | if (ctrl->notification_enabled) { |
971 | pcie_disable_notification(ctrl); | |
972 | pciehp_free_irq(ctrl); | |
973 | ctrl->notification_enabled = 0; | |
974 | } | |
c4635eb0 KK |
975 | } |
976 | ||
2aeeef11 | 977 | static inline void dbg_ctrl(struct controller *ctrl) |
08e7a7d2 | 978 | { |
385e2491 | 979 | struct pci_dev *pdev = ctrl->pcie->port; |
3784e0c6 | 980 | u16 reg16; |
08e7a7d2 | 981 | |
7e696b8a | 982 | ctrl_dbg(ctrl, "Slot Capabilities : 0x%08x\n", ctrl->slot_cap); |
cd84d340 | 983 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, ®16); |
7e696b8a | 984 | ctrl_dbg(ctrl, "Slot Status : 0x%04x\n", reg16); |
cd84d340 | 985 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, ®16); |
7e696b8a | 986 | ctrl_dbg(ctrl, "Slot Control : 0x%04x\n", reg16); |
2aeeef11 | 987 | } |
08e7a7d2 | 988 | |
3c78bc61 | 989 | #define FLAG(x, y) (((x) & (y)) ? '+' : '-') |
afe2478f | 990 | |
085a9f43 HG |
991 | static inline int pcie_hotplug_depth(struct pci_dev *dev) |
992 | { | |
993 | struct pci_bus *bus = dev->bus; | |
994 | int depth = 0; | |
995 | ||
996 | while (bus->parent) { | |
997 | bus = bus->parent; | |
998 | if (bus->self && bus->self->is_hotplug_bridge) | |
999 | depth++; | |
1000 | } | |
1001 | ||
1002 | return depth; | |
1003 | } | |
1004 | ||
c4635eb0 | 1005 | struct controller *pcie_init(struct pcie_device *dev) |
2aeeef11 | 1006 | { |
c4635eb0 | 1007 | struct controller *ctrl; |
1f087398 | 1008 | u32 slot_cap, slot_cap2; |
80696f99 | 1009 | u8 poweron; |
2aeeef11 | 1010 | struct pci_dev *pdev = dev->port; |
5790a9c7 | 1011 | struct pci_bus *subordinate = pdev->subordinate; |
08e7a7d2 | 1012 | |
c4635eb0 | 1013 | ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); |
c7abb235 | 1014 | if (!ctrl) |
5790a9c7 | 1015 | return NULL; |
c7abb235 | 1016 | |
f7a10e32 | 1017 | ctrl->pcie = dev; |
085a9f43 | 1018 | ctrl->depth = pcie_hotplug_depth(dev->port); |
1a84b99c | 1019 | pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); |
576243b3 KB |
1020 | |
1021 | if (pdev->hotplug_user_indicators) | |
1022 | slot_cap &= ~(PCI_EXP_SLTCAP_AIP | PCI_EXP_SLTCAP_PIP); | |
1023 | ||
493fb50e LW |
1024 | /* |
1025 | * We assume no Thunderbolt controllers support Command Complete events, | |
1026 | * but some controllers falsely claim they do. | |
1027 | */ | |
1028 | if (pdev->is_thunderbolt) | |
1029 | slot_cap |= PCI_EXP_SLTCAP_NCCS; | |
1030 | ||
2aeeef11 | 1031 | ctrl->slot_cap = slot_cap; |
08e7a7d2 | 1032 | mutex_init(&ctrl->ctrl_lock); |
4ff3126e | 1033 | mutex_init(&ctrl->state_lock); |
5b3f7b7d | 1034 | init_rwsem(&ctrl->reset_lock); |
32a8cef2 | 1035 | init_waitqueue_head(&ctrl->requester); |
08e7a7d2 | 1036 | init_waitqueue_head(&ctrl->queue); |
4ff3126e | 1037 | INIT_DELAYED_WORK(&ctrl->button_work, pciehp_queue_pushbutton_work); |
2aeeef11 | 1038 | dbg_ctrl(ctrl); |
2cc56f30 | 1039 | |
5790a9c7 LW |
1040 | down_read(&pci_bus_sem); |
1041 | ctrl->state = list_empty(&subordinate->devices) ? OFF_STATE : ON_STATE; | |
1042 | up_read(&pci_bus_sem); | |
1043 | ||
20285359 AG |
1044 | pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP2, &slot_cap2); |
1045 | if (slot_cap2 & PCI_EXP_SLTCAP2_IBPD) { | |
1046 | pcie_write_cmd_nowait(ctrl, PCI_EXP_SLTCTL_IBPD_DISABLE, | |
1047 | PCI_EXP_SLTCTL_IBPD_DISABLE); | |
1048 | ctrl->inband_presence_disabled = 1; | |
1049 | } | |
1050 | ||
0b382546 SH |
1051 | if (dmi_first_match(inband_presence_disabled_dmi_table)) |
1052 | ctrl->inband_presence_disabled = 1; | |
1053 | ||
cdf6b736 | 1054 | /* Clear all remaining event bits in Slot Status register. */ |
df72648c BH |
1055 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, |
1056 | PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | | |
db63d400 | 1057 | PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_CC | |
cdf6b736 | 1058 | PCI_EXP_SLTSTA_DLLSC | PCI_EXP_SLTSTA_PDC); |
08e7a7d2 | 1059 | |
20285359 | 1060 | ctrl_info(ctrl, "Slot #%d AttnBtn%c PwrCtrl%c MRL%c AttnInd%c PwrInd%c HotPlug%c Surprise%c Interlock%c NoCompl%c IbPresDis%c LLActRep%c%s\n", |
abaaac48 | 1061 | FIELD_GET(PCI_EXP_SLTCAP_PSN, slot_cap), |
afe2478f | 1062 | FLAG(slot_cap, PCI_EXP_SLTCAP_ABP), |
afe2478f BH |
1063 | FLAG(slot_cap, PCI_EXP_SLTCAP_PCP), |
1064 | FLAG(slot_cap, PCI_EXP_SLTCAP_MRLSP), | |
3784e0c6 BH |
1065 | FLAG(slot_cap, PCI_EXP_SLTCAP_AIP), |
1066 | FLAG(slot_cap, PCI_EXP_SLTCAP_PIP), | |
1067 | FLAG(slot_cap, PCI_EXP_SLTCAP_HPC), | |
1068 | FLAG(slot_cap, PCI_EXP_SLTCAP_HPS), | |
afe2478f BH |
1069 | FLAG(slot_cap, PCI_EXP_SLTCAP_EIP), |
1070 | FLAG(slot_cap, PCI_EXP_SLTCAP_NCCS), | |
20285359 | 1071 | FLAG(slot_cap2, PCI_EXP_SLTCAP2_IBPD), |
1f087398 | 1072 | FLAG(pdev->link_active_reporting, true), |
d22b3621 | 1073 | pdev->broken_cmd_compl ? " (with Cmd Compl erratum)" : ""); |
c4635eb0 | 1074 | |
4e6a1335 LW |
1075 | /* |
1076 | * If empty slot's power status is on, turn power off. The IRQ isn't | |
1077 | * requested yet, so avoid triggering a notification with this command. | |
1078 | */ | |
1079 | if (POWER_CTRL(ctrl)) { | |
5790a9c7 | 1080 | pciehp_get_power_status(ctrl, &poweron); |
80696f99 | 1081 | if (!pciehp_card_present_or_link_active(ctrl) && poweron) { |
4e6a1335 | 1082 | pcie_disable_notification(ctrl); |
5790a9c7 | 1083 | pciehp_power_off_slot(ctrl); |
4e6a1335 LW |
1084 | } |
1085 | } | |
1086 | ||
9d573d19 LW |
1087 | pdev = pci_get_slot(subordinate, PCI_DEVFN(0, 0)); |
1088 | if (pdev) | |
1089 | ctrl->dsn = pci_get_dsn(pdev); | |
1090 | pci_dev_put(pdev); | |
1091 | ||
c4635eb0 | 1092 | return ctrl; |
c4635eb0 KK |
1093 | } |
1094 | ||
82a9e79e | 1095 | void pciehp_release_ctrl(struct controller *ctrl) |
c4635eb0 | 1096 | { |
4ff3126e | 1097 | cancel_delayed_work_sync(&ctrl->button_work); |
c4635eb0 | 1098 | kfree(ctrl); |
08e7a7d2 | 1099 | } |
d22b3621 BH |
1100 | |
1101 | static void quirk_cmd_compl(struct pci_dev *pdev) | |
1102 | { | |
1103 | u32 slot_cap; | |
1104 | ||
1105 | if (pci_is_pcie(pdev)) { | |
1106 | pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); | |
1107 | if (slot_cap & PCI_EXP_SLTCAP_HPC && | |
1108 | !(slot_cap & PCI_EXP_SLTCAP_NCCS)) | |
1109 | pdev->broken_cmd_compl = 1; | |
1110 | } | |
1111 | } | |
1112 | DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, | |
1113 | PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl); | |
82b34b08 MS |
1114 | DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x010e, |
1115 | PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl); | |
9f72d475 MS |
1116 | DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0110, |
1117 | PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl); | |
d22b3621 BH |
1118 | DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0400, |
1119 | PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl); | |
1120 | DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0401, | |
1121 | PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl); | |
22e4d639 SY |
1122 | DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_HXT, 0x0401, |
1123 | PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl); |