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