xref: /linux/drivers/pci/hotplug/cpci_hotplug_core.c (revision e5c86679d5e864947a52fb31e45a425dea3e7fa9)
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/sched/signal.h>
31 #include <linux/slab.h>
32 #include <linux/pci.h>
33 #include <linux/pci_hotplug.h>
34 #include <linux/init.h>
35 #include <linux/interrupt.h>
36 #include <linux/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 	retval = cpci_unconfigure_slot(slot);
130 	if (retval) {
131 		err("%s - could not unconfigure slot %s",
132 		    __func__, slot_name(slot));
133 		goto disable_error;
134 	}
135 	dbg("%s - finished unconfiguring slot %s", __func__, slot_name(slot));
136 
137 	/* Clear EXT (by setting it) */
138 	if (cpci_clear_ext(slot)) {
139 		err("%s - could not clear EXT for slot %s",
140 		    __func__, slot_name(slot));
141 		retval = -ENODEV;
142 		goto disable_error;
143 	}
144 	cpci_led_on(slot);
145 
146 	if (controller->ops->set_power) {
147 		retval = controller->ops->set_power(slot, 0);
148 		if (retval)
149 			goto disable_error;
150 	}
151 
152 	if (update_adapter_status(slot->hotplug_slot, 0))
153 		warn("failure to update adapter file");
154 
155 	if (slot->extracting) {
156 		slot->extracting = 0;
157 		atomic_dec(&extracting);
158 	}
159 disable_error:
160 	up_write(&list_rwsem);
161 	return retval;
162 }
163 
164 static u8
165 cpci_get_power_status(struct slot *slot)
166 {
167 	u8 power = 1;
168 
169 	if (controller->ops->get_power)
170 		power = controller->ops->get_power(slot);
171 	return power;
172 }
173 
174 static int
175 get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
176 {
177 	struct slot *slot = hotplug_slot->private;
178 
179 	*value = cpci_get_power_status(slot);
180 	return 0;
181 }
182 
183 static int
184 get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
185 {
186 	struct slot *slot = hotplug_slot->private;
187 
188 	*value = cpci_get_attention_status(slot);
189 	return 0;
190 }
191 
192 static int
193 set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
194 {
195 	return cpci_set_attention_status(hotplug_slot->private, status);
196 }
197 
198 static int
199 get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
200 {
201 	*value = hotplug_slot->info->adapter_status;
202 	return 0;
203 }
204 
205 static int
206 get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
207 {
208 	*value = hotplug_slot->info->latch_status;
209 	return 0;
210 }
211 
212 static void release_slot(struct hotplug_slot *hotplug_slot)
213 {
214 	struct slot *slot = hotplug_slot->private;
215 
216 	kfree(slot->hotplug_slot->info);
217 	kfree(slot->hotplug_slot);
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