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