]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/pci/hotplug/pciehp_ctrl.c
2 * PCI Express Hot Plug Controller Driver
4 * Copyright (C) 1995,2001 Compaq Computer Corporation
5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6 * Copyright (C) 2001 IBM Corp.
7 * Copyright (C) 2003-2004 Intel Corporation
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or (at
14 * your option) any later version.
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
19 * NON INFRINGEMENT. See the GNU General Public License for more
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
30 #include <linux/module.h>
31 #include <linux/kernel.h>
32 #include <linux/types.h>
33 #include <linux/slab.h>
34 #include <linux/pci.h>
38 static void interrupt_event_handler(struct work_struct
*work
);
40 static int queue_interrupt_event(struct slot
*p_slot
, u32 event_type
)
42 struct event_info
*info
;
44 info
= kmalloc(sizeof(*info
), GFP_ATOMIC
);
48 info
->event_type
= event_type
;
49 info
->p_slot
= p_slot
;
50 INIT_WORK(&info
->work
, interrupt_event_handler
);
52 queue_work(p_slot
->wq
, &info
->work
);
57 u8
pciehp_handle_attention_button(struct slot
*p_slot
)
60 struct controller
*ctrl
= p_slot
->ctrl
;
63 * Button pressed - See if need to TAKE ACTION!!!
65 ctrl_info(ctrl
, "Button pressed on Slot(%s)\n", slot_name(p_slot
));
66 event_type
= INT_BUTTON_PRESS
;
68 queue_interrupt_event(p_slot
, event_type
);
73 u8
pciehp_handle_switch_change(struct slot
*p_slot
)
77 struct controller
*ctrl
= p_slot
->ctrl
;
79 pciehp_get_latch_status(p_slot
, &getstatus
);
84 ctrl_info(ctrl
, "Latch open on Slot(%s)\n", slot_name(p_slot
));
85 event_type
= INT_SWITCH_OPEN
;
90 ctrl_info(ctrl
, "Latch close on Slot(%s)\n", slot_name(p_slot
));
91 event_type
= INT_SWITCH_CLOSE
;
94 queue_interrupt_event(p_slot
, event_type
);
99 u8
pciehp_handle_presence_change(struct slot
*p_slot
)
103 struct controller
*ctrl
= p_slot
->ctrl
;
105 /* Switch is open, assume a presence change
106 * Save the presence state
108 pciehp_get_adapter_status(p_slot
, &presence_save
);
113 ctrl_info(ctrl
, "Card present on Slot(%s)\n", slot_name(p_slot
));
114 event_type
= INT_PRESENCE_ON
;
119 ctrl_info(ctrl
, "Card not present on Slot(%s)\n",
121 event_type
= INT_PRESENCE_OFF
;
124 queue_interrupt_event(p_slot
, event_type
);
129 u8
pciehp_handle_power_fault(struct slot
*p_slot
)
132 struct controller
*ctrl
= p_slot
->ctrl
;
134 ctrl_err(ctrl
, "Power fault on slot %s\n", slot_name(p_slot
));
135 event_type
= INT_POWER_FAULT
;
136 ctrl_info(ctrl
, "Power fault bit %x set\n", 0);
137 queue_interrupt_event(p_slot
, event_type
);
142 void pciehp_handle_linkstate_change(struct slot
*p_slot
)
145 struct controller
*ctrl
= p_slot
->ctrl
;
147 if (pciehp_check_link_active(ctrl
)) {
148 ctrl_info(ctrl
, "slot(%s): Link Up event\n",
150 event_type
= INT_LINK_UP
;
152 ctrl_info(ctrl
, "slot(%s): Link Down event\n",
154 event_type
= INT_LINK_DOWN
;
157 queue_interrupt_event(p_slot
, event_type
);
160 /* The following routines constitute the bulk of the
161 hotplug controller logic
164 static void set_slot_off(struct controller
*ctrl
, struct slot
*pslot
)
166 /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
167 if (POWER_CTRL(ctrl
)) {
168 pciehp_power_off_slot(pslot
);
171 * After turning power off, we must wait for at least 1 second
172 * before taking any action that relies on power having been
173 * removed from the slot/adapter.
178 pciehp_green_led_off(pslot
);
179 pciehp_set_attention_status(pslot
, 1);
183 * board_added - Called after a board has been added to the system.
184 * @p_slot: &slot where board is added
186 * Turns power on for the board.
189 static int board_added(struct slot
*p_slot
)
192 struct controller
*ctrl
= p_slot
->ctrl
;
193 struct pci_bus
*parent
= ctrl
->pcie
->port
->subordinate
;
195 if (POWER_CTRL(ctrl
)) {
197 retval
= pciehp_power_on_slot(p_slot
);
202 pciehp_green_led_blink(p_slot
);
204 /* Check link training status */
205 retval
= pciehp_check_link_status(ctrl
);
207 ctrl_err(ctrl
, "Failed to check link status\n");
211 /* Check for a power fault */
212 if (ctrl
->power_fault_detected
|| pciehp_query_power_fault(p_slot
)) {
213 ctrl_err(ctrl
, "Power fault on slot %s\n", slot_name(p_slot
));
218 retval
= pciehp_configure_device(p_slot
);
220 ctrl_err(ctrl
, "Cannot add device at %04x:%02x:00\n",
221 pci_domain_nr(parent
), parent
->number
);
222 if (retval
!= -EEXIST
)
226 pciehp_green_led_on(p_slot
);
230 set_slot_off(ctrl
, p_slot
);
235 * remove_board - Turns off slot and LEDs
236 * @p_slot: slot where board is being removed
238 static int remove_board(struct slot
*p_slot
)
241 struct controller
*ctrl
= p_slot
->ctrl
;
243 retval
= pciehp_unconfigure_device(p_slot
);
247 if (POWER_CTRL(ctrl
)) {
248 pciehp_power_off_slot(p_slot
);
251 * After turning power off, we must wait for at least 1 second
252 * before taking any action that relies on power having been
253 * removed from the slot/adapter.
258 /* turn off Green LED */
259 pciehp_green_led_off(p_slot
);
263 struct power_work_info
{
265 struct work_struct work
;
267 #define DISABLE_REQ 0
272 * pciehp_power_thread - handle pushbutton events
273 * @work: &struct work_struct describing work to be done
275 * Scheduled procedure to handle blocking stuff for the pushbuttons.
276 * Handles all pending events and exits.
278 static void pciehp_power_thread(struct work_struct
*work
)
280 struct power_work_info
*info
=
281 container_of(work
, struct power_work_info
, work
);
282 struct slot
*p_slot
= info
->p_slot
;
287 mutex_lock(&p_slot
->hotplug_lock
);
288 pciehp_disable_slot(p_slot
);
289 mutex_unlock(&p_slot
->hotplug_lock
);
290 mutex_lock(&p_slot
->lock
);
291 p_slot
->state
= STATIC_STATE
;
292 mutex_unlock(&p_slot
->lock
);
295 mutex_lock(&p_slot
->hotplug_lock
);
296 ret
= pciehp_enable_slot(p_slot
);
297 mutex_unlock(&p_slot
->hotplug_lock
);
299 pciehp_green_led_off(p_slot
);
300 mutex_lock(&p_slot
->lock
);
301 p_slot
->state
= STATIC_STATE
;
302 mutex_unlock(&p_slot
->lock
);
311 void pciehp_queue_pushbutton_work(struct work_struct
*work
)
313 struct slot
*p_slot
= container_of(work
, struct slot
, work
.work
);
314 struct power_work_info
*info
;
316 info
= kmalloc(sizeof(*info
), GFP_KERNEL
);
318 ctrl_err(p_slot
->ctrl
, "%s: Cannot allocate memory\n",
322 info
->p_slot
= p_slot
;
323 INIT_WORK(&info
->work
, pciehp_power_thread
);
325 mutex_lock(&p_slot
->lock
);
326 switch (p_slot
->state
) {
327 case BLINKINGOFF_STATE
:
328 p_slot
->state
= POWEROFF_STATE
;
329 info
->req
= DISABLE_REQ
;
331 case BLINKINGON_STATE
:
332 p_slot
->state
= POWERON_STATE
;
333 info
->req
= ENABLE_REQ
;
339 queue_work(p_slot
->wq
, &info
->work
);
341 mutex_unlock(&p_slot
->lock
);
345 * Note: This function must be called with slot->lock held
347 static void handle_button_press_event(struct slot
*p_slot
)
349 struct controller
*ctrl
= p_slot
->ctrl
;
352 switch (p_slot
->state
) {
354 pciehp_get_power_status(p_slot
, &getstatus
);
356 p_slot
->state
= BLINKINGOFF_STATE
;
357 ctrl_info(ctrl
, "PCI slot #%s - powering off due to button press\n",
360 p_slot
->state
= BLINKINGON_STATE
;
361 ctrl_info(ctrl
, "PCI slot #%s - powering on due to button press\n",
364 /* blink green LED and turn off amber */
365 pciehp_green_led_blink(p_slot
);
366 pciehp_set_attention_status(p_slot
, 0);
367 queue_delayed_work(p_slot
->wq
, &p_slot
->work
, 5*HZ
);
369 case BLINKINGOFF_STATE
:
370 case BLINKINGON_STATE
:
372 * Cancel if we are still blinking; this means that we
373 * press the attention again before the 5 sec. limit
374 * expires to cancel hot-add or hot-remove
376 ctrl_info(ctrl
, "Button cancel on Slot(%s)\n", slot_name(p_slot
));
377 cancel_delayed_work(&p_slot
->work
);
378 if (p_slot
->state
== BLINKINGOFF_STATE
)
379 pciehp_green_led_on(p_slot
);
381 pciehp_green_led_off(p_slot
);
382 pciehp_set_attention_status(p_slot
, 0);
383 ctrl_info(ctrl
, "PCI slot #%s - action canceled due to button press\n",
385 p_slot
->state
= STATIC_STATE
;
390 * Ignore if the slot is on power-on or power-off state;
391 * this means that the previous attention button action
392 * to hot-add or hot-remove is undergoing
394 ctrl_info(ctrl
, "Button ignore on Slot(%s)\n", slot_name(p_slot
));
397 ctrl_warn(ctrl
, "ignoring invalid state %#x\n", p_slot
->state
);
403 * Note: This function must be called with slot->lock held
405 static void handle_surprise_event(struct slot
*p_slot
)
408 struct power_work_info
*info
;
410 info
= kmalloc(sizeof(*info
), GFP_KERNEL
);
412 ctrl_err(p_slot
->ctrl
, "%s: Cannot allocate memory\n",
416 info
->p_slot
= p_slot
;
417 INIT_WORK(&info
->work
, pciehp_power_thread
);
419 pciehp_get_adapter_status(p_slot
, &getstatus
);
421 p_slot
->state
= POWEROFF_STATE
;
422 info
->req
= DISABLE_REQ
;
424 p_slot
->state
= POWERON_STATE
;
425 info
->req
= ENABLE_REQ
;
428 queue_work(p_slot
->wq
, &info
->work
);
432 * Note: This function must be called with slot->lock held
434 static void handle_link_event(struct slot
*p_slot
, u32 event
)
436 struct controller
*ctrl
= p_slot
->ctrl
;
437 struct power_work_info
*info
;
439 info
= kmalloc(sizeof(*info
), GFP_KERNEL
);
441 ctrl_err(p_slot
->ctrl
, "%s: Cannot allocate memory\n",
445 info
->p_slot
= p_slot
;
446 info
->req
= event
== INT_LINK_UP
? ENABLE_REQ
: DISABLE_REQ
;
447 INIT_WORK(&info
->work
, pciehp_power_thread
);
449 switch (p_slot
->state
) {
450 case BLINKINGON_STATE
:
451 case BLINKINGOFF_STATE
:
452 cancel_delayed_work(&p_slot
->work
);
455 p_slot
->state
= event
== INT_LINK_UP
?
456 POWERON_STATE
: POWEROFF_STATE
;
457 queue_work(p_slot
->wq
, &info
->work
);
460 if (event
== INT_LINK_UP
) {
462 "Link Up event ignored on slot(%s): already powering on\n",
467 "Link Down event queued on slot(%s): currently getting powered on\n",
469 p_slot
->state
= POWEROFF_STATE
;
470 queue_work(p_slot
->wq
, &info
->work
);
474 if (event
== INT_LINK_UP
) {
476 "Link Up event queued on slot(%s): currently getting powered off\n",
478 p_slot
->state
= POWERON_STATE
;
479 queue_work(p_slot
->wq
, &info
->work
);
482 "Link Down event ignored on slot(%s): already powering off\n",
488 ctrl_err(ctrl
, "ignoring invalid state %#x on slot(%s)\n",
489 p_slot
->state
, slot_name(p_slot
));
495 static void interrupt_event_handler(struct work_struct
*work
)
497 struct event_info
*info
= container_of(work
, struct event_info
, work
);
498 struct slot
*p_slot
= info
->p_slot
;
499 struct controller
*ctrl
= p_slot
->ctrl
;
501 mutex_lock(&p_slot
->lock
);
502 switch (info
->event_type
) {
503 case INT_BUTTON_PRESS
:
504 handle_button_press_event(p_slot
);
506 case INT_POWER_FAULT
:
507 if (!POWER_CTRL(ctrl
))
509 pciehp_set_attention_status(p_slot
, 1);
510 pciehp_green_led_off(p_slot
);
512 case INT_PRESENCE_ON
:
513 handle_surprise_event(p_slot
);
515 case INT_PRESENCE_OFF
:
517 * Regardless of surprise capability, we need to
518 * definitely remove a card that has been pulled out!
520 handle_surprise_event(p_slot
);
524 handle_link_event(p_slot
, info
->event_type
);
529 mutex_unlock(&p_slot
->lock
);
535 * Note: This function must be called with slot->hotplug_lock held
537 int pciehp_enable_slot(struct slot
*p_slot
)
541 struct controller
*ctrl
= p_slot
->ctrl
;
543 pciehp_get_adapter_status(p_slot
, &getstatus
);
545 ctrl_info(ctrl
, "No adapter on slot(%s)\n", slot_name(p_slot
));
548 if (MRL_SENS(p_slot
->ctrl
)) {
549 pciehp_get_latch_status(p_slot
, &getstatus
);
551 ctrl_info(ctrl
, "Latch open on slot(%s)\n",
557 if (POWER_CTRL(p_slot
->ctrl
)) {
558 pciehp_get_power_status(p_slot
, &getstatus
);
560 ctrl_info(ctrl
, "Already enabled on slot(%s)\n",
566 pciehp_get_latch_status(p_slot
, &getstatus
);
568 rc
= board_added(p_slot
);
570 pciehp_get_latch_status(p_slot
, &getstatus
);
576 * Note: This function must be called with slot->hotplug_lock held
578 int pciehp_disable_slot(struct slot
*p_slot
)
581 struct controller
*ctrl
= p_slot
->ctrl
;
586 if (POWER_CTRL(p_slot
->ctrl
)) {
587 pciehp_get_power_status(p_slot
, &getstatus
);
589 ctrl_info(ctrl
, "Already disabled on slot(%s)\n",
595 return remove_board(p_slot
);
598 int pciehp_sysfs_enable_slot(struct slot
*p_slot
)
600 int retval
= -ENODEV
;
601 struct controller
*ctrl
= p_slot
->ctrl
;
603 mutex_lock(&p_slot
->lock
);
604 switch (p_slot
->state
) {
605 case BLINKINGON_STATE
:
606 cancel_delayed_work(&p_slot
->work
);
608 p_slot
->state
= POWERON_STATE
;
609 mutex_unlock(&p_slot
->lock
);
610 mutex_lock(&p_slot
->hotplug_lock
);
611 retval
= pciehp_enable_slot(p_slot
);
612 mutex_unlock(&p_slot
->hotplug_lock
);
613 mutex_lock(&p_slot
->lock
);
614 p_slot
->state
= STATIC_STATE
;
617 ctrl_info(ctrl
, "Slot %s is already in powering on state\n",
620 case BLINKINGOFF_STATE
:
622 ctrl_info(ctrl
, "Already enabled on slot %s\n",
626 ctrl_err(ctrl
, "invalid state %#x on slot %s\n",
627 p_slot
->state
, slot_name(p_slot
));
630 mutex_unlock(&p_slot
->lock
);
635 int pciehp_sysfs_disable_slot(struct slot
*p_slot
)
637 int retval
= -ENODEV
;
638 struct controller
*ctrl
= p_slot
->ctrl
;
640 mutex_lock(&p_slot
->lock
);
641 switch (p_slot
->state
) {
642 case BLINKINGOFF_STATE
:
643 cancel_delayed_work(&p_slot
->work
);
645 p_slot
->state
= POWEROFF_STATE
;
646 mutex_unlock(&p_slot
->lock
);
647 retval
= pciehp_disable_slot(p_slot
);
648 mutex_lock(&p_slot
->lock
);
649 p_slot
->state
= STATIC_STATE
;
652 ctrl_info(ctrl
, "Slot %s is already in powering off state\n",
655 case BLINKINGON_STATE
:
657 ctrl_info(ctrl
, "Already disabled on slot %s\n",
661 ctrl_err(ctrl
, "invalid state %#x on slot %s\n",
662 p_slot
->state
, slot_name(p_slot
));
665 mutex_unlock(&p_slot
->lock
);