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