1 // SPDX-License-Identifier: GPL-2.0+
3 * PCI Express Hot Plug Controller Driver
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
10 * All rights reserved.
12 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/types.h>
19 #include <linux/slab.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/pci.h>
25 /* The following routines constitute the bulk of the
26 hotplug controller logic
29 static void set_slot_off(struct controller
*ctrl
, struct slot
*pslot
)
31 /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
32 if (POWER_CTRL(ctrl
)) {
33 pciehp_power_off_slot(pslot
);
36 * After turning power off, we must wait for at least 1 second
37 * before taking any action that relies on power having been
38 * removed from the slot/adapter.
43 pciehp_green_led_off(pslot
);
44 pciehp_set_attention_status(pslot
, 1);
48 * board_added - Called after a board has been added to the system.
49 * @p_slot: &slot where board is added
51 * Turns power on for the board.
54 static int board_added(struct slot
*p_slot
)
57 struct controller
*ctrl
= p_slot
->ctrl
;
58 struct pci_bus
*parent
= ctrl
->pcie
->port
->subordinate
;
60 if (POWER_CTRL(ctrl
)) {
62 retval
= pciehp_power_on_slot(p_slot
);
67 pciehp_green_led_blink(p_slot
);
69 /* Check link training status */
70 retval
= pciehp_check_link_status(ctrl
);
72 ctrl_err(ctrl
, "Failed to check link status\n");
76 /* Check for a power fault */
77 if (ctrl
->power_fault_detected
|| pciehp_query_power_fault(p_slot
)) {
78 ctrl_err(ctrl
, "Slot(%s): Power fault\n", slot_name(p_slot
));
83 retval
= pciehp_configure_device(p_slot
);
85 if (retval
!= -EEXIST
) {
86 ctrl_err(ctrl
, "Cannot add device at %04x:%02x:00\n",
87 pci_domain_nr(parent
), parent
->number
);
92 pciehp_green_led_on(p_slot
);
93 pciehp_set_attention_status(p_slot
, 0);
97 set_slot_off(ctrl
, p_slot
);
102 * remove_board - Turns off slot and LEDs
103 * @p_slot: slot where board is being removed
105 static void remove_board(struct slot
*p_slot
)
107 struct controller
*ctrl
= p_slot
->ctrl
;
109 pciehp_unconfigure_device(p_slot
);
111 if (POWER_CTRL(ctrl
)) {
112 pciehp_power_off_slot(p_slot
);
115 * After turning power off, we must wait for at least 1 second
116 * before taking any action that relies on power having been
117 * removed from the slot/adapter.
122 /* turn off Green LED */
123 pciehp_green_led_off(p_slot
);
126 static int pciehp_enable_slot(struct slot
*slot
);
127 static int pciehp_disable_slot(struct slot
*slot
);
129 void pciehp_request(struct controller
*ctrl
, int action
)
131 atomic_or(action
, &ctrl
->pending_events
);
132 if (!pciehp_poll_mode
)
133 irq_wake_thread(ctrl
->pcie
->irq
, ctrl
);
136 void pciehp_queue_pushbutton_work(struct work_struct
*work
)
138 struct slot
*p_slot
= container_of(work
, struct slot
, work
.work
);
139 struct controller
*ctrl
= p_slot
->ctrl
;
141 mutex_lock(&p_slot
->lock
);
142 switch (p_slot
->state
) {
143 case BLINKINGOFF_STATE
:
144 pciehp_request(ctrl
, DISABLE_SLOT
);
146 case BLINKINGON_STATE
:
147 pciehp_request(ctrl
, PCI_EXP_SLTSTA_PDC
);
152 mutex_unlock(&p_slot
->lock
);
155 void pciehp_handle_button_press(struct slot
*p_slot
)
157 struct controller
*ctrl
= p_slot
->ctrl
;
159 mutex_lock(&p_slot
->lock
);
160 switch (p_slot
->state
) {
163 if (p_slot
->state
== ON_STATE
) {
164 p_slot
->state
= BLINKINGOFF_STATE
;
165 ctrl_info(ctrl
, "Slot(%s): Powering off due to button press\n",
168 p_slot
->state
= BLINKINGON_STATE
;
169 ctrl_info(ctrl
, "Slot(%s) Powering on due to button press\n",
172 /* blink green LED and turn off amber */
173 pciehp_green_led_blink(p_slot
);
174 pciehp_set_attention_status(p_slot
, 0);
175 schedule_delayed_work(&p_slot
->work
, 5 * HZ
);
177 case BLINKINGOFF_STATE
:
178 case BLINKINGON_STATE
:
180 * Cancel if we are still blinking; this means that we
181 * press the attention again before the 5 sec. limit
182 * expires to cancel hot-add or hot-remove
184 ctrl_info(ctrl
, "Slot(%s): Button cancel\n", slot_name(p_slot
));
185 cancel_delayed_work(&p_slot
->work
);
186 if (p_slot
->state
== BLINKINGOFF_STATE
) {
187 p_slot
->state
= ON_STATE
;
188 pciehp_green_led_on(p_slot
);
190 p_slot
->state
= OFF_STATE
;
191 pciehp_green_led_off(p_slot
);
193 pciehp_set_attention_status(p_slot
, 0);
194 ctrl_info(ctrl
, "Slot(%s): Action canceled due to button press\n",
198 ctrl_err(ctrl
, "Slot(%s): Ignoring invalid state %#x\n",
199 slot_name(p_slot
), p_slot
->state
);
202 mutex_unlock(&p_slot
->lock
);
205 void pciehp_handle_disable_request(struct slot
*slot
)
207 struct controller
*ctrl
= slot
->ctrl
;
209 mutex_lock(&slot
->lock
);
210 switch (slot
->state
) {
211 case BLINKINGON_STATE
:
212 case BLINKINGOFF_STATE
:
213 cancel_delayed_work(&slot
->work
);
216 slot
->state
= POWEROFF_STATE
;
217 mutex_unlock(&slot
->lock
);
219 ctrl
->request_result
= pciehp_disable_slot(slot
);
222 void pciehp_handle_presence_or_link_change(struct slot
*slot
, u32 events
)
224 struct controller
*ctrl
= slot
->ctrl
;
229 * If the slot is on and presence or link has changed, turn it off.
230 * Even if it's occupied again, we cannot assume the card is the same.
232 mutex_lock(&slot
->lock
);
233 switch (slot
->state
) {
234 case BLINKINGOFF_STATE
:
235 cancel_delayed_work(&slot
->work
);
238 slot
->state
= POWEROFF_STATE
;
239 mutex_unlock(&slot
->lock
);
240 if (events
& PCI_EXP_SLTSTA_DLLSC
)
241 ctrl_info(ctrl
, "Slot(%s): Link Down\n",
243 if (events
& PCI_EXP_SLTSTA_PDC
)
244 ctrl_info(ctrl
, "Slot(%s): Card not present\n",
246 pciehp_disable_slot(slot
);
249 mutex_unlock(&slot
->lock
);
253 /* Turn the slot on if it's occupied or link is up */
254 mutex_lock(&slot
->lock
);
255 pciehp_get_adapter_status(slot
, &present
);
256 link_active
= pciehp_check_link_active(ctrl
);
257 if (!present
&& !link_active
) {
258 mutex_unlock(&slot
->lock
);
262 switch (slot
->state
) {
263 case BLINKINGON_STATE
:
264 cancel_delayed_work(&slot
->work
);
267 slot
->state
= POWERON_STATE
;
268 mutex_unlock(&slot
->lock
);
270 ctrl_info(ctrl
, "Slot(%s): Card present\n",
273 ctrl_info(ctrl
, "Slot(%s): Link Up\n",
275 ctrl
->request_result
= pciehp_enable_slot(slot
);
278 mutex_unlock(&slot
->lock
);
283 static int __pciehp_enable_slot(struct slot
*p_slot
)
286 struct controller
*ctrl
= p_slot
->ctrl
;
288 pciehp_get_adapter_status(p_slot
, &getstatus
);
290 ctrl_info(ctrl
, "Slot(%s): No adapter\n", slot_name(p_slot
));
293 if (MRL_SENS(p_slot
->ctrl
)) {
294 pciehp_get_latch_status(p_slot
, &getstatus
);
296 ctrl_info(ctrl
, "Slot(%s): Latch open\n",
302 if (POWER_CTRL(p_slot
->ctrl
)) {
303 pciehp_get_power_status(p_slot
, &getstatus
);
305 ctrl_info(ctrl
, "Slot(%s): Already enabled\n",
311 return board_added(p_slot
);
314 static int pciehp_enable_slot(struct slot
*slot
)
316 struct controller
*ctrl
= slot
->ctrl
;
319 pm_runtime_get_sync(&ctrl
->pcie
->port
->dev
);
320 ret
= __pciehp_enable_slot(slot
);
321 if (ret
&& ATTN_BUTTN(ctrl
))
322 pciehp_green_led_off(slot
); /* may be blinking */
323 pm_runtime_put(&ctrl
->pcie
->port
->dev
);
325 mutex_lock(&slot
->lock
);
326 slot
->state
= ret
? OFF_STATE
: ON_STATE
;
327 mutex_unlock(&slot
->lock
);
332 static int __pciehp_disable_slot(struct slot
*p_slot
)
335 struct controller
*ctrl
= p_slot
->ctrl
;
337 if (POWER_CTRL(p_slot
->ctrl
)) {
338 pciehp_get_power_status(p_slot
, &getstatus
);
340 ctrl_info(ctrl
, "Slot(%s): Already disabled\n",
346 remove_board(p_slot
);
350 static int pciehp_disable_slot(struct slot
*slot
)
352 struct controller
*ctrl
= slot
->ctrl
;
355 pm_runtime_get_sync(&ctrl
->pcie
->port
->dev
);
356 ret
= __pciehp_disable_slot(slot
);
357 pm_runtime_put(&ctrl
->pcie
->port
->dev
);
359 mutex_lock(&slot
->lock
);
360 slot
->state
= OFF_STATE
;
361 mutex_unlock(&slot
->lock
);
366 int pciehp_sysfs_enable_slot(struct slot
*p_slot
)
368 struct controller
*ctrl
= p_slot
->ctrl
;
370 mutex_lock(&p_slot
->lock
);
371 switch (p_slot
->state
) {
372 case BLINKINGON_STATE
:
374 mutex_unlock(&p_slot
->lock
);
376 * The IRQ thread becomes a no-op if the user pulls out the
377 * card before the thread wakes up, so initialize to -ENODEV.
379 ctrl
->request_result
= -ENODEV
;
380 pciehp_request(ctrl
, PCI_EXP_SLTSTA_PDC
);
381 wait_event(ctrl
->requester
,
382 !atomic_read(&ctrl
->pending_events
));
383 return ctrl
->request_result
;
385 ctrl_info(ctrl
, "Slot(%s): Already in powering on state\n",
388 case BLINKINGOFF_STATE
:
391 ctrl_info(ctrl
, "Slot(%s): Already enabled\n",
395 ctrl_err(ctrl
, "Slot(%s): Invalid state %#x\n",
396 slot_name(p_slot
), p_slot
->state
);
399 mutex_unlock(&p_slot
->lock
);
404 int pciehp_sysfs_disable_slot(struct slot
*p_slot
)
406 struct controller
*ctrl
= p_slot
->ctrl
;
408 mutex_lock(&p_slot
->lock
);
409 switch (p_slot
->state
) {
410 case BLINKINGOFF_STATE
:
412 mutex_unlock(&p_slot
->lock
);
413 pciehp_request(ctrl
, DISABLE_SLOT
);
414 wait_event(ctrl
->requester
,
415 !atomic_read(&ctrl
->pending_events
));
416 return ctrl
->request_result
;
418 ctrl_info(ctrl
, "Slot(%s): Already in powering off state\n",
421 case BLINKINGON_STATE
:
424 ctrl_info(ctrl
, "Slot(%s): Already disabled\n",
428 ctrl_err(ctrl
, "Slot(%s): Invalid state %#x\n",
429 slot_name(p_slot
), p_slot
->state
);
432 mutex_unlock(&p_slot
->lock
);