xref: /linux/drivers/pci/hotplug/cpci_hotplug_core.c (revision 44eeab67416711db9b84610ef18c99a60415dff8)
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);
726