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