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