Merge branch 'for-2.6.31' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[pandora-kernel.git] / drivers / pci / hotplug / cpci_hotplug_core.c
1 /*
2  * CompactPCI Hot Plug Driver
3  *
4  * Copyright (C) 2002,2005 SOMA Networks, Inc.
5  * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6  * Copyright (C) 2001 IBM Corp.
7  *
8  * All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or (at
13  * your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
18  * NON INFRINGEMENT.  See the GNU General Public License for more
19  * details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  * Send feedback to <scottm@somanetworks.com>
26  */
27
28 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/slab.h>
31 #include <linux/pci.h>
32 #include <linux/pci_hotplug.h>
33 #include <linux/init.h>
34 #include <linux/interrupt.h>
35 #include <linux/smp_lock.h>
36 #include <asm/atomic.h>
37 #include <linux/delay.h>
38 #include <linux/kthread.h>
39 #include "cpci_hotplug.h"
40
41 #define DRIVER_AUTHOR   "Scott Murray <scottm@somanetworks.com>"
42 #define DRIVER_DESC     "CompactPCI Hot Plug Core"
43
44 #define MY_NAME "cpci_hotplug"
45
46 #define dbg(format, arg...)                                     \
47         do {                                                    \
48                 if (cpci_debug)                                 \
49                         printk (KERN_DEBUG "%s: " format "\n",  \
50                                 MY_NAME , ## arg);              \
51         } while (0)
52 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
53 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
54 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
55
56 /* local variables */
57 static DECLARE_RWSEM(list_rwsem);
58 static LIST_HEAD(slot_list);
59 static int slots;
60 static atomic_t extracting;
61 int cpci_debug;
62 static struct cpci_hp_controller *controller;
63 static struct task_struct *cpci_thread;
64 static int thread_finished;
65
66 static int enable_slot(struct hotplug_slot *slot);
67 static int disable_slot(struct hotplug_slot *slot);
68 static int set_attention_status(struct hotplug_slot *slot, u8 value);
69 static int get_power_status(struct hotplug_slot *slot, u8 * value);
70 static int get_attention_status(struct hotplug_slot *slot, u8 * value);
71 static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
72 static int get_latch_status(struct hotplug_slot *slot, u8 * value);
73
74 static struct hotplug_slot_ops cpci_hotplug_slot_ops = {
75         .enable_slot = enable_slot,
76         .disable_slot = disable_slot,
77         .set_attention_status = set_attention_status,
78         .get_power_status = get_power_status,
79         .get_attention_status = get_attention_status,
80         .get_adapter_status = get_adapter_status,
81         .get_latch_status = get_latch_status,
82 };
83
84 static int
85 update_latch_status(struct hotplug_slot *hotplug_slot, u8 value)
86 {
87         struct hotplug_slot_info info;
88
89         memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info));
90         info.latch_status = value;
91         return pci_hp_change_slot_info(hotplug_slot, &info);
92 }
93
94 static int
95 update_adapter_status(struct hotplug_slot *hotplug_slot, u8 value)
96 {
97         struct hotplug_slot_info info;
98
99         memcpy(&info, hotplug_slot->info, sizeof(struct hotplug_slot_info));
100         info.adapter_status = value;
101         return pci_hp_change_slot_info(hotplug_slot, &info);
102 }
103
104 static int
105 enable_slot(struct hotplug_slot *hotplug_slot)
106 {
107         struct slot *slot = hotplug_slot->private;
108         int retval = 0;
109
110         dbg("%s - physical_slot = %s", __func__, slot_name(slot));
111
112         if (controller->ops->set_power)
113                 retval = controller->ops->set_power(slot, 1);
114         return retval;
115 }
116
117 static int
118 disable_slot(struct hotplug_slot *hotplug_slot)
119 {
120         struct slot *slot = hotplug_slot->private;
121         int retval = 0;
122
123         dbg("%s - physical_slot = %s", __func__, slot_name(slot));
124
125         down_write(&list_rwsem);
126
127         /* Unconfigure device */
128         dbg("%s - unconfiguring slot %s", __func__, slot_name(slot));
129         if ((retval = cpci_unconfigure_slot(slot))) {
130                 err("%s - could not unconfigure slot %s",
131                     __func__, slot_name(slot));
132                 goto disable_error;
133         }
134         dbg("%s - finished unconfiguring slot %s", __func__, slot_name(slot));
135
136         /* Clear EXT (by setting it) */
137         if (cpci_clear_ext(slot)) {
138                 err("%s - could not clear EXT for slot %s",
139                     __func__, slot_name(slot));
140                 retval = -ENODEV;
141                 goto disable_error;
142         }
143         cpci_led_on(slot);
144
145         if (controller->ops->set_power)
146                 if ((retval = controller->ops->set_power(slot, 0)))
147                         goto disable_error;
148
149         if (update_adapter_status(slot->hotplug_slot, 0))
150                 warn("failure to update adapter file");
151
152         if (slot->extracting) {
153                 slot->extracting = 0;
154                 atomic_dec(&extracting);
155         }
156 disable_error:
157         up_write(&list_rwsem);
158         return retval;
159 }
160
161 static u8
162 cpci_get_power_status(struct slot *slot)
163 {
164         u8 power = 1;
165
166         if (controller->ops->get_power)
167                 power = controller->ops->get_power(slot);
168         return power;
169 }
170
171 static int
172 get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
173 {
174         struct slot *slot = hotplug_slot->private;
175
176         *value = cpci_get_power_status(slot);
177         return 0;
178 }
179
180 static int
181 get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
182 {
183         struct slot *slot = hotplug_slot->private;
184
185         *value = cpci_get_attention_status(slot);
186         return 0;
187 }
188
189 static int
190 set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
191 {
192         return cpci_set_attention_status(hotplug_slot->private, status);
193 }
194
195 static int
196 get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
197 {
198         *value = hotplug_slot->info->adapter_status;
199         return 0;
200 }
201
202 static int
203 get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)
204 {
205         *value = hotplug_slot->info->latch_status;
206         return 0;
207 }
208
209 static void release_slot(struct hotplug_slot *hotplug_slot)
210 {
211         struct slot *slot = hotplug_slot->private;
212
213         kfree(slot->hotplug_slot->info);
214         kfree(slot->hotplug_slot);
215         if (slot->dev)
216                 pci_dev_put(slot->dev);
217         kfree(slot);
218 }
219
220 #define SLOT_NAME_SIZE  6
221
222 int
223 cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
224 {
225         struct slot *slot;
226         struct hotplug_slot *hotplug_slot;
227         struct hotplug_slot_info *info;
228         char name[SLOT_NAME_SIZE];
229         int status = -ENOMEM;
230         int i;
231
232         if (!(controller && bus))
233                 return -ENODEV;
234
235         /*
236          * Create a structure for each slot, and register that slot
237          * with the pci_hotplug subsystem.
238          */
239         for (i = first; i <= last; ++i) {
240                 slot = kzalloc(sizeof (struct slot), GFP_KERNEL);
241                 if (!slot)
242                         goto error;
243
244                 hotplug_slot =
245                         kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
246                 if (!hotplug_slot)
247                         goto error_slot;
248                 slot->hotplug_slot = hotplug_slot;
249
250                 info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL);
251                 if (!info)
252                         goto error_hpslot;
253                 hotplug_slot->info = info;
254
255                 slot->bus = bus;
256                 slot->number = i;
257                 slot->devfn = PCI_DEVFN(i, 0);
258
259                 snprintf(name, SLOT_NAME_SIZE, "%02x:%02x", bus->number, i);
260
261                 hotplug_slot->private = slot;
262                 hotplug_slot->release = &release_slot;
263                 hotplug_slot->ops = &cpci_hotplug_slot_ops;
264
265                 /*
266                  * Initialize the slot info structure with some known
267                  * good values.
268                  */
269                 dbg("initializing slot %s", name);
270                 info->power_status = cpci_get_power_status(slot);
271                 info->attention_status = cpci_get_attention_status(slot);
272
273                 dbg("registering slot %s", name);
274                 status = pci_hp_register(slot->hotplug_slot, bus, i, name);
275                 if (status) {
276                         err("pci_hp_register failed with error %d", status);
277                         goto error_info;
278                 }
279                 dbg("slot registered with name: %s", slot_name(slot));
280
281                 /* Add slot to our internal list */
282                 down_write(&list_rwsem);
283                 list_add(&slot->slot_list, &slot_list);
284                 slots++;
285                 up_write(&list_rwsem);
286         }
287         return 0;
288 error_info:
289         kfree(info);
290 error_hpslot:
291         kfree(hotplug_slot);
292 error_slot:
293         kfree(slot);
294 error:
295         return status;
296 }
297
298 int
299 cpci_hp_unregister_bus(struct pci_bus *bus)
300 {
301         struct slot *slot;
302         struct slot *tmp;
303         int status = 0;
304
305         down_write(&list_rwsem);
306         if (!slots) {
307                 up_write(&list_rwsem);
308                 return -1;
309         }
310         list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) {
311                 if (slot->bus == bus) {
312                         list_del(&slot->slot_list);
313                         slots--;
314
315                         dbg("deregistering slot %s", slot_name(slot));
316                         status = pci_hp_deregister(slot->hotplug_slot);
317                         if (status) {
318                                 err("pci_hp_deregister failed with error %d",
319                                     status);
320                                 break;
321                         }
322                 }
323         }
324         up_write(&list_rwsem);
325         return status;
326 }
327
328 /* This is the interrupt mode interrupt handler */
329 static irqreturn_t
330 cpci_hp_intr(int irq, void *data)
331 {
332         dbg("entered cpci_hp_intr");
333
334         /* Check to see if it was our interrupt */
335         if ((controller->irq_flags & IRQF_SHARED) &&
336             !controller->ops->check_irq(controller->dev_id)) {
337                 dbg("exited cpci_hp_intr, not our interrupt");
338                 return IRQ_NONE;
339         }
340
341         /* Disable ENUM interrupt */
342         controller->ops->disable_irq();
343
344         /* Trigger processing by the event thread */
345         wake_up_process(cpci_thread);
346         return IRQ_HANDLED;
347 }
348
349 /*
350  * According to PICMG 2.1 R2.0, section 6.3.2, upon
351  * initialization, the system driver shall clear the
352  * INS bits of the cold-inserted devices.
353  */
354 static int
355 init_slots(int clear_ins)
356 {
357         struct slot *slot;
358         struct pci_dev* dev;
359
360         dbg("%s - enter", __func__);
361         down_read(&list_rwsem);
362         if (!slots) {
363                 up_read(&list_rwsem);
364                 return -1;
365         }
366         list_for_each_entry(slot, &slot_list, slot_list) {
367                 dbg("%s - looking at slot %s", __func__, slot_name(slot));
368                 if (clear_ins && cpci_check_and_clear_ins(slot))
369                         dbg("%s - cleared INS for slot %s",
370                             __func__, slot_name(slot));
371                 dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0));
372                 if (dev) {
373                         if (update_adapter_status(slot->hotplug_slot, 1))
374                                 warn("failure to update adapter file");
375                         if (update_latch_status(slot->hotplug_slot, 1))
376                                 warn("failure to update latch file");
377                         slot->dev = dev;
378                 }
379         }
380         up_read(&list_rwsem);
381         dbg("%s - exit", __func__);
382         return 0;
383 }
384
385 static int
386 check_slots(void)
387 {
388         struct slot *slot;
389         int extracted;
390         int inserted;
391         u16 hs_csr;
392
393         down_read(&list_rwsem);
394         if (!slots) {
395                 up_read(&list_rwsem);
396                 err("no slots registered, shutting down");
397                 return -1;
398         }
399         extracted = inserted = 0;
400         list_for_each_entry(slot, &slot_list, slot_list) {
401                 dbg("%s - looking at slot %s", __func__, slot_name(slot));
402                 if (cpci_check_and_clear_ins(slot)) {
403                         /*
404                          * Some broken hardware (e.g. PLX 9054AB) asserts
405                          * ENUM# twice...
406                          */
407                         if (slot->dev) {
408                                 warn("slot %s already inserted",
409                                      slot_name(slot));
410                                 inserted++;
411                                 continue;
412                         }
413
414                         /* Process insertion */
415                         dbg("%s - slot %s inserted", __func__, slot_name(slot));
416
417                         /* GSM, debug */
418                         hs_csr = cpci_get_hs_csr(slot);
419                         dbg("%s - slot %s HS_CSR (1) = %04x",
420                             __func__, slot_name(slot), hs_csr);
421
422                         /* Configure device */
423                         dbg("%s - configuring slot %s",
424                             __func__, slot_name(slot));
425                         if (cpci_configure_slot(slot)) {
426                                 err("%s - could not configure slot %s",
427                                     __func__, slot_name(slot));
428                                 continue;
429                         }
430                         dbg("%s - finished configuring slot %s",
431                             __func__, slot_name(slot));
432
433                         /* GSM, debug */
434                         hs_csr = cpci_get_hs_csr(slot);
435                         dbg("%s - slot %s HS_CSR (2) = %04x",
436                             __func__, slot_name(slot), hs_csr);
437
438                         if (update_latch_status(slot->hotplug_slot, 1))
439                                 warn("failure to update latch file");
440
441                         if (update_adapter_status(slot->hotplug_slot, 1))
442                                 warn("failure to update adapter file");
443
444                         cpci_led_off(slot);
445
446                         /* GSM, debug */
447                         hs_csr = cpci_get_hs_csr(slot);
448                         dbg("%s - slot %s HS_CSR (3) = %04x",
449                             __func__, slot_name(slot), hs_csr);
450
451                         inserted++;
452                 } else if (cpci_check_ext(slot)) {
453                         /* Process extraction request */
454                         dbg("%s - slot %s extracted",
455                             __func__, slot_name(slot));
456
457                         /* GSM, debug */
458                         hs_csr = cpci_get_hs_csr(slot);
459                         dbg("%s - slot %s HS_CSR = %04x",
460                             __func__, slot_name(slot), hs_csr);
461
462                         if (!slot->extracting) {
463                                 if (update_latch_status(slot->hotplug_slot, 0)) {
464                                         warn("failure to update latch file");
465                                 }
466                                 slot->extracting = 1;
467                                 atomic_inc(&extracting);
468                         }
469                         extracted++;
470                 } else if (slot->extracting) {
471                         hs_csr = cpci_get_hs_csr(slot);
472                         if (hs_csr == 0xffff) {
473                                 /*
474                                  * Hmmm, we're likely hosed at this point, should we
475                                  * bother trying to tell the driver or not?
476                                  */
477                                 err("card in slot %s was improperly removed",
478                                     slot_name(slot));
479                                 if (update_adapter_status(slot->hotplug_slot, 0))
480                                         warn("failure to update adapter file");
481                                 slot->extracting = 0;
482                                 atomic_dec(&extracting);
483                         }
484                 }
485         }
486         up_read(&list_rwsem);
487         dbg("inserted=%d, extracted=%d, extracting=%d",
488             inserted, extracted, atomic_read(&extracting));
489         if (inserted || extracted)
490                 return extracted;
491         else if (!atomic_read(&extracting)) {
492                 err("cannot find ENUM# source, shutting down");
493                 return -1;
494         }
495         return 0;
496 }
497
498 /* This is the interrupt mode worker thread body */
499 static int
500 event_thread(void *data)
501 {
502         int rc;
503
504         dbg("%s - event thread started", __func__);
505         while (1) {
506                 dbg("event thread sleeping");
507                 set_current_state(TASK_INTERRUPTIBLE);
508                 schedule();
509                 if (kthread_should_stop())
510                         break;
511                 do {
512                         rc = check_slots();
513                         if (rc > 0) {
514                                 /* Give userspace a chance to handle extraction */
515                                 msleep(500);
516                         } else if (rc < 0) {
517                                 dbg("%s - error checking slots", __func__);
518                                 thread_finished = 1;
519                                 goto out;
520                         }
521                 } while (atomic_read(&extracting) && !kthread_should_stop());
522                 if (kthread_should_stop())
523                         break;
524
525                 /* Re-enable ENUM# interrupt */
526                 dbg("%s - re-enabling irq", __func__);
527                 controller->ops->enable_irq();
528         }
529  out:
530         return 0;
531 }
532
533 /* This is the polling mode worker thread body */
534 static int
535 poll_thread(void *data)
536 {
537         int rc;
538
539         while (1) {
540                 if (kthread_should_stop() || signal_pending(current))
541                         break;
542                 if (controller->ops->query_enum()) {
543                         do {
544                                 rc = check_slots();
545                                 if (rc > 0) {
546                                         /* Give userspace a chance to handle extraction */
547                                         msleep(500);
548                                 } else if (rc < 0) {
549                                         dbg("%s - error checking slots", __func__);
550                                         thread_finished = 1;
551                                         goto out;
552                                 }
553                         } while (atomic_read(&extracting) && !kthread_should_stop());
554                 }
555                 msleep(100);
556         }
557  out:
558         return 0;
559 }
560
561 static int
562 cpci_start_thread(void)
563 {
564         if (controller->irq)
565                 cpci_thread = kthread_run(event_thread, NULL, "cpci_hp_eventd");
566         else
567                 cpci_thread = kthread_run(poll_thread, NULL, "cpci_hp_polld");
568         if (IS_ERR(cpci_thread)) {
569                 err("Can't start up our thread");
570                 return PTR_ERR(cpci_thread);
571         }
572         thread_finished = 0;
573         return 0;
574 }
575
576 static void
577 cpci_stop_thread(void)
578 {
579         kthread_stop(cpci_thread);
580         thread_finished = 1;
581 }
582
583 int
584 cpci_hp_register_controller(struct cpci_hp_controller *new_controller)
585 {
586         int status = 0;
587
588         if (controller)
589                 return -1;
590         if (!(new_controller && new_controller->ops))
591                 return -EINVAL;
592         if (new_controller->irq) {
593                 if (!(new_controller->ops->enable_irq &&
594                      new_controller->ops->disable_irq))
595                         status = -EINVAL;
596                 if (request_irq(new_controller->irq,
597                                cpci_hp_intr,
598                                new_controller->irq_flags,
599                                MY_NAME,
600                                new_controller->dev_id)) {
601                         err("Can't get irq %d for the hotplug cPCI controller",
602                             new_controller->irq);
603                         status = -ENODEV;
604                 }
605                 dbg("%s - acquired controller irq %d",
606                     __func__, new_controller->irq);
607         }
608         if (!status)
609                 controller = new_controller;
610         return status;
611 }
612
613 static void
614 cleanup_slots(void)
615 {
616         struct slot *slot;
617         struct slot *tmp;
618
619         /*
620          * Unregister all of our slots with the pci_hotplug subsystem,
621          * and free up all memory that we had allocated.
622          */
623         down_write(&list_rwsem);
624         if (!slots)
625                 goto cleanup_null;
626         list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) {
627                 list_del(&slot->slot_list);
628                 pci_hp_deregister(slot->hotplug_slot);
629         }
630 cleanup_null:
631         up_write(&list_rwsem);
632         return;
633 }
634
635 int
636 cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller)
637 {
638         int status = 0;
639
640         if (controller) {
641                 if (!thread_finished)
642                         cpci_stop_thread();
643                 if (controller->irq)
644                         free_irq(controller->irq, controller->dev_id);
645                 controller = NULL;
646                 cleanup_slots();
647         } else
648                 status = -ENODEV;
649         return status;
650 }
651
652 int
653 cpci_hp_start(void)
654 {
655         static int first = 1;
656         int status;
657
658         dbg("%s - enter", __func__);
659         if (!controller)
660                 return -ENODEV;
661
662         down_read(&list_rwsem);
663         if (list_empty(&slot_list)) {
664                 up_read(&list_rwsem);
665                 return -ENODEV;
666         }
667         up_read(&list_rwsem);
668
669         status = init_slots(first);
670         if (first)
671                 first = 0;
672         if (status)
673                 return status;
674
675         status = cpci_start_thread();
676         if (status)
677                 return status;
678         dbg("%s - thread started", __func__);
679
680         if (controller->irq) {
681                 /* Start enum interrupt processing */
682                 dbg("%s - enabling irq", __func__);
683                 controller->ops->enable_irq();
684         }
685         dbg("%s - exit", __func__);
686         return 0;
687 }
688
689 int
690 cpci_hp_stop(void)
691 {
692         if (!controller)
693                 return -ENODEV;
694         if (controller->irq) {
695                 /* Stop enum interrupt processing */
696                 dbg("%s - disabling irq", __func__);
697                 controller->ops->disable_irq();
698         }
699         cpci_stop_thread();
700         return 0;
701 }
702
703 int __init
704 cpci_hotplug_init(int debug)
705 {
706         cpci_debug = debug;
707         return 0;
708 }
709
710 void __exit
711 cpci_hotplug_exit(void)
712 {
713         /*
714          * Clean everything up.
715          */
716         cpci_hp_stop();
717         cpci_hp_unregister_controller(controller);
718 }
719
720 EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
721 EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller);
722 EXPORT_SYMBOL_GPL(cpci_hp_register_bus);
723 EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus);
724 EXPORT_SYMBOL_GPL(cpci_hp_start);
725 EXPORT_SYMBOL_GPL(cpci_hp_stop);