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