GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / pci / hotplug / shpchp_ctrl.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Standard Hot Plug Controller Driver
4  *
5  * Copyright (C) 1995,2001 Compaq Computer Corporation
6  * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
7  * Copyright (C) 2001 IBM Corp.
8  * Copyright (C) 2003-2004 Intel Corporation
9  *
10  * All rights reserved.
11  *
12  * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
13  *
14  */
15
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/types.h>
19 #include <linux/slab.h>
20 #include <linux/pci.h>
21 #include "../pci.h"
22 #include "shpchp.h"
23
24 static void interrupt_event_handler(struct work_struct *work);
25 static int shpchp_enable_slot(struct slot *p_slot);
26 static int shpchp_disable_slot(struct slot *p_slot);
27
28 static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
29 {
30         struct event_info *info;
31
32         info = kmalloc(sizeof(*info), GFP_ATOMIC);
33         if (!info)
34                 return -ENOMEM;
35
36         info->event_type = event_type;
37         info->p_slot = p_slot;
38         INIT_WORK(&info->work, interrupt_event_handler);
39
40         queue_work(p_slot->wq, &info->work);
41
42         return 0;
43 }
44
45 u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl)
46 {
47         struct slot *p_slot;
48         u32 event_type;
49
50         /* Attention Button Change */
51         ctrl_dbg(ctrl, "Attention button interrupt received\n");
52
53         p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
54         p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
55
56         /*
57          *  Button pressed - See if need to TAKE ACTION!!!
58          */
59         ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot));
60         event_type = INT_BUTTON_PRESS;
61
62         queue_interrupt_event(p_slot, event_type);
63
64         return 0;
65
66 }
67
68 u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl)
69 {
70         struct slot *p_slot;
71         u8 getstatus;
72         u32 event_type;
73
74         /* Switch Change */
75         ctrl_dbg(ctrl, "Switch interrupt received\n");
76
77         p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
78         p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
79         p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
80         ctrl_dbg(ctrl, "Card present %x Power status %x\n",
81                  p_slot->presence_save, p_slot->pwr_save);
82
83         if (getstatus) {
84                 /*
85                  * Switch opened
86                  */
87                 ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot));
88                 event_type = INT_SWITCH_OPEN;
89                 if (p_slot->pwr_save && p_slot->presence_save) {
90                         event_type = INT_POWER_FAULT;
91                         ctrl_err(ctrl, "Surprise Removal of card\n");
92                 }
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 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl)
107 {
108         struct slot *p_slot;
109         u32 event_type;
110
111         /* Presence Change */
112         ctrl_dbg(ctrl, "Presence/Notify input change\n");
113
114         p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
115
116         /*
117          * Save the presence state
118          */
119         p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
120         if (p_slot->presence_save) {
121                 /*
122                  * Card Present
123                  */
124                 ctrl_info(ctrl, "Card present on Slot(%s)\n",
125                           slot_name(p_slot));
126                 event_type = INT_PRESENCE_ON;
127         } else {
128                 /*
129                  * Not Present
130                  */
131                 ctrl_info(ctrl, "Card not present on Slot(%s)\n",
132                           slot_name(p_slot));
133                 event_type = INT_PRESENCE_OFF;
134         }
135
136         queue_interrupt_event(p_slot, event_type);
137
138         return 1;
139 }
140
141 u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
142 {
143         struct slot *p_slot;
144         u32 event_type;
145
146         /* Power fault */
147         ctrl_dbg(ctrl, "Power fault interrupt received\n");
148
149         p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
150
151         if (!(p_slot->hpc_ops->query_power_fault(p_slot))) {
152                 /*
153                  * Power fault Cleared
154                  */
155                 ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
156                           slot_name(p_slot));
157                 p_slot->status = 0x00;
158                 event_type = INT_POWER_FAULT_CLEAR;
159         } else {
160                 /*
161                  *   Power fault
162                  */
163                 ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot));
164                 event_type = INT_POWER_FAULT;
165                 /* set power fault status for this board */
166                 p_slot->status = 0xFF;
167                 ctrl_info(ctrl, "Power fault bit %x set\n", hp_slot);
168         }
169
170         queue_interrupt_event(p_slot, event_type);
171
172         return 1;
173 }
174
175 /* The following routines constitute the bulk of the
176    hotplug controller logic
177  */
178 static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
179                 enum pci_bus_speed speed)
180 {
181         int rc = 0;
182
183         ctrl_dbg(ctrl, "Change speed to %d\n", speed);
184         rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed);
185         if (rc) {
186                 ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n",
187                          __func__);
188                 return WRONG_BUS_FREQUENCY;
189         }
190         return rc;
191 }
192
193 static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
194                 u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp,
195                 enum pci_bus_speed msp)
196 {
197         int rc = 0;
198
199         /*
200          * If other slots on the same bus are occupied, we cannot
201          * change the bus speed.
202          */
203         if (flag) {
204                 if (asp < bsp) {
205                         ctrl_err(ctrl, "Speed of bus %x and adapter %x mismatch\n",
206                                  bsp, asp);
207                         rc = WRONG_BUS_FREQUENCY;
208                 }
209                 return rc;
210         }
211
212         if (asp < msp) {
213                 if (bsp != asp)
214                         rc = change_bus_speed(ctrl, pslot, asp);
215         } else {
216                 if (bsp != msp)
217                         rc = change_bus_speed(ctrl, pslot, msp);
218         }
219         return rc;
220 }
221
222 /**
223  * board_added - Called after a board has been added to the system.
224  * @p_slot: target &slot
225  *
226  * Turns power on for the board.
227  * Configures board.
228  */
229 static int board_added(struct slot *p_slot)
230 {
231         u8 hp_slot;
232         u8 slots_not_empty = 0;
233         int rc = 0;
234         enum pci_bus_speed asp, bsp, msp;
235         struct controller *ctrl = p_slot->ctrl;
236         struct pci_bus *parent = ctrl->pci_dev->subordinate;
237
238         hp_slot = p_slot->device - ctrl->slot_device_offset;
239
240         ctrl_dbg(ctrl, "%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",
241                  __func__, p_slot->device, ctrl->slot_device_offset, hp_slot);
242
243         /* Power on slot without connecting to bus */
244         rc = p_slot->hpc_ops->power_on_slot(p_slot);
245         if (rc) {
246                 ctrl_err(ctrl, "Failed to power on slot\n");
247                 return -1;
248         }
249
250         if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
251                 rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz);
252                 if (rc) {
253                         ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n",
254                                  __func__);
255                         return WRONG_BUS_FREQUENCY;
256                 }
257
258                 /* turn on board, blink green LED, turn off Amber LED */
259                 rc = p_slot->hpc_ops->slot_enable(p_slot);
260                 if (rc) {
261                         ctrl_err(ctrl, "Issue of Slot Enable command failed\n");
262                         return rc;
263                 }
264         }
265
266         rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp);
267         if (rc) {
268                 ctrl_err(ctrl, "Can't get adapter speed or bus mode mismatch\n");
269                 return WRONG_BUS_FREQUENCY;
270         }
271
272         bsp = ctrl->pci_dev->subordinate->cur_bus_speed;
273         msp = ctrl->pci_dev->subordinate->max_bus_speed;
274
275         /* Check if there are other slots or devices on the same bus */
276         if (!list_empty(&ctrl->pci_dev->subordinate->devices))
277                 slots_not_empty = 1;
278
279         ctrl_dbg(ctrl, "%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, max_bus_speed %d\n",
280                  __func__, slots_not_empty, asp,
281                  bsp, msp);
282
283         rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp);
284         if (rc)
285                 return rc;
286
287         /* turn on board, blink green LED, turn off Amber LED */
288         rc = p_slot->hpc_ops->slot_enable(p_slot);
289         if (rc) {
290                 ctrl_err(ctrl, "Issue of Slot Enable command failed\n");
291                 return rc;
292         }
293
294         /* Wait for ~1 second */
295         msleep(1000);
296
297         ctrl_dbg(ctrl, "%s: slot status = %x\n", __func__, p_slot->status);
298         /* Check for a power fault */
299         if (p_slot->status == 0xFF) {
300                 /* power fault occurred, but it was benign */
301                 ctrl_dbg(ctrl, "%s: Power fault\n", __func__);
302                 rc = POWER_FAILURE;
303                 p_slot->status = 0;
304                 goto err_exit;
305         }
306
307         if (shpchp_configure_device(p_slot)) {
308                 ctrl_err(ctrl, "Cannot add device at %04x:%02x:%02x\n",
309                          pci_domain_nr(parent), p_slot->bus, p_slot->device);
310                 goto err_exit;
311         }
312
313         p_slot->status = 0;
314         p_slot->is_a_board = 0x01;
315         p_slot->pwr_save = 1;
316
317         p_slot->hpc_ops->green_led_on(p_slot);
318
319         return 0;
320
321 err_exit:
322         /* turn off slot, turn on Amber LED, turn off Green LED */
323         rc = p_slot->hpc_ops->slot_disable(p_slot);
324         if (rc) {
325                 ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n",
326                          __func__);
327                 return rc;
328         }
329
330         return(rc);
331 }
332
333
334 /**
335  * remove_board - Turns off slot and LEDs
336  * @p_slot: target &slot
337  */
338 static int remove_board(struct slot *p_slot)
339 {
340         struct controller *ctrl = p_slot->ctrl;
341         u8 hp_slot;
342         int rc;
343
344         if (shpchp_unconfigure_device(p_slot))
345                 return(1);
346
347         hp_slot = p_slot->device - ctrl->slot_device_offset;
348         p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
349
350         ctrl_dbg(ctrl, "%s: hp_slot = %d\n", __func__, hp_slot);
351
352         /* Change status to shutdown */
353         if (p_slot->is_a_board)
354                 p_slot->status = 0x01;
355
356         /* turn off slot, turn on Amber LED, turn off Green LED */
357         rc = p_slot->hpc_ops->slot_disable(p_slot);
358         if (rc) {
359                 ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n",
360                          __func__);
361                 return rc;
362         }
363
364         rc = p_slot->hpc_ops->set_attention_status(p_slot, 0);
365         if (rc) {
366                 ctrl_err(ctrl, "Issue of Set Attention command failed\n");
367                 return rc;
368         }
369
370         p_slot->pwr_save = 0;
371         p_slot->is_a_board = 0;
372
373         return 0;
374 }
375
376
377 struct pushbutton_work_info {
378         struct slot *p_slot;
379         struct work_struct work;
380 };
381
382 /**
383  * shpchp_pushbutton_thread - handle pushbutton events
384  * @work: &struct work_struct to be handled
385  *
386  * Scheduled procedure to handle blocking stuff for the pushbuttons.
387  * Handles all pending events and exits.
388  */
389 static void shpchp_pushbutton_thread(struct work_struct *work)
390 {
391         struct pushbutton_work_info *info =
392                 container_of(work, struct pushbutton_work_info, work);
393         struct slot *p_slot = info->p_slot;
394
395         mutex_lock(&p_slot->lock);
396         switch (p_slot->state) {
397         case POWEROFF_STATE:
398                 mutex_unlock(&p_slot->lock);
399                 shpchp_disable_slot(p_slot);
400                 mutex_lock(&p_slot->lock);
401                 p_slot->state = STATIC_STATE;
402                 break;
403         case POWERON_STATE:
404                 mutex_unlock(&p_slot->lock);
405                 if (shpchp_enable_slot(p_slot))
406                         p_slot->hpc_ops->green_led_off(p_slot);
407                 mutex_lock(&p_slot->lock);
408                 p_slot->state = STATIC_STATE;
409                 break;
410         default:
411                 break;
412         }
413         mutex_unlock(&p_slot->lock);
414
415         kfree(info);
416 }
417
418 void shpchp_queue_pushbutton_work(struct work_struct *work)
419 {
420         struct slot *p_slot = container_of(work, struct slot, work.work);
421         struct pushbutton_work_info *info;
422
423         info = kmalloc(sizeof(*info), GFP_KERNEL);
424         if (!info) {
425                 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
426                          __func__);
427                 return;
428         }
429         info->p_slot = p_slot;
430         INIT_WORK(&info->work, shpchp_pushbutton_thread);
431
432         mutex_lock(&p_slot->lock);
433         switch (p_slot->state) {
434         case BLINKINGOFF_STATE:
435                 p_slot->state = POWEROFF_STATE;
436                 break;
437         case BLINKINGON_STATE:
438                 p_slot->state = POWERON_STATE;
439                 break;
440         default:
441                 kfree(info);
442                 goto out;
443         }
444         queue_work(p_slot->wq, &info->work);
445  out:
446         mutex_unlock(&p_slot->lock);
447 }
448
449 static int update_slot_info (struct slot *slot)
450 {
451         struct hotplug_slot_info *info;
452         int result;
453
454         info = kmalloc(sizeof(*info), GFP_KERNEL);
455         if (!info)
456                 return -ENOMEM;
457
458         slot->hpc_ops->get_power_status(slot, &(info->power_status));
459         slot->hpc_ops->get_attention_status(slot, &(info->attention_status));
460         slot->hpc_ops->get_latch_status(slot, &(info->latch_status));
461         slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status));
462
463         result = pci_hp_change_slot_info(slot->hotplug_slot, info);
464         kfree (info);
465         return result;
466 }
467
468 /*
469  * Note: This function must be called with slot->lock held
470  */
471 static void handle_button_press_event(struct slot *p_slot)
472 {
473         u8 getstatus;
474         struct controller *ctrl = p_slot->ctrl;
475
476         switch (p_slot->state) {
477         case STATIC_STATE:
478                 p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
479                 if (getstatus) {
480                         p_slot->state = BLINKINGOFF_STATE;
481                         ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n",
482                                   slot_name(p_slot));
483                 } else {
484                         p_slot->state = BLINKINGON_STATE;
485                         ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n",
486                                   slot_name(p_slot));
487                 }
488                 /* blink green LED and turn off amber */
489                 p_slot->hpc_ops->green_led_blink(p_slot);
490                 p_slot->hpc_ops->set_attention_status(p_slot, 0);
491
492                 queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
493                 break;
494         case BLINKINGOFF_STATE:
495         case BLINKINGON_STATE:
496                 /*
497                  * Cancel if we are still blinking; this means that we
498                  * press the attention again before the 5 sec. limit
499                  * expires to cancel hot-add or hot-remove
500                  */
501                 ctrl_info(ctrl, "Button cancel on Slot(%s)\n",
502                           slot_name(p_slot));
503                 cancel_delayed_work(&p_slot->work);
504                 if (p_slot->state == BLINKINGOFF_STATE)
505                         p_slot->hpc_ops->green_led_on(p_slot);
506                 else
507                         p_slot->hpc_ops->green_led_off(p_slot);
508                 p_slot->hpc_ops->set_attention_status(p_slot, 0);
509                 ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n",
510                           slot_name(p_slot));
511                 p_slot->state = STATIC_STATE;
512                 break;
513         case POWEROFF_STATE:
514         case POWERON_STATE:
515                 /*
516                  * Ignore if the slot is on power-on or power-off state;
517                  * this means that the previous attention button action
518                  * to hot-add or hot-remove is undergoing
519                  */
520                 ctrl_info(ctrl, "Button ignore on Slot(%s)\n",
521                           slot_name(p_slot));
522                 update_slot_info(p_slot);
523                 break;
524         default:
525                 ctrl_warn(ctrl, "Not a valid state\n");
526                 break;
527         }
528 }
529
530 static void interrupt_event_handler(struct work_struct *work)
531 {
532         struct event_info *info = container_of(work, struct event_info, work);
533         struct slot *p_slot = info->p_slot;
534
535         mutex_lock(&p_slot->lock);
536         switch (info->event_type) {
537         case INT_BUTTON_PRESS:
538                 handle_button_press_event(p_slot);
539                 break;
540         case INT_POWER_FAULT:
541                 ctrl_dbg(p_slot->ctrl, "%s: Power fault\n", __func__);
542                 p_slot->hpc_ops->set_attention_status(p_slot, 1);
543                 p_slot->hpc_ops->green_led_off(p_slot);
544                 break;
545         default:
546                 update_slot_info(p_slot);
547                 break;
548         }
549         mutex_unlock(&p_slot->lock);
550
551         kfree(info);
552 }
553
554
555 static int shpchp_enable_slot (struct slot *p_slot)
556 {
557         u8 getstatus = 0;
558         int rc, retval = -ENODEV;
559         struct controller *ctrl = p_slot->ctrl;
560
561         /* Check to see if (latch closed, card present, power off) */
562         mutex_lock(&p_slot->ctrl->crit_sect);
563         rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
564         if (rc || !getstatus) {
565                 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
566                 goto out;
567         }
568         rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
569         if (rc || getstatus) {
570                 ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot));
571                 goto out;
572         }
573         rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
574         if (rc || getstatus) {
575                 ctrl_info(ctrl, "Already enabled on slot(%s)\n",
576                           slot_name(p_slot));
577                 goto out;
578         }
579
580         p_slot->is_a_board = 1;
581
582         /* We have to save the presence info for these slots */
583         p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
584         p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save));
585         ctrl_dbg(ctrl, "%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save);
586         p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
587
588         if ((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD &&
589              p_slot->ctrl->pci_dev->device == PCI_DEVICE_ID_AMD_POGO_7458)
590              && p_slot->ctrl->num_slots == 1) {
591                 /* handle AMD POGO errata; this must be done before enable  */
592                 amd_pogo_errata_save_misc_reg(p_slot);
593                 retval = board_added(p_slot);
594                 /* handle AMD POGO errata; this must be done after enable  */
595                 amd_pogo_errata_restore_misc_reg(p_slot);
596         } else
597                 retval = board_added(p_slot);
598
599         if (retval) {
600                 p_slot->hpc_ops->get_adapter_status(p_slot,
601                                 &(p_slot->presence_save));
602                 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
603         }
604
605         update_slot_info(p_slot);
606  out:
607         mutex_unlock(&p_slot->ctrl->crit_sect);
608         return retval;
609 }
610
611
612 static int shpchp_disable_slot (struct slot *p_slot)
613 {
614         u8 getstatus = 0;
615         int rc, retval = -ENODEV;
616         struct controller *ctrl = p_slot->ctrl;
617
618         if (!p_slot->ctrl)
619                 return -ENODEV;
620
621         /* Check to see if (latch closed, card present, power on) */
622         mutex_lock(&p_slot->ctrl->crit_sect);
623
624         rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
625         if (rc || !getstatus) {
626                 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
627                 goto out;
628         }
629         rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
630         if (rc || getstatus) {
631                 ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot));
632                 goto out;
633         }
634         rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
635         if (rc || !getstatus) {
636                 ctrl_info(ctrl, "Already disabled on slot(%s)\n",
637                           slot_name(p_slot));
638                 goto out;
639         }
640
641         retval = remove_board(p_slot);
642         update_slot_info(p_slot);
643  out:
644         mutex_unlock(&p_slot->ctrl->crit_sect);
645         return retval;
646 }
647
648 int shpchp_sysfs_enable_slot(struct slot *p_slot)
649 {
650         int retval = -ENODEV;
651         struct controller *ctrl = p_slot->ctrl;
652
653         mutex_lock(&p_slot->lock);
654         switch (p_slot->state) {
655         case BLINKINGON_STATE:
656                 cancel_delayed_work(&p_slot->work);
657                 /* fall through */
658         case STATIC_STATE:
659                 p_slot->state = POWERON_STATE;
660                 mutex_unlock(&p_slot->lock);
661                 retval = shpchp_enable_slot(p_slot);
662                 mutex_lock(&p_slot->lock);
663                 p_slot->state = STATIC_STATE;
664                 break;
665         case POWERON_STATE:
666                 ctrl_info(ctrl, "Slot %s is already in powering on state\n",
667                           slot_name(p_slot));
668                 break;
669         case BLINKINGOFF_STATE:
670         case POWEROFF_STATE:
671                 ctrl_info(ctrl, "Already enabled on slot %s\n",
672                           slot_name(p_slot));
673                 break;
674         default:
675                 ctrl_err(ctrl, "Not a valid state on slot %s\n",
676                          slot_name(p_slot));
677                 break;
678         }
679         mutex_unlock(&p_slot->lock);
680
681         return retval;
682 }
683
684 int shpchp_sysfs_disable_slot(struct slot *p_slot)
685 {
686         int retval = -ENODEV;
687         struct controller *ctrl = p_slot->ctrl;
688
689         mutex_lock(&p_slot->lock);
690         switch (p_slot->state) {
691         case BLINKINGOFF_STATE:
692                 cancel_delayed_work(&p_slot->work);
693                 /* fall through */
694         case STATIC_STATE:
695                 p_slot->state = POWEROFF_STATE;
696                 mutex_unlock(&p_slot->lock);
697                 retval = shpchp_disable_slot(p_slot);
698                 mutex_lock(&p_slot->lock);
699                 p_slot->state = STATIC_STATE;
700                 break;
701         case POWEROFF_STATE:
702                 ctrl_info(ctrl, "Slot %s is already in powering off state\n",
703                           slot_name(p_slot));
704                 break;
705         case BLINKINGON_STATE:
706         case POWERON_STATE:
707                 ctrl_info(ctrl, "Already disabled on slot %s\n",
708                           slot_name(p_slot));
709                 break;
710         default:
711                 ctrl_err(ctrl, "Not a valid state on slot %s\n",
712                          slot_name(p_slot));
713                 break;
714         }
715         mutex_unlock(&p_slot->lock);
716
717         return retval;
718 }