SUNRPC: Ensure we return EAGAIN in xs_nospace if congestion is cleared
[pandora-kernel.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/slab.h>
34 #include <linux/pci.h>
35 #include "../pci.h"
36 #include "pciehp.h"
37
38 static void interrupt_event_handler(struct work_struct *work);
39
40 static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
41 {
42         struct event_info *info;
43
44         info = kmalloc(sizeof(*info), GFP_ATOMIC);
45         if (!info)
46                 return -ENOMEM;
47
48         info->event_type = event_type;
49         info->p_slot = p_slot;
50         INIT_WORK(&info->work, interrupt_event_handler);
51
52         queue_work(pciehp_wq, &info->work);
53
54         return 0;
55 }
56
57 u8 pciehp_handle_attention_button(struct slot *p_slot)
58 {
59         u32 event_type;
60         struct controller *ctrl = p_slot->ctrl;
61
62         /* Attention Button Change */
63         ctrl_dbg(ctrl, "Attention button interrupt received\n");
64
65         /*
66          *  Button pressed - See if need to TAKE ACTION!!!
67          */
68         ctrl_info(ctrl, "Button pressed on Slot(%s)\n", slot_name(p_slot));
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         struct controller *ctrl = p_slot->ctrl;
81
82         /* Switch Change */
83         ctrl_dbg(ctrl, "Switch interrupt received\n");
84
85         pciehp_get_latch_status(p_slot, &getstatus);
86         if (getstatus) {
87                 /*
88                  * Switch opened
89                  */
90                 ctrl_info(ctrl, "Latch open on Slot(%s)\n", slot_name(p_slot));
91                 event_type = INT_SWITCH_OPEN;
92         } else {
93                 /*
94                  *  Switch closed
95                  */
96                 ctrl_info(ctrl, "Latch close on Slot(%s)\n", slot_name(p_slot));
97                 event_type = INT_SWITCH_CLOSE;
98         }
99
100         queue_interrupt_event(p_slot, event_type);
101
102         return 1;
103 }
104
105 u8 pciehp_handle_presence_change(struct slot *p_slot)
106 {
107         u32 event_type;
108         u8 presence_save;
109         struct controller *ctrl = p_slot->ctrl;
110
111         /* Presence Change */
112         ctrl_dbg(ctrl, "Presence/Notify input change\n");
113
114         /* Switch is open, assume a presence change
115          * Save the presence state
116          */
117         pciehp_get_adapter_status(p_slot, &presence_save);
118         if (presence_save) {
119                 /*
120                  * Card Present
121                  */
122                 ctrl_info(ctrl, "Card present on Slot(%s)\n", slot_name(p_slot));
123                 event_type = INT_PRESENCE_ON;
124         } else {
125                 /*
126                  * Not Present
127                  */
128                 ctrl_info(ctrl, "Card not present on Slot(%s)\n",
129                           slot_name(p_slot));
130                 event_type = INT_PRESENCE_OFF;
131         }
132
133         queue_interrupt_event(p_slot, event_type);
134
135         return 1;
136 }
137
138 u8 pciehp_handle_power_fault(struct slot *p_slot)
139 {
140         u32 event_type;
141         struct controller *ctrl = p_slot->ctrl;
142
143         /* power fault */
144         ctrl_dbg(ctrl, "Power fault interrupt received\n");
145         ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
146         event_type = INT_POWER_FAULT;
147         ctrl_info(ctrl, "Power fault bit %x set\n", 0);
148         queue_interrupt_event(p_slot, event_type);
149
150         return 1;
151 }
152
153 /* The following routines constitute the bulk of the
154    hotplug controller logic
155  */
156
157 static void set_slot_off(struct controller *ctrl, struct slot * pslot)
158 {
159         /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
160         if (POWER_CTRL(ctrl)) {
161                 if (pciehp_power_off_slot(pslot)) {
162                         ctrl_err(ctrl,
163                                  "Issue of Slot Power Off command failed\n");
164                         return;
165                 }
166                 /*
167                  * After turning power off, we must wait for at least 1 second
168                  * before taking any action that relies on power having been
169                  * removed from the slot/adapter.
170                  */
171                 msleep(1000);
172         }
173
174         if (PWR_LED(ctrl))
175                 pciehp_green_led_off(pslot);
176
177         if (ATTN_LED(ctrl)) {
178                 if (pciehp_set_attention_status(pslot, 1)) {
179                         ctrl_err(ctrl,
180                                  "Issue of Set Attention Led command failed\n");
181                         return;
182                 }
183         }
184 }
185
186 /**
187  * board_added - Called after a board has been added to the system.
188  * @p_slot: &slot where board is added
189  *
190  * Turns power on for the board.
191  * Configures board.
192  */
193 static int board_added(struct slot *p_slot)
194 {
195         int retval = 0;
196         struct controller *ctrl = p_slot->ctrl;
197         struct pci_bus *parent = ctrl->pcie->port->subordinate;
198
199         if (POWER_CTRL(ctrl)) {
200                 /* Power on slot */
201                 retval = pciehp_power_on_slot(p_slot);
202                 if (retval)
203                         return retval;
204         }
205
206         if (PWR_LED(ctrl))
207                 pciehp_green_led_blink(p_slot);
208
209         /* Check link training status */
210         retval = pciehp_check_link_status(ctrl);
211         if (retval) {
212                 ctrl_err(ctrl, "Failed to check link status\n");
213                 goto err_exit;
214         }
215
216         /* Wait for 1 second after checking link training status */
217         msleep(1000);
218
219         /* Check for a power fault */
220         if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
221                 ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
222                 retval = -EIO;
223                 goto err_exit;
224         }
225
226         retval = pciehp_configure_device(p_slot);
227         if (retval) {
228                 ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
229                          pci_domain_nr(parent), parent->number);
230                 goto err_exit;
231         }
232
233         if (PWR_LED(ctrl))
234                 pciehp_green_led_on(p_slot);
235
236         return 0;
237
238 err_exit:
239         set_slot_off(ctrl, p_slot);
240         return retval;
241 }
242
243 /**
244  * remove_board - Turns off slot and LEDs
245  * @p_slot: slot where board is being removed
246  */
247 static int remove_board(struct slot *p_slot)
248 {
249         int retval = 0;
250         struct controller *ctrl = p_slot->ctrl;
251
252         retval = pciehp_unconfigure_device(p_slot);
253         if (retval)
254                 return retval;
255
256         if (POWER_CTRL(ctrl)) {
257                 /* power off slot */
258                 retval = pciehp_power_off_slot(p_slot);
259                 if (retval) {
260                         ctrl_err(ctrl,
261                                  "Issue of Slot Disable command failed\n");
262                         return retval;
263                 }
264                 /*
265                  * After turning power off, we must wait for at least 1 second
266                  * before taking any action that relies on power having been
267                  * removed from the slot/adapter.
268                  */
269                 msleep(1000);
270         }
271
272         /* turn off Green LED */
273         if (PWR_LED(ctrl))
274                 pciehp_green_led_off(p_slot);
275
276         return 0;
277 }
278
279 struct power_work_info {
280         struct slot *p_slot;
281         struct work_struct work;
282 };
283
284 /**
285  * pciehp_power_thread - handle pushbutton events
286  * @work: &struct work_struct describing work to be done
287  *
288  * Scheduled procedure to handle blocking stuff for the pushbuttons.
289  * Handles all pending events and exits.
290  */
291 static void pciehp_power_thread(struct work_struct *work)
292 {
293         struct power_work_info *info =
294                 container_of(work, struct power_work_info, work);
295         struct slot *p_slot = info->p_slot;
296
297         mutex_lock(&p_slot->lock);
298         switch (p_slot->state) {
299         case POWEROFF_STATE:
300                 mutex_unlock(&p_slot->lock);
301                 ctrl_dbg(p_slot->ctrl,
302                          "Disabling domain:bus:device=%04x:%02x:00\n",
303                          pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),
304                          p_slot->ctrl->pcie->port->subordinate->number);
305                 pciehp_disable_slot(p_slot);
306                 mutex_lock(&p_slot->lock);
307                 p_slot->state = STATIC_STATE;
308                 break;
309         case POWERON_STATE:
310                 mutex_unlock(&p_slot->lock);
311                 if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl))
312                         pciehp_green_led_off(p_slot);
313                 mutex_lock(&p_slot->lock);
314                 p_slot->state = STATIC_STATE;
315                 break;
316         default:
317                 break;
318         }
319         mutex_unlock(&p_slot->lock);
320
321         kfree(info);
322 }
323
324 void pciehp_queue_pushbutton_work(struct work_struct *work)
325 {
326         struct slot *p_slot = container_of(work, struct slot, work.work);
327         struct power_work_info *info;
328
329         info = kmalloc(sizeof(*info), GFP_KERNEL);
330         if (!info) {
331                 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
332                          __func__);
333                 return;
334         }
335         info->p_slot = p_slot;
336         INIT_WORK(&info->work, pciehp_power_thread);
337
338         mutex_lock(&p_slot->lock);
339         switch (p_slot->state) {
340         case BLINKINGOFF_STATE:
341                 p_slot->state = POWEROFF_STATE;
342                 break;
343         case BLINKINGON_STATE:
344                 p_slot->state = POWERON_STATE;
345                 break;
346         default:
347                 kfree(info);
348                 goto out;
349         }
350         queue_work(pciehp_ordered_wq, &info->work);
351  out:
352         mutex_unlock(&p_slot->lock);
353 }
354
355 /*
356  * Note: This function must be called with slot->lock held
357  */
358 static void handle_button_press_event(struct slot *p_slot)
359 {
360         struct controller *ctrl = p_slot->ctrl;
361         u8 getstatus;
362
363         switch (p_slot->state) {
364         case STATIC_STATE:
365                 pciehp_get_power_status(p_slot, &getstatus);
366                 if (getstatus) {
367                         p_slot->state = BLINKINGOFF_STATE;
368                         ctrl_info(ctrl,
369                                   "PCI slot #%s - powering off due to button "
370                                   "press.\n", slot_name(p_slot));
371                 } else {
372                         p_slot->state = BLINKINGON_STATE;
373                         ctrl_info(ctrl,
374                                   "PCI slot #%s - powering on due to button "
375                                   "press.\n", slot_name(p_slot));
376                 }
377                 /* blink green LED and turn off amber */
378                 if (PWR_LED(ctrl))
379                         pciehp_green_led_blink(p_slot);
380                 if (ATTN_LED(ctrl))
381                         pciehp_set_attention_status(p_slot, 0);
382
383                 queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ);
384                 break;
385         case BLINKINGOFF_STATE:
386         case BLINKINGON_STATE:
387                 /*
388                  * Cancel if we are still blinking; this means that we
389                  * press the attention again before the 5 sec. limit
390                  * expires to cancel hot-add or hot-remove
391                  */
392                 ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot));
393                 cancel_delayed_work(&p_slot->work);
394                 if (p_slot->state == BLINKINGOFF_STATE) {
395                         if (PWR_LED(ctrl))
396                                 pciehp_green_led_on(p_slot);
397                 } else {
398                         if (PWR_LED(ctrl))
399                                 pciehp_green_led_off(p_slot);
400                 }
401                 if (ATTN_LED(ctrl))
402                         pciehp_set_attention_status(p_slot, 0);
403                 ctrl_info(ctrl, "PCI slot #%s - action canceled "
404                           "due to button press\n", slot_name(p_slot));
405                 p_slot->state = STATIC_STATE;
406                 break;
407         case POWEROFF_STATE:
408         case POWERON_STATE:
409                 /*
410                  * Ignore if the slot is on power-on or power-off state;
411                  * this means that the previous attention button action
412                  * to hot-add or hot-remove is undergoing
413                  */
414                 ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot));
415                 break;
416         default:
417                 ctrl_warn(ctrl, "Not a valid state\n");
418                 break;
419         }
420 }
421
422 /*
423  * Note: This function must be called with slot->lock held
424  */
425 static void handle_surprise_event(struct slot *p_slot)
426 {
427         u8 getstatus;
428         struct power_work_info *info;
429
430         info = kmalloc(sizeof(*info), GFP_KERNEL);
431         if (!info) {
432                 ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n",
433                          __func__);
434                 return;
435         }
436         info->p_slot = p_slot;
437         INIT_WORK(&info->work, pciehp_power_thread);
438
439         pciehp_get_adapter_status(p_slot, &getstatus);
440         if (!getstatus)
441                 p_slot->state = POWEROFF_STATE;
442         else
443                 p_slot->state = POWERON_STATE;
444
445         queue_work(pciehp_ordered_wq, &info->work);
446 }
447
448 static void interrupt_event_handler(struct work_struct *work)
449 {
450         struct event_info *info = container_of(work, struct event_info, work);
451         struct slot *p_slot = info->p_slot;
452         struct controller *ctrl = p_slot->ctrl;
453
454         mutex_lock(&p_slot->lock);
455         switch (info->event_type) {
456         case INT_BUTTON_PRESS:
457                 handle_button_press_event(p_slot);
458                 break;
459         case INT_POWER_FAULT:
460                 if (!POWER_CTRL(ctrl))
461                         break;
462                 if (ATTN_LED(ctrl))
463                         pciehp_set_attention_status(p_slot, 1);
464                 if (PWR_LED(ctrl))
465                         pciehp_green_led_off(p_slot);
466                 break;
467         case INT_PRESENCE_ON:
468         case INT_PRESENCE_OFF:
469                 if (!HP_SUPR_RM(ctrl))
470                         break;
471                 ctrl_dbg(ctrl, "Surprise Removal\n");
472                 handle_surprise_event(p_slot);
473                 break;
474         default:
475                 break;
476         }
477         mutex_unlock(&p_slot->lock);
478
479         kfree(info);
480 }
481
482 int pciehp_enable_slot(struct slot *p_slot)
483 {
484         u8 getstatus = 0;
485         int rc;
486         struct controller *ctrl = p_slot->ctrl;
487
488         rc = pciehp_get_adapter_status(p_slot, &getstatus);
489         if (rc || !getstatus) {
490                 ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));
491                 return -ENODEV;
492         }
493         if (MRL_SENS(p_slot->ctrl)) {
494                 rc = pciehp_get_latch_status(p_slot, &getstatus);
495                 if (rc || getstatus) {
496                         ctrl_info(ctrl, "Latch open on slot(%s)\n",
497                                   slot_name(p_slot));
498                         return -ENODEV;
499                 }
500         }
501
502         if (POWER_CTRL(p_slot->ctrl)) {
503                 rc = pciehp_get_power_status(p_slot, &getstatus);
504                 if (rc || getstatus) {
505                         ctrl_info(ctrl, "Already enabled on slot(%s)\n",
506                                   slot_name(p_slot));
507                         return -EINVAL;
508                 }
509         }
510
511         pciehp_get_latch_status(p_slot, &getstatus);
512
513         rc = board_added(p_slot);
514         if (rc) {
515                 pciehp_get_latch_status(p_slot, &getstatus);
516         }
517         return rc;
518 }
519
520
521 int pciehp_disable_slot(struct slot *p_slot)
522 {
523         u8 getstatus = 0;
524         int ret = 0;
525         struct controller *ctrl = p_slot->ctrl;
526
527         if (!p_slot->ctrl)
528                 return 1;
529
530         if (!HP_SUPR_RM(p_slot->ctrl)) {
531                 ret = pciehp_get_adapter_status(p_slot, &getstatus);
532                 if (ret || !getstatus) {
533                         ctrl_info(ctrl, "No adapter on slot(%s)\n",
534                                   slot_name(p_slot));
535                         return -ENODEV;
536                 }
537         }
538
539         if (MRL_SENS(p_slot->ctrl)) {
540                 ret = pciehp_get_latch_status(p_slot, &getstatus);
541                 if (ret || getstatus) {
542                         ctrl_info(ctrl, "Latch open on slot(%s)\n",
543                                   slot_name(p_slot));
544                         return -ENODEV;
545                 }
546         }
547
548         if (POWER_CTRL(p_slot->ctrl)) {
549                 ret = pciehp_get_power_status(p_slot, &getstatus);
550                 if (ret || !getstatus) {
551                         ctrl_info(ctrl, "Already disabled on slot(%s)\n",
552                                   slot_name(p_slot));
553                         return -EINVAL;
554                 }
555         }
556
557         return remove_board(p_slot);
558 }
559
560 int pciehp_sysfs_enable_slot(struct slot *p_slot)
561 {
562         int retval = -ENODEV;
563         struct controller *ctrl = p_slot->ctrl;
564
565         mutex_lock(&p_slot->lock);
566         switch (p_slot->state) {
567         case BLINKINGON_STATE:
568                 cancel_delayed_work(&p_slot->work);
569         case STATIC_STATE:
570                 p_slot->state = POWERON_STATE;
571                 mutex_unlock(&p_slot->lock);
572                 retval = pciehp_enable_slot(p_slot);
573                 mutex_lock(&p_slot->lock);
574                 p_slot->state = STATIC_STATE;
575                 break;
576         case POWERON_STATE:
577                 ctrl_info(ctrl, "Slot %s is already in powering on state\n",
578                           slot_name(p_slot));
579                 break;
580         case BLINKINGOFF_STATE:
581         case POWEROFF_STATE:
582                 ctrl_info(ctrl, "Already enabled on slot %s\n",
583                           slot_name(p_slot));
584                 break;
585         default:
586                 ctrl_err(ctrl, "Not a valid state on slot %s\n",
587                          slot_name(p_slot));
588                 break;
589         }
590         mutex_unlock(&p_slot->lock);
591
592         return retval;
593 }
594
595 int pciehp_sysfs_disable_slot(struct slot *p_slot)
596 {
597         int retval = -ENODEV;
598         struct controller *ctrl = p_slot->ctrl;
599
600         mutex_lock(&p_slot->lock);
601         switch (p_slot->state) {
602         case BLINKINGOFF_STATE:
603                 cancel_delayed_work(&p_slot->work);
604         case STATIC_STATE:
605                 p_slot->state = POWEROFF_STATE;
606                 mutex_unlock(&p_slot->lock);
607                 retval = pciehp_disable_slot(p_slot);
608                 mutex_lock(&p_slot->lock);
609                 p_slot->state = STATIC_STATE;
610                 break;
611         case POWEROFF_STATE:
612                 ctrl_info(ctrl, "Slot %s is already in powering off state\n",
613                           slot_name(p_slot));
614                 break;
615         case BLINKINGON_STATE:
616         case POWERON_STATE:
617                 ctrl_info(ctrl, "Already disabled on slot %s\n",
618                           slot_name(p_slot));
619                 break;
620         default:
621                 ctrl_err(ctrl, "Not a valid state on slot %s\n",
622                          slot_name(p_slot));
623                 break;
624         }
625         mutex_unlock(&p_slot->lock);
626
627         return retval;
628 }