xref: /linux/drivers/pci/hotplug/pciehp_ctrl.c (revision a33f32244d8550da8b4a26e277ce07d5c6d158b5)
1 /*
2  * PCI Express Hot Plug Controller Driver
3  *
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
8  *
9  * All rights reserved.
10  *
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.
15  *
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
20  * details.
21  *
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.
25  *
26  * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
27  *
28  */
29 
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>
35 #include <linux/workqueue.h>
36 #include "../pci.h"
37 #include "pciehp.h"
38 
39 static void interrupt_event_handler(struct work_struct *work);
40 
41 static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
42 {
43 	struct event_info *info;
44 
45 	info = kmalloc(sizeof(*info), GFP_ATOMIC);
46 	if (!info)
47 		return -ENOMEM;
48 
49 	info->event_type = event_type;
50 	info->p_slot = p_slot;
51 	INIT_WORK(&info->work, interrupt_event_handler);
52 
53 	schedule_work(&info->work);
54 
55 	return 0;
56 }
57 
58 u8 pciehp_handle_attention_button(struct slot *p_slot)
59 {
60 	u32 event_type;
61 	struct controller *ctrl = p_slot->ctrl;
62 
63 	/* Attention Button Change */
64 	ctrl_dbg(ctrl, "Attention button interrupt received\n");
65 
66 	/*
67 	 *  Button pressed - See if need to TAKE ACTION!!!
68 	 */
69 	ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot));
70 	event_type = INT_BUTTON_PRESS;
71 
72 	queue_interrupt_event(p_slot, event_type);
73 
74 	return 0;
75 }
76 
77 u8 pciehp_handle_switch_change(struct slot *p_slot)
78 {
79 	u8 getstatus;
80 	u32 event_type;
81 	struct controller *ctrl = p_slot->ctrl;
82 
83 	/* Switch Change */
84 	ctrl_dbg(ctrl, "Switch interrupt received\n");
85 
86 	pciehp_get_latch_status(p_slot, &getstatus);
87 	if (getstatus) {
88 		/*
89 		 * Switch opened
90 		 */
91 		ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot));
92 		event_type = INT_SWITCH_OPEN;
93 	} else {
94 		/*
95 		 *  Switch closed
96 		 */
97 		ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot));
98 		event_type = INT_SWITCH_CLOSE;
99 	}
100 
101 	queue_interrupt_event(p_slot, event_type);
102 
103 	return 1;
104 }
105 
106 u8 pciehp_handle_presence_change(struct slot *p_slot)
107 {
108 	u32 event_type;
109 	u8 presence_save;
110 	struct controller *ctrl = p_slot->ctrl;
111 
112 	/* Presence Change */
113 	ctrl_dbg(ctrl, "Presence/Notify input change\n");
114 
115 	/* Switch is open, assume a presence change
116 	 * Save the presence state
117 	 */
118 	pciehp_get_adapter_status(p_slot, &presence_save);
119 	if (presence_save) {
120 		/*
121 		 * Card Present
122 		 */
123 		ctrl_info(ctrl, "Card present on Slot(%s)\n", slot_name(p_slot));
124 		event_type = INT_PRESENCE_ON;
125 	} else {
126 		/*
127 		 * Not Present
128 		 */
129 		ctrl_info(ctrl, "Card not present on Slot(%s)\n",
130 			  slot_name(p_slot));
131 		event_type = INT_PRESENCE_OFF;
132 	}
133 
134 	queue_interrupt_event(p_slot, event_type);
135 
136 	return 1;
137 }
138 
139 u8 pciehp_handle_power_fault(struct slot *p_slot)
140 {
141 	u32 event_type;
142 	struct controller *ctrl = p_slot->ctrl;
143 
144 	/* power fault */
145 	ctrl_dbg(ctrl, "Power fault interrupt received\n");
146 	ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
147 	event_type = INT_POWER_FAULT;
148 	ctrl_info(ctrl, "Power fault bit %x set\n", 0);
149 	queue_interrupt_event(p_slot, event_type);
150 
151 	return 1;
152 }
153 
154 /* The following routines constitute the bulk of the
155    hotplug controller logic
156  */
157 
158 static void set_slot_off(struct controller *ctrl, struct slot * pslot)
159 {
160 	/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
161 	if (POWER_CTRL(ctrl)) {
162 		if (pciehp_power_off_slot(pslot)) {
163 			ctrl_err(ctrl,
164 				 "Issue of Slot Power Off command failed\n");
165 			return;
166 		}
167 		/*
168 		 * After turning power off, we must wait for at least 1 second
169 		 * before taking any action that relies on power having been
170 		 * removed from the slot/adapter.
171 		 */
172 		msleep(1000);
173 	}
174 
175 	if (PWR_LED(ctrl))
176 		pciehp_green_led_off(pslot);
177 
178 	if (ATTN_LED(ctrl)) {
179 		if (pciehp_set_attention_status(pslot, 1)) {
180 			ctrl_err(ctrl,
181 				 "Issue of Set Attention Led command failed\n");
182 			return;
183 		}
184 	}
185 }
186 
187 /**
188  * board_added - Called after a board has been added to the system.
189  * @p_slot: &slot where board is added
190  *
191  * Turns power on for the board.
192  * Configures board.
193  */
194 static int board_added(struct slot *p_slot)
195 {
196 	int retval = 0;
197 	struct controller *ctrl = p_slot->ctrl;
198 	struct pci_bus *parent = ctrl->pcie->port->subordinate;
199 
200 	if (POWER_CTRL(ctrl)) {
201 		/* Power on slot */
202 		retval = pciehp_power_on_slot(p_slot);
203 		if (retval)
204 			return retval;
205 	}
206 
207 	if (PWR_LED(ctrl))
208 		pciehp_green_led_blink(p_slot);
209 
210 	/* Check link training status */
211 	retval = pciehp_check_link_status(ctrl);
212 	if (retval) {
213 		ctrl_err(ctrl, "Failed to check link status\n");
214 		goto err_exit;
215 	}
216 
217 	/* Check for a power fault */
218 	if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
219 		ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
220 		retval = -EIO;
221 		goto err_exit;
222 	}
223 
224 	retval = pciehp_configure_device(p_slot);
225 	if (retval) {
226 		ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
227 			 pci_domain_nr(parent), parent->number);
228 		goto err_exit;
229 	}
230 
231 	if (PWR_LED(ctrl))
232 		pciehp_green_led_on(p_slot);
233 
234 	return 0;
235 
236 err_exit:
237 	set_slot_off(ctrl, p_slot);
238 	return retval;
239 }
240 
241 /**
242  * remove_board - Turns off slot and LEDs
243  * @p_slot: slot where board is being removed
244  */
245 static int remove_board(struct slot *p_slot)
246 {
247 	int retval = 0;
248 	struct controller *ctrl = p_slot->ctrl;
249 
250 	retval = pciehp_unconfigure_device(p_slot);
251 	if (retval)
252 		return retval;
253 
254 	if (POWER_CTRL(ctrl)) {
255 		/* power off slot */
256 		retval = pciehp_power_off_slot(p_slot);
257 		if (retval) {
258 			ctrl_err(ctrl,
259 				 "Issue of Slot Disable command failed\n");
260 			return retval;
261 		}
262 		/*
263 		 * After turning power off, we must wait for at least 1 second
264 		 * before taking any action that relies on power having been
265 		 * removed from the slot/adapter.
266 		 */
267 		msleep(1000);
268 	}
269 
270 	/* turn off Green LED */
271 	if (PWR_LED(ctrl))
272 		pciehp_green_led_off(p_slot);
273 
274 	return 0;
275 }
276 
277 struct power_work_info {
278 	struct slot *p_slot;
279 	struct work_struct work;
280 };
281 
282 /**
283  * pciehp_power_thread - handle pushbutton events
284  * @work: &struct work_struct describing work to be done
285  *
286  * Scheduled procedure to handle blocking stuff for the pushbuttons.
287  * Handles all pending events and exits.
288  */
289 static void pciehp_power_thread(struct work_struct *work)
290 {
291 	struct power_work_info *info =
292 		container_of(work, struct power_work_info, work);
293 	struct slot *p_slot = info->p_slot;
294 
295 	mutex_lock(&p_slot->lock);
296 	switch (p_slot->state) {
297 	case POWEROFF_STATE:
298 		mutex_unlock(&p_slot->lock);
299 		ctrl_dbg(p_slot->ctrl,
300 			 "Disabling domain:bus:device=%04x:%02x:00\n",
301 			 pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
302 			 p_slot->ctrl->pcie->port->subordinate->number);
303 		pciehp_disable_slot(p_slot);
304 		mutex_lock(&p_slot->lock);
305 		p_slot->state = STATIC_STATE;
306 		break;
307 	case POWERON_STATE:
308 		mutex_unlock(&p_slot->lock);
309 		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl))
310 			pciehp_green_led_off(p_slot);
311 		mutex_lock(&p_slot->lock);
312 		p_slot->state = STATIC_STATE;
313 		break;
314 	default:
315 		break;
316 	}
317 	mutex_unlock(&p_slot->lock);
318 
319 	kfree(info);
320 }
321 
322 void pciehp_queue_pushbutton_work(struct work_struct *work)
323 {
324 	struct slot *p_slot = container_of(work, struct slot, work.work);
325 	struct power_work_info *info;
326 
327 	info = kmalloc(sizeof(*info), GFP_KERNEL);
328 	if (!info) {
329 		ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
330 			 __func__);
331 		return;
332 	}
333 	info->p_slot = p_slot;
334 	INIT_WORK(&info->work, pciehp_power_thread);
335 
336 	mutex_lock(&p_slot->lock);
337 	switch (p_slot->state) {
338 	case BLINKINGOFF_STATE:
339 		p_slot->state = POWEROFF_STATE;
340 		break;
341 	case BLINKINGON_STATE:
342 		p_slot->state = POWERON_STATE;
343 		break;
344 	default:
345 		kfree(info);
346 		goto out;
347 	}
348 	queue_work(pciehp_wq, &info->work);
349  out:
350 	mutex_unlock(&p_slot->lock);
351 }
352 
353 /*
354  * Note: This function must be called with slot->lock held
355  */
356 static void handle_button_press_event(struct slot *p_slot)
357 {
358 	struct controller *ctrl = p_slot->ctrl;
359 	u8 getstatus;
360 
361 	switch (p_slot->state) {
362 	case STATIC_STATE:
363 		pciehp_get_power_status(p_slot, &getstatus);
364 		if (getstatus) {
365 			p_slot->state = BLINKINGOFF_STATE;
366 			ctrl_info(ctrl,
367 				  "PCI slot #%s - powering off due to button "
368 				  "press.\n", slot_name(p_slot));
369 		} else {
370 			p_slot->state = BLINKINGON_STATE;
371 			ctrl_info(ctrl,
372 				  "PCI slot #%s - powering on due to button "
373 				  "press.\n", slot_name(p_slot));
374 		}
375 		/* blink green LED and turn off amber */
376 		if (PWR_LED(ctrl))
377 			pciehp_green_led_blink(p_slot);
378 		if (ATTN_LED(ctrl))
379 			pciehp_set_attention_status(p_slot, 0);
380 
381 		schedule_delayed_work(&p_slot->work, 5*HZ);
382 		break;
383 	case BLINKINGOFF_STATE:
384 	case BLINKINGON_STATE:
385 		/*
386 		 * Cancel if we are still blinking; this means that we
387 		 * press the attention again before the 5 sec. limit
388 		 * expires to cancel hot-add or hot-remove
389 		 */
390 		ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot));
391 		cancel_delayed_work(&p_slot->work);
392 		if (p_slot->state == BLINKINGOFF_STATE) {
393 			if (PWR_LED(ctrl))
394 				pciehp_green_led_on(p_slot);
395 		} else {
396 			if (PWR_LED(ctrl))
397 				pciehp_green_led_off(p_slot);
398 		}
399 		if (ATTN_LED(ctrl))
400 			pciehp_set_attention_status(p_slot, 0);
401 		ctrl_info(ctrl, "PCI slot #%s - action canceled "
402 			  "due to button press\n", slot_name(p_slot));
403 		p_slot->state = STATIC_STATE;
404 		break;
405 	case POWEROFF_STATE:
406 	case POWERON_STATE:
407 		/*
408 		 * Ignore if the slot is on power-on or power-off state;
409 		 * this means that the previous attention button action
410 		 * to hot-add or hot-remove is undergoing
411 		 */
412 		ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot));
413 		break;
414 	default:
415 		ctrl_warn(ctrl, "Not a valid state\n");
416 		break;
417 	}
418 }
419 
420 /*
421  * Note: This function must be called with slot->lock held
422  */
423 static void handle_surprise_event(struct slot *p_slot)
424 {
425 	u8 getstatus;
426 	struct power_work_info *info;
427 
428 	info = kmalloc(sizeof(*info), GFP_KERNEL);
429 	if (!info) {
430 		ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
431 			 __func__);
432 		return;
433 	}
434 	info->p_slot = p_slot;
435 	INIT_WORK(&info->work, pciehp_power_thread);
436 
437 	pciehp_get_adapter_status(p_slot, &getstatus);
438 	if (!getstatus)
439 		p_slot->state = POWEROFF_STATE;
440 	else
441 		p_slot->state = POWERON_STATE;
442 
443 	queue_work(pciehp_wq, &info->work);
444 }
445 
446 static void interrupt_event_handler(struct work_struct *work)
447 {
448 	struct event_info *info = container_of(work, struct event_info, work);
449 	struct slot *p_slot = info->p_slot;
450 	struct controller *ctrl = p_slot->ctrl;
451 
452 	mutex_lock(&p_slot->lock);
453 	switch (info->event_type) {
454 	case INT_BUTTON_PRESS:
455 		handle_button_press_event(p_slot);
456 		break;
457 	case INT_POWER_FAULT:
458 		if (!POWER_CTRL(ctrl))
459 			break;
460 		if (ATTN_LED(ctrl))
461 			pciehp_set_attention_status(p_slot, 1);
462 		if (PWR_LED(ctrl))
463 			pciehp_green_led_off(p_slot);
464 		break;
465 	case INT_PRESENCE_ON:
466 	case INT_PRESENCE_OFF:
467 		if (!HP_SUPR_RM(ctrl))
468 			break;
469 		ctrl_dbg(ctrl, "Surprise Removal\n");
470 		handle_surprise_event(p_slot);
471 		break;
472 	default:
473 		break;
474 	}
475 	mutex_unlock(&p_slot->lock);
476 
477 	kfree(info);
478 }
479 
480 int pciehp_enable_slot(struct slot *p_slot)
481 {
482 	u8 getstatus = 0;
483 	int rc;
484 	struct controller *ctrl = p_slot->ctrl;
485 
486 	rc = pciehp_get_adapter_status(p_slot, &getstatus);
487 	if (rc || !getstatus) {
488 		ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
489 		return -ENODEV;
490 	}
491 	if (MRL_SENS(p_slot->ctrl)) {
492 		rc = pciehp_get_latch_status(p_slot, &getstatus);
493 		if (rc || getstatus) {
494 			ctrl_info(ctrl, "Latch open on slot(%s)\n",
495 				  slot_name(p_slot));
496 			return -ENODEV;
497 		}
498 	}
499 
500 	if (POWER_CTRL(p_slot->ctrl)) {
501 		rc = pciehp_get_power_status(p_slot, &getstatus);
502 		if (rc || getstatus) {
503 			ctrl_info(ctrl, "Already enabled on slot(%s)\n",
504 				  slot_name(p_slot));
505 			return -EINVAL;
506 		}
507 	}
508 
509 	pciehp_get_latch_status(p_slot, &getstatus);
510 
511 	rc = board_added(p_slot);
512 	if (rc) {
513 		pciehp_get_latch_status(p_slot, &getstatus);
514 	}
515 	return rc;
516 }
517 
518 
519 int pciehp_disable_slot(struct slot *p_slot)
520 {
521 	u8 getstatus = 0;
522 	int ret = 0;
523 	struct controller *ctrl = p_slot->ctrl;
524 
525 	if (!p_slot->ctrl)
526 		return 1;
527 
528 	if (!HP_SUPR_RM(p_slot->ctrl)) {
529 		ret = pciehp_get_adapter_status(p_slot, &getstatus);
530 		if (ret || !getstatus) {
531 			ctrl_info(ctrl, "No adapter on slot(%s)\n",
532 				  slot_name(p_slot));
533 			return -ENODEV;
534 		}
535 	}
536 
537 	if (MRL_SENS(p_slot->ctrl)) {
538 		ret = pciehp_get_latch_status(p_slot, &getstatus);
539 		if (ret || getstatus) {
540 			ctrl_info(ctrl, "Latch open on slot(%s)\n",
541 				  slot_name(p_slot));
542 			return -ENODEV;
543 		}
544 	}
545 
546 	if (POWER_CTRL(p_slot->ctrl)) {
547 		ret = pciehp_get_power_status(p_slot, &getstatus);
548 		if (ret || !getstatus) {
549 			ctrl_info(ctrl, "Already disabled on slot(%s)\n",
550 				  slot_name(p_slot));
551 			return -EINVAL;
552 		}
553 	}
554 
555 	return remove_board(p_slot);
556 }
557 
558 int pciehp_sysfs_enable_slot(struct slot *p_slot)
559 {
560 	int retval = -ENODEV;
561 	struct controller *ctrl = p_slot->ctrl;
562 
563 	mutex_lock(&p_slot->lock);
564 	switch (p_slot->state) {
565 	case BLINKINGON_STATE:
566 		cancel_delayed_work(&p_slot->work);
567 	case STATIC_STATE:
568 		p_slot->state = POWERON_STATE;
569 		mutex_unlock(&p_slot->lock);
570 		retval = pciehp_enable_slot(p_slot);
571 		mutex_lock(&p_slot->lock);
572 		p_slot->state = STATIC_STATE;
573 		break;
574 	case POWERON_STATE:
575 		ctrl_info(ctrl, "Slot %s is already in powering on state\n",
576 			  slot_name(p_slot));
577 		break;
578 	case BLINKINGOFF_STATE:
579 	case POWEROFF_STATE:
580 		ctrl_info(ctrl, "Already enabled on slot %s\n",
581 			  slot_name(p_slot));
582 		break;
583 	default:
584 		ctrl_err(ctrl, "Not a valid state on slot %s\n",
585 			 slot_name(p_slot));
586 		break;
587 	}
588 	mutex_unlock(&p_slot->lock);
589 
590 	return retval;
591 }
592 
593 int pciehp_sysfs_disable_slot(struct slot *p_slot)
594 {
595 	int retval = -ENODEV;
596 	struct controller *ctrl = p_slot->ctrl;
597 
598 	mutex_lock(&p_slot->lock);
599 	switch (p_slot->state) {
600 	case BLINKINGOFF_STATE:
601 		cancel_delayed_work(&p_slot->work);
602 	case STATIC_STATE:
603 		p_slot->state = POWEROFF_STATE;
604 		mutex_unlock(&p_slot->lock);
605 		retval = pciehp_disable_slot(p_slot);
606 		mutex_lock(&p_slot->lock);
607 		p_slot->state = STATIC_STATE;
608 		break;
609 	case POWEROFF_STATE:
610 		ctrl_info(ctrl, "Slot %s is already in powering off state\n",
611 			  slot_name(p_slot));
612 		break;
613 	case BLINKINGON_STATE:
614 	case POWERON_STATE:
615 		ctrl_info(ctrl, "Already disabled on slot %s\n",
616 			  slot_name(p_slot));
617 		break;
618 	default:
619 		ctrl_err(ctrl, "Not a valid state on slot %s\n",
620 			 slot_name(p_slot));
621 		break;
622 	}
623 	mutex_unlock(&p_slot->lock);
624 
625 	return retval;
626 }
627