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