treewide: Use fallthrough pseudo-keyword
[linux-block.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         shpchp_unconfigure_device(p_slot);
345
346         hp_slot = p_slot->device - ctrl->slot_device_offset;
347         p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
348
349         ctrl_dbg(ctrl, "%s: hp_slot = %d\n", __func__, hp_slot);
350
351         /* Change status to shutdown */
352         if (p_slot->is_a_board)
353                 p_slot->status = 0x01;
354
355         /* turn off slot, turn on Amber LED, turn off Green LED */
356         rc = p_slot->hpc_ops->slot_disable(p_slot);
357         if (rc) {
358                 ctrl_err(ctrl, "%s: Issue of Slot Disable command failed\n",
359                          __func__);
360                 return rc;
361         }
362
363         rc = p_slot->hpc_ops->set_attention_status(p_slot, 0);
364         if (rc) {
365                 ctrl_err(ctrl, "Issue of Set Attention command failed\n");
366                 return rc;
367         }
368
369         p_slot->pwr_save = 0;
370         p_slot->is_a_board = 0;
371
372         return 0;
373 }
374
375
376 struct pushbutton_work_info {
377         struct slot *p_slot;
378         struct work_struct work;
379 };
380
381 /**
382  * shpchp_pushbutton_thread - handle pushbutton events
383  * @work: &struct work_struct to be handled
384  *
385  * Scheduled procedure to handle blocking stuff for the pushbuttons.
386  * Handles all pending events and exits.
387  */
388 static void shpchp_pushbutton_thread(struct work_struct *work)
389 {
390         struct pushbutton_work_info *info =
391                 container_of(work, struct pushbutton_work_info, work);
392         struct slot *p_slot = info->p_slot;
393
394         mutex_lock(&p_slot->lock);
395         switch (p_slot->state) {
396         case POWEROFF_STATE:
397                 mutex_unlock(&p_slot->lock);
398                 shpchp_disable_slot(p_slot);
399                 mutex_lock(&p_slot->lock);
400                 p_slot->state = STATIC_STATE;
401                 break;
402         case POWERON_STATE:
403                 mutex_unlock(&p_slot->lock);
404                 if (shpchp_enable_slot(p_slot))
405                         p_slot->hpc_ops->green_led_off(p_slot);
406                 mutex_lock(&p_slot->lock);
407                 p_slot->state = STATIC_STATE;
408                 break;
409         default:
410                 break;
411         }
412         mutex_unlock(&p_slot->lock);
413
414         kfree(info);
415 }
416
417 void shpchp_queue_pushbutton_work(struct work_struct *work)
418 {
419         struct slot *p_slot = container_of(work, struct slot, work.work);
420         struct pushbutton_work_info *info;
421
422         info = kmalloc(sizeof(*info), GFP_KERNEL);
423         if (!info) {
424                 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
425                          __func__);
426                 return;
427         }
428         info->p_slot = p_slot;
429         INIT_WORK(&info->work, shpchp_pushbutton_thread);
430
431         mutex_lock(&p_slot->lock);
432         switch (p_slot->state) {
433         case BLINKINGOFF_STATE:
434                 p_slot->state = POWEROFF_STATE;
435                 break;
436         case BLINKINGON_STATE:
437                 p_slot->state = POWERON_STATE;
438                 break;
439         default:
440                 kfree(info);
441                 goto out;
442         }
443         queue_work(p_slot->wq, &info->work);
444  out:
445         mutex_unlock(&p_slot->lock);
446 }
447
448 static void update_slot_info(struct slot *slot)
449 {
450         slot->hpc_ops->get_power_status(slot, &slot->pwr_save);
451         slot->hpc_ops->get_attention_status(slot, &slot->attention_save);
452         slot->hpc_ops->get_latch_status(slot, &slot->latch_save);
453         slot->hpc_ops->get_adapter_status(slot, &slot->presence_save);
454 }
455
456 /*
457  * Note: This function must be called with slot->lock held
458  */
459 static void handle_button_press_event(struct slot *p_slot)
460 {
461         u8 getstatus;
462         struct controller *ctrl = p_slot->ctrl;
463
464         switch (p_slot->state) {
465         case STATIC_STATE:
466                 p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
467                 if (getstatus) {
468                         p_slot->state = BLINKINGOFF_STATE;
469                         ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n",
470                                   slot_name(p_slot));
471                 } else {
472                         p_slot->state = BLINKINGON_STATE;
473                         ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n",
474                                   slot_name(p_slot));
475                 }
476                 /* blink green LED and turn off amber */
477                 p_slot->hpc_ops->green_led_blink(p_slot);
478                 p_slot->hpc_ops->set_attention_status(p_slot, 0);
479
480                 queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
481                 break;
482         case BLINKINGOFF_STATE:
483         case BLINKINGON_STATE:
484                 /*
485                  * Cancel if we are still blinking; this means that we
486                  * press the attention again before the 5 sec. limit
487                  * expires to cancel hot-add or hot-remove
488                  */
489                 ctrl_info(ctrl, "Button cancel on Slot(%s)\n",
490                           slot_name(p_slot));
491                 cancel_delayed_work(&p_slot->work);
492                 if (p_slot->state == BLINKINGOFF_STATE)
493                         p_slot->hpc_ops->green_led_on(p_slot);
494                 else
495                         p_slot->hpc_ops->green_led_off(p_slot);
496                 p_slot->hpc_ops->set_attention_status(p_slot, 0);
497                 ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n",
498                           slot_name(p_slot));
499                 p_slot->state = STATIC_STATE;
500                 break;
501         case POWEROFF_STATE:
502         case POWERON_STATE:
503                 /*
504                  * Ignore if the slot is on power-on or power-off state;
505                  * this means that the previous attention button action
506                  * to hot-add or hot-remove is undergoing
507                  */
508                 ctrl_info(ctrl, "Button ignore on Slot(%s)\n",
509                           slot_name(p_slot));
510                 update_slot_info(p_slot);
511                 break;
512         default:
513                 ctrl_warn(ctrl, "Not a valid state\n");
514                 break;
515         }
516 }
517
518 static void interrupt_event_handler(struct work_struct *work)
519 {
520         struct event_info *info = container_of(work, struct event_info, work);
521         struct slot *p_slot = info->p_slot;
522
523         mutex_lock(&p_slot->lock);
524         switch (info->event_type) {
525         case INT_BUTTON_PRESS:
526                 handle_button_press_event(p_slot);
527                 break;
528         case INT_POWER_FAULT:
529                 ctrl_dbg(p_slot->ctrl, "%s: Power fault\n", __func__);
530                 p_slot->hpc_ops->set_attention_status(p_slot, 1);
531                 p_slot->hpc_ops->green_led_off(p_slot);
532                 break;
533         default:
534                 update_slot_info(p_slot);
535                 break;
536         }
537         mutex_unlock(&p_slot->lock);
538
539         kfree(info);
540 }
541
542
543 static int shpchp_enable_slot (struct slot *p_slot)
544 {
545         u8 getstatus = 0;
546         int rc, retval = -ENODEV;
547         struct controller *ctrl = p_slot->ctrl;
548
549         /* Check to see if (latch closed, card present, power off) */
550         mutex_lock(&p_slot->ctrl->crit_sect);
551         rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
552         if (rc || !getstatus) {
553                 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
554                 goto out;
555         }
556         rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
557         if (rc || getstatus) {
558                 ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot));
559                 goto out;
560         }
561         rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
562         if (rc || getstatus) {
563                 ctrl_info(ctrl, "Already enabled on slot(%s)\n",
564                           slot_name(p_slot));
565                 goto out;
566         }
567
568         p_slot->is_a_board = 1;
569
570         /* We have to save the presence info for these slots */
571         p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));
572         p_slot->hpc_ops->get_power_status(p_slot, &(p_slot->pwr_save));
573         ctrl_dbg(ctrl, "%s: p_slot->pwr_save %x\n", __func__, p_slot->pwr_save);
574         p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
575
576         if ((p_slot->ctrl->pci_dev->vendor == PCI_VENDOR_ID_AMD &&
577              p_slot->ctrl->pci_dev->device == PCI_DEVICE_ID_AMD_POGO_7458)
578              && p_slot->ctrl->num_slots == 1) {
579                 /* handle AMD POGO errata; this must be done before enable  */
580                 amd_pogo_errata_save_misc_reg(p_slot);
581                 retval = board_added(p_slot);
582                 /* handle AMD POGO errata; this must be done after enable  */
583                 amd_pogo_errata_restore_misc_reg(p_slot);
584         } else
585                 retval = board_added(p_slot);
586
587         if (retval) {
588                 p_slot->hpc_ops->get_adapter_status(p_slot,
589                                 &(p_slot->presence_save));
590                 p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
591         }
592
593         update_slot_info(p_slot);
594  out:
595         mutex_unlock(&p_slot->ctrl->crit_sect);
596         return retval;
597 }
598
599
600 static int shpchp_disable_slot (struct slot *p_slot)
601 {
602         u8 getstatus = 0;
603         int rc, retval = -ENODEV;
604         struct controller *ctrl = p_slot->ctrl;
605
606         if (!p_slot->ctrl)
607                 return -ENODEV;
608
609         /* Check to see if (latch closed, card present, power on) */
610         mutex_lock(&p_slot->ctrl->crit_sect);
611
612         rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
613         if (rc || !getstatus) {
614                 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
615                 goto out;
616         }
617         rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
618         if (rc || getstatus) {
619                 ctrl_info(ctrl, "Latch open on slot(%s)\n", slot_name(p_slot));
620                 goto out;
621         }
622         rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
623         if (rc || !getstatus) {
624                 ctrl_info(ctrl, "Already disabled on slot(%s)\n",
625                           slot_name(p_slot));
626                 goto out;
627         }
628
629         retval = remove_board(p_slot);
630         update_slot_info(p_slot);
631  out:
632         mutex_unlock(&p_slot->ctrl->crit_sect);
633         return retval;
634 }
635
636 int shpchp_sysfs_enable_slot(struct slot *p_slot)
637 {
638         int retval = -ENODEV;
639         struct controller *ctrl = p_slot->ctrl;
640
641         mutex_lock(&p_slot->lock);
642         switch (p_slot->state) {
643         case BLINKINGON_STATE:
644                 cancel_delayed_work(&p_slot->work);
645                 fallthrough;
646         case STATIC_STATE:
647                 p_slot->state = POWERON_STATE;
648                 mutex_unlock(&p_slot->lock);
649                 retval = shpchp_enable_slot(p_slot);
650                 mutex_lock(&p_slot->lock);
651                 p_slot->state = STATIC_STATE;
652                 break;
653         case POWERON_STATE:
654                 ctrl_info(ctrl, "Slot %s is already in powering on state\n",
655                           slot_name(p_slot));
656                 break;
657         case BLINKINGOFF_STATE:
658         case POWEROFF_STATE:
659                 ctrl_info(ctrl, "Already enabled on slot %s\n",
660                           slot_name(p_slot));
661                 break;
662         default:
663                 ctrl_err(ctrl, "Not a valid state on slot %s\n",
664                          slot_name(p_slot));
665                 break;
666         }
667         mutex_unlock(&p_slot->lock);
668
669         return retval;
670 }
671
672 int shpchp_sysfs_disable_slot(struct slot *p_slot)
673 {
674         int retval = -ENODEV;
675         struct controller *ctrl = p_slot->ctrl;
676
677         mutex_lock(&p_slot->lock);
678         switch (p_slot->state) {
679         case BLINKINGOFF_STATE:
680                 cancel_delayed_work(&p_slot->work);
681                 fallthrough;
682         case STATIC_STATE:
683                 p_slot->state = POWEROFF_STATE;
684                 mutex_unlock(&p_slot->lock);
685                 retval = shpchp_disable_slot(p_slot);
686                 mutex_lock(&p_slot->lock);
687                 p_slot->state = STATIC_STATE;
688                 break;
689         case POWEROFF_STATE:
690                 ctrl_info(ctrl, "Slot %s is already in powering off state\n",
691                           slot_name(p_slot));
692                 break;
693         case BLINKINGON_STATE:
694         case POWERON_STATE:
695                 ctrl_info(ctrl, "Already disabled on slot %s\n",
696                           slot_name(p_slot));
697                 break;
698         default:
699                 ctrl_err(ctrl, "Not a valid state on slot %s\n",
700                          slot_name(p_slot));
701                 break;
702         }
703         mutex_unlock(&p_slot->lock);
704
705         return retval;
706 }