]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/pci/hotplug/pciehp_ctrl.c
PCI: pciehp: Clean up debug logging
[mirror_ubuntu-bionic-kernel.git] / drivers / pci / hotplug / pciehp_ctrl.c
CommitLineData
1da177e4
LT
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 *
8cf4c195 26 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
1da177e4
LT
27 *
28 */
29
1da177e4
LT
30#include <linux/module.h>
31#include <linux/kernel.h>
32#include <linux/types.h>
5a0e3ad6 33#include <linux/slab.h>
1da177e4
LT
34#include <linux/pci.h>
35#include "../pci.h"
36#include "pciehp.h"
1da177e4 37
5d386e1a 38static void interrupt_event_handler(struct work_struct *work);
1da177e4 39
5d386e1a 40static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
49ed2b49 41{
5d386e1a
KK
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
c2be6f93 52 queue_work(p_slot->wq, &info->work);
5d386e1a
KK
53
54 return 0;
49ed2b49
KK
55}
56
dbd79aed 57u8 pciehp_handle_attention_button(struct slot *p_slot)
1da177e4 58{
5d386e1a 59 u32 event_type;
7f2feec1 60 struct controller *ctrl = p_slot->ctrl;
1da177e4 61
1da177e4
LT
62 /*
63 * Button pressed - See if need to TAKE ACTION!!!
64 */
e1acb24f 65 ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot));
5d386e1a 66 event_type = INT_BUTTON_PRESS;
1da177e4 67
5d386e1a 68 queue_interrupt_event(p_slot, event_type);
1da177e4
LT
69
70 return 0;
1da177e4
LT
71}
72
dbd79aed 73u8 pciehp_handle_switch_change(struct slot *p_slot)
1da177e4 74{
1da177e4 75 u8 getstatus;
5d386e1a 76 u32 event_type;
7f2feec1 77 struct controller *ctrl = p_slot->ctrl;
1da177e4 78
82a9e79e 79 pciehp_get_latch_status(p_slot, &getstatus);
1da177e4
LT
80 if (getstatus) {
81 /*
82 * Switch opened
83 */
e1acb24f 84 ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot));
5d386e1a 85 event_type = INT_SWITCH_OPEN;
1da177e4
LT
86 } else {
87 /*
88 * Switch closed
89 */
e1acb24f 90 ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot));
5d386e1a 91 event_type = INT_SWITCH_CLOSE;
1da177e4
LT
92 }
93
5d386e1a 94 queue_interrupt_event(p_slot, event_type);
1da177e4 95
5d386e1a 96 return 1;
1da177e4
LT
97}
98
dbd79aed 99u8 pciehp_handle_presence_change(struct slot *p_slot)
1da177e4 100{
5d386e1a
KK
101 u32 event_type;
102 u8 presence_save;
7f2feec1 103 struct controller *ctrl = p_slot->ctrl;
1da177e4 104
1da177e4
LT
105 /* Switch is open, assume a presence change
106 * Save the presence state
107 */
82a9e79e 108 pciehp_get_adapter_status(p_slot, &presence_save);
ed6cbcf2 109 if (presence_save) {
1da177e4
LT
110 /*
111 * Card Present
112 */
e1acb24f 113 ctrl_info(ctrl, "Card present on Slot(%s)\n", slot_name(p_slot));
5d386e1a 114 event_type = INT_PRESENCE_ON;
1da177e4
LT
115 } else {
116 /*
117 * Not Present
118 */
e1acb24f
AC
119 ctrl_info(ctrl, "Card not present on Slot(%s)\n",
120 slot_name(p_slot));
5d386e1a 121 event_type = INT_PRESENCE_OFF;
1da177e4
LT
122 }
123
5d386e1a 124 queue_interrupt_event(p_slot, event_type);
1da177e4 125
5d386e1a 126 return 1;
1da177e4
LT
127}
128
dbd79aed 129u8 pciehp_handle_power_fault(struct slot *p_slot)
1da177e4 130{
5d386e1a 131 u32 event_type;
7f2feec1 132 struct controller *ctrl = p_slot->ctrl;
1da177e4 133
5651c48c
KK
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);
5d386e1a
KK
137 queue_interrupt_event(p_slot, event_type);
138
139 return 1;
1da177e4
LT
140}
141
e48f1b67
RJ
142void pciehp_handle_linkstate_change(struct slot *p_slot)
143{
144 u32 event_type;
145 struct controller *ctrl = p_slot->ctrl;
146
e48f1b67
RJ
147 if (pciehp_check_link_active(ctrl)) {
148 ctrl_info(ctrl, "slot(%s): Link Up event\n",
149 slot_name(p_slot));
150 event_type = INT_LINK_UP;
151 } else {
152 ctrl_info(ctrl, "slot(%s): Link Down event\n",
153 slot_name(p_slot));
154 event_type = INT_LINK_DOWN;
155 }
156
157 queue_interrupt_event(p_slot, event_type);
158}
159
36ed27b0 160/* The following routines constitute the bulk of the
1da177e4
LT
161 hotplug controller logic
162 */
163
3c78bc61 164static void set_slot_off(struct controller *ctrl, struct slot *pslot)
1da177e4 165{
1da177e4 166 /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
ae416e6b 167 if (POWER_CTRL(ctrl)) {
6dae6202
BH
168 pciehp_power_off_slot(pslot);
169
c7b4fee3
KK
170 /*
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.
174 */
175 msleep(1000);
1da177e4
LT
176 }
177
af9ab791
BH
178 pciehp_green_led_off(pslot);
179 pciehp_set_attention_status(pslot, 1);
1da177e4
LT
180}
181
182/**
183 * board_added - Called after a board has been added to the system.
26e6c66e 184 * @p_slot: &slot where board is added
1da177e4 185 *
26e6c66e
RD
186 * Turns power on for the board.
187 * Configures board.
1da177e4 188 */
ed6cbcf2 189static int board_added(struct slot *p_slot)
1da177e4 190{
44ef4cef 191 int retval = 0;
ca22a5e4 192 struct controller *ctrl = p_slot->ctrl;
385e2491 193 struct pci_bus *parent = ctrl->pcie->port->subordinate;
1da177e4 194
ae416e6b 195 if (POWER_CTRL(ctrl)) {
1da177e4 196 /* Power on slot */
82a9e79e 197 retval = pciehp_power_on_slot(p_slot);
44ef4cef
KK
198 if (retval)
199 return retval;
1da177e4 200 }
36ed27b0 201
af9ab791 202 pciehp_green_led_blink(p_slot);
1da177e4 203
44ef4cef 204 /* Check link training status */
82a9e79e 205 retval = pciehp_check_link_status(ctrl);
44ef4cef 206 if (retval) {
18b341b7 207 ctrl_err(ctrl, "Failed to check link status\n");
5651c48c 208 goto err_exit;
1da177e4
LT
209 }
210
1da177e4 211 /* Check for a power fault */
5651c48c
KK
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));
d9fb42a8 214 retval = -EIO;
71b720c0 215 goto err_exit;
1da177e4
LT
216 }
217
44ef4cef
KK
218 retval = pciehp_configure_device(p_slot);
219 if (retval) {
d689f7eb
KK
220 ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
221 pci_domain_nr(parent), parent->number);
50277c8b
YW
222 if (retval != -EEXIST)
223 goto err_exit;
71b720c0 224 }
1da177e4 225
af9ab791 226 pciehp_green_led_on(p_slot);
1da177e4 227 return 0;
71b720c0
RS
228
229err_exit:
230 set_slot_off(ctrl, p_slot);
44ef4cef 231 return retval;
1da177e4
LT
232}
233
1da177e4 234/**
26e6c66e
RD
235 * remove_board - Turns off slot and LEDs
236 * @p_slot: slot where board is being removed
1da177e4 237 */
ed6cbcf2 238static int remove_board(struct slot *p_slot)
1da177e4 239{
6dae6202 240 int retval;
ca22a5e4 241 struct controller *ctrl = p_slot->ctrl;
1da177e4 242
44ef4cef
KK
243 retval = pciehp_unconfigure_device(p_slot);
244 if (retval)
245 return retval;
1da177e4 246
ae416e6b 247 if (POWER_CTRL(ctrl)) {
6dae6202
BH
248 pciehp_power_off_slot(p_slot);
249
c7b4fee3
KK
250 /*
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.
254 */
255 msleep(1000);
1da177e4
LT
256 }
257
82a9e79e 258 /* turn off Green LED */
af9ab791 259 pciehp_green_led_off(p_slot);
1da177e4
LT
260 return 0;
261}
262
5d386e1a
KK
263struct power_work_info {
264 struct slot *p_slot;
265 struct work_struct work;
c4f2f5e4
RJ
266 unsigned int req;
267#define DISABLE_REQ 0
268#define ENABLE_REQ 1
5d386e1a 269};
1da177e4
LT
270
271/**
26e6c66e
RD
272 * pciehp_power_thread - handle pushbutton events
273 * @work: &struct work_struct describing work to be done
1da177e4 274 *
26e6c66e 275 * Scheduled procedure to handle blocking stuff for the pushbuttons.
1da177e4 276 * Handles all pending events and exits.
1da177e4 277 */
5d386e1a 278static void pciehp_power_thread(struct work_struct *work)
1da177e4 279{
5d386e1a
KK
280 struct power_work_info *info =
281 container_of(work, struct power_work_info, work);
282 struct slot *p_slot = info->p_slot;
50b52fde 283 int ret;
5d386e1a 284
c4f2f5e4
RJ
285 switch (info->req) {
286 case DISABLE_REQ:
50b52fde 287 mutex_lock(&p_slot->hotplug_lock);
1da177e4 288 pciehp_disable_slot(p_slot);
50b52fde 289 mutex_unlock(&p_slot->hotplug_lock);
5d386e1a 290 mutex_lock(&p_slot->lock);
1da177e4 291 p_slot->state = STATIC_STATE;
5d386e1a 292 mutex_unlock(&p_slot->lock);
c4f2f5e4
RJ
293 break;
294 case ENABLE_REQ:
50b52fde
RJ
295 mutex_lock(&p_slot->hotplug_lock);
296 ret = pciehp_enable_slot(p_slot);
297 mutex_unlock(&p_slot->hotplug_lock);
298 if (ret)
82a9e79e 299 pciehp_green_led_off(p_slot);
5d386e1a 300 mutex_lock(&p_slot->lock);
1da177e4 301 p_slot->state = STATIC_STATE;
c4f2f5e4 302 mutex_unlock(&p_slot->lock);
5d386e1a
KK
303 break;
304 default:
305 break;
1da177e4
LT
306 }
307
5d386e1a 308 kfree(info);
1da177e4
LT
309}
310
e325e1f0 311void pciehp_queue_pushbutton_work(struct work_struct *work)
1da177e4 312{
5d386e1a
KK
313 struct slot *p_slot = container_of(work, struct slot, work.work);
314 struct power_work_info *info;
1da177e4 315
5d386e1a
KK
316 info = kmalloc(sizeof(*info), GFP_KERNEL);
317 if (!info) {
7f2feec1
TI
318 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
319 __func__);
1da177e4
LT
320 return;
321 }
5d386e1a
KK
322 info->p_slot = p_slot;
323 INIT_WORK(&info->work, pciehp_power_thread);
1da177e4 324
5d386e1a
KK
325 mutex_lock(&p_slot->lock);
326 switch (p_slot->state) {
327 case BLINKINGOFF_STATE:
1da177e4 328 p_slot->state = POWEROFF_STATE;
c4f2f5e4 329 info->req = DISABLE_REQ;
5d386e1a
KK
330 break;
331 case BLINKINGON_STATE:
1da177e4 332 p_slot->state = POWERON_STATE;
c4f2f5e4 333 info->req = ENABLE_REQ;
5d386e1a
KK
334 break;
335 default:
6fcaf17a 336 kfree(info);
5d386e1a 337 goto out;
1da177e4 338 }
c2be6f93 339 queue_work(p_slot->wq, &info->work);
5d386e1a
KK
340 out:
341 mutex_unlock(&p_slot->lock);
1da177e4
LT
342}
343
5d386e1a
KK
344/*
345 * Note: This function must be called with slot->lock held
346 */
347static void handle_button_press_event(struct slot *p_slot)
1da177e4 348{
5d386e1a 349 struct controller *ctrl = p_slot->ctrl;
1da177e4 350 u8 getstatus;
1da177e4 351
5d386e1a
KK
352 switch (p_slot->state) {
353 case STATIC_STATE:
82a9e79e 354 pciehp_get_power_status(p_slot, &getstatus);
5d386e1a
KK
355 if (getstatus) {
356 p_slot->state = BLINKINGOFF_STATE;
227f0647
RD
357 ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n",
358 slot_name(p_slot));
5d386e1a
KK
359 } else {
360 p_slot->state = BLINKINGON_STATE;
227f0647
RD
361 ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n",
362 slot_name(p_slot));
5d386e1a
KK
363 }
364 /* blink green LED and turn off amber */
af9ab791
BH
365 pciehp_green_led_blink(p_slot);
366 pciehp_set_attention_status(p_slot, 0);
c2be6f93 367 queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
5d386e1a
KK
368 break;
369 case BLINKINGOFF_STATE:
370 case BLINKINGON_STATE:
371 /*
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
375 */
e1acb24f 376 ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot));
5d386e1a 377 cancel_delayed_work(&p_slot->work);
9cad7f58 378 if (p_slot->state == BLINKINGOFF_STATE)
af9ab791 379 pciehp_green_led_on(p_slot);
9cad7f58 380 else
af9ab791 381 pciehp_green_led_off(p_slot);
af9ab791 382 pciehp_set_attention_status(p_slot, 0);
227f0647
RD
383 ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n",
384 slot_name(p_slot));
5d386e1a
KK
385 p_slot->state = STATIC_STATE;
386 break;
387 case POWEROFF_STATE:
388 case POWERON_STATE:
389 /*
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
393 */
e1acb24f 394 ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot));
5d386e1a
KK
395 break;
396 default:
3784e0c6 397 ctrl_warn(ctrl, "ignoring invalid state %#x\n", p_slot->state);
5d386e1a 398 break;
1da177e4
LT
399 }
400}
401
5d386e1a
KK
402/*
403 * Note: This function must be called with slot->lock held
404 */
405static void handle_surprise_event(struct slot *p_slot)
406{
407 u8 getstatus;
408 struct power_work_info *info;
409
410 info = kmalloc(sizeof(*info), GFP_KERNEL);
411 if (!info) {
7f2feec1
TI
412 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
413 __func__);
5d386e1a
KK
414 return;
415 }
416 info->p_slot = p_slot;
417 INIT_WORK(&info->work, pciehp_power_thread);
418
82a9e79e 419 pciehp_get_adapter_status(p_slot, &getstatus);
c4f2f5e4 420 if (!getstatus) {
5d386e1a 421 p_slot->state = POWEROFF_STATE;
c4f2f5e4
RJ
422 info->req = DISABLE_REQ;
423 } else {
5d386e1a 424 p_slot->state = POWERON_STATE;
c4f2f5e4
RJ
425 info->req = ENABLE_REQ;
426 }
5d386e1a 427
c2be6f93 428 queue_work(p_slot->wq, &info->work);
5d386e1a
KK
429}
430
e48f1b67
RJ
431/*
432 * Note: This function must be called with slot->lock held
433 */
434static void handle_link_event(struct slot *p_slot, u32 event)
435{
436 struct controller *ctrl = p_slot->ctrl;
437 struct power_work_info *info;
438
439 info = kmalloc(sizeof(*info), GFP_KERNEL);
440 if (!info) {
441 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
442 __func__);
443 return;
444 }
445 info->p_slot = p_slot;
c4f2f5e4 446 info->req = event == INT_LINK_UP ? ENABLE_REQ : DISABLE_REQ;
e48f1b67
RJ
447 INIT_WORK(&info->work, pciehp_power_thread);
448
449 switch (p_slot->state) {
450 case BLINKINGON_STATE:
451 case BLINKINGOFF_STATE:
452 cancel_delayed_work(&p_slot->work);
453 /* Fall through */
454 case STATIC_STATE:
455 p_slot->state = event == INT_LINK_UP ?
456 POWERON_STATE : POWEROFF_STATE;
457 queue_work(p_slot->wq, &info->work);
458 break;
459 case POWERON_STATE:
460 if (event == INT_LINK_UP) {
461 ctrl_info(ctrl,
462 "Link Up event ignored on slot(%s): already powering on\n",
463 slot_name(p_slot));
464 kfree(info);
465 } else {
466 ctrl_info(ctrl,
467 "Link Down event queued on slot(%s): currently getting powered on\n",
468 slot_name(p_slot));
469 p_slot->state = POWEROFF_STATE;
470 queue_work(p_slot->wq, &info->work);
471 }
472 break;
473 case POWEROFF_STATE:
474 if (event == INT_LINK_UP) {
475 ctrl_info(ctrl,
476 "Link Up event queued on slot(%s): currently getting powered off\n",
477 slot_name(p_slot));
478 p_slot->state = POWERON_STATE;
479 queue_work(p_slot->wq, &info->work);
480 } else {
481 ctrl_info(ctrl,
482 "Link Down event ignored on slot(%s): already powering off\n",
483 slot_name(p_slot));
484 kfree(info);
485 }
486 break;
487 default:
3784e0c6
BH
488 ctrl_err(ctrl, "ignoring invalid state %#x on slot(%s)\n",
489 p_slot->state, slot_name(p_slot));
e48f1b67
RJ
490 kfree(info);
491 break;
492 }
493}
494
5d386e1a
KK
495static void interrupt_event_handler(struct work_struct *work)
496{
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;
500
501 mutex_lock(&p_slot->lock);
502 switch (info->event_type) {
503 case INT_BUTTON_PRESS:
504 handle_button_press_event(p_slot);
505 break;
506 case INT_POWER_FAULT:
ae416e6b 507 if (!POWER_CTRL(ctrl))
5d386e1a 508 break;
af9ab791
BH
509 pciehp_set_attention_status(p_slot, 1);
510 pciehp_green_led_off(p_slot);
5d386e1a
KK
511 break;
512 case INT_PRESENCE_ON:
2b3940b6
RJ
513 handle_surprise_event(p_slot);
514 break;
515 case INT_PRESENCE_OFF:
516 /*
517 * Regardless of surprise capability, we need to
518 * definitely remove a card that has been pulled out!
519 */
5d386e1a
KK
520 handle_surprise_event(p_slot);
521 break;
e48f1b67
RJ
522 case INT_LINK_UP:
523 case INT_LINK_DOWN:
524 handle_link_event(p_slot, info->event_type);
525 break;
5d386e1a 526 default:
5d386e1a
KK
527 break;
528 }
529 mutex_unlock(&p_slot->lock);
530
531 kfree(info);
532}
533
50b52fde
RJ
534/*
535 * Note: This function must be called with slot->hotplug_lock held
536 */
1da177e4
LT
537int pciehp_enable_slot(struct slot *p_slot)
538{
539 u8 getstatus = 0;
540 int rc;
7f2feec1 541 struct controller *ctrl = p_slot->ctrl;
1da177e4 542
6dae6202
BH
543 pciehp_get_adapter_status(p_slot, &getstatus);
544 if (!getstatus) {
18b341b7 545 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
c9d86d76 546 return -ENODEV;
1da177e4 547 }
ae416e6b 548 if (MRL_SENS(p_slot->ctrl)) {
6dae6202
BH
549 pciehp_get_latch_status(p_slot, &getstatus);
550 if (getstatus) {
18b341b7
TI
551 ctrl_info(ctrl, "Latch open on slot(%s)\n",
552 slot_name(p_slot));
c9d86d76 553 return -ENODEV;
1da177e4
LT
554 }
555 }
36ed27b0 556
ae416e6b 557 if (POWER_CTRL(p_slot->ctrl)) {
6dae6202
BH
558 pciehp_get_power_status(p_slot, &getstatus);
559 if (getstatus) {
18b341b7
TI
560 ctrl_info(ctrl, "Already enabled on slot(%s)\n",
561 slot_name(p_slot));
c9d86d76 562 return -EINVAL;
1da177e4
LT
563 }
564 }
1da177e4 565
82a9e79e 566 pciehp_get_latch_status(p_slot, &getstatus);
1da177e4 567
ca22a5e4 568 rc = board_added(p_slot);
9cad7f58 569 if (rc)
82a9e79e 570 pciehp_get_latch_status(p_slot, &getstatus);
9cad7f58 571
1da177e4
LT
572 return rc;
573}
574
50b52fde
RJ
575/*
576 * Note: This function must be called with slot->hotplug_lock held
577 */
1da177e4
LT
578int pciehp_disable_slot(struct slot *p_slot)
579{
1da177e4 580 u8 getstatus = 0;
7f2feec1 581 struct controller *ctrl = p_slot->ctrl;
1da177e4
LT
582
583 if (!p_slot->ctrl)
584 return 1;
585
ae416e6b 586 if (POWER_CTRL(p_slot->ctrl)) {
6dae6202
BH
587 pciehp_get_power_status(p_slot, &getstatus);
588 if (!getstatus) {
18b341b7
TI
589 ctrl_info(ctrl, "Already disabled on slot(%s)\n",
590 slot_name(p_slot));
c9d86d76 591 return -EINVAL;
1da177e4
LT
592 }
593 }
594
445f7985 595 return remove_board(p_slot);
1da177e4
LT
596}
597
5d386e1a
KK
598int pciehp_sysfs_enable_slot(struct slot *p_slot)
599{
600 int retval = -ENODEV;
7f2feec1 601 struct controller *ctrl = p_slot->ctrl;
5d386e1a
KK
602
603 mutex_lock(&p_slot->lock);
604 switch (p_slot->state) {
605 case BLINKINGON_STATE:
606 cancel_delayed_work(&p_slot->work);
607 case STATIC_STATE:
608 p_slot->state = POWERON_STATE;
609 mutex_unlock(&p_slot->lock);
50b52fde 610 mutex_lock(&p_slot->hotplug_lock);
5d386e1a 611 retval = pciehp_enable_slot(p_slot);
50b52fde 612 mutex_unlock(&p_slot->hotplug_lock);
5d386e1a
KK
613 mutex_lock(&p_slot->lock);
614 p_slot->state = STATIC_STATE;
615 break;
616 case POWERON_STATE:
7f2feec1 617 ctrl_info(ctrl, "Slot %s is already in powering on state\n",
e1acb24f 618 slot_name(p_slot));
5d386e1a
KK
619 break;
620 case BLINKINGOFF_STATE:
621 case POWEROFF_STATE:
e1acb24f
AC
622 ctrl_info(ctrl, "Already enabled on slot %s\n",
623 slot_name(p_slot));
5d386e1a
KK
624 break;
625 default:
3784e0c6
BH
626 ctrl_err(ctrl, "invalid state %#x on slot %s\n",
627 p_slot->state, slot_name(p_slot));
5d386e1a
KK
628 break;
629 }
630 mutex_unlock(&p_slot->lock);
631
632 return retval;
633}
634
635int pciehp_sysfs_disable_slot(struct slot *p_slot)
636{
637 int retval = -ENODEV;
7f2feec1 638 struct controller *ctrl = p_slot->ctrl;
5d386e1a
KK
639
640 mutex_lock(&p_slot->lock);
641 switch (p_slot->state) {
642 case BLINKINGOFF_STATE:
643 cancel_delayed_work(&p_slot->work);
644 case STATIC_STATE:
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;
650 break;
651 case POWEROFF_STATE:
7f2feec1 652 ctrl_info(ctrl, "Slot %s is already in powering off state\n",
e1acb24f 653 slot_name(p_slot));
5d386e1a
KK
654 break;
655 case BLINKINGON_STATE:
656 case POWERON_STATE:
e1acb24f
AC
657 ctrl_info(ctrl, "Already disabled on slot %s\n",
658 slot_name(p_slot));
5d386e1a
KK
659 break;
660 default:
3784e0c6
BH
661 ctrl_err(ctrl, "invalid state %#x on slot %s\n",
662 p_slot->state, slot_name(p_slot));
5d386e1a
KK
663 break;
664 }
665 mutex_unlock(&p_slot->lock);
666
667 return retval;
668}