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