xref: /linux/drivers/pci/hotplug/pciehp_core.c (revision c537b994505099b7197e7d3125b942ecbcc51eb6)
1 /*
2  * PCI Express Hot Plug Controller Driver
3  *
4  * Copyright (C) 1995,2001 Compaq Computer Corporation
5  * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6  * Copyright (C) 2001 IBM Corp.
7  * Copyright (C) 2003-2004 Intel Corporation
8  *
9  * All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or (at
14  * your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
19  * NON INFRINGEMENT.  See the GNU General Public License for more
20  * details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
27  *
28  */
29 
30 #include <linux/module.h>
31 #include <linux/moduleparam.h>
32 #include <linux/kernel.h>
33 #include <linux/types.h>
34 #include <linux/pci.h>
35 #include "pciehp.h"
36 #include <linux/interrupt.h>
37 #include <linux/time.h>
38 
39 /* Global variables */
40 int pciehp_debug;
41 int pciehp_poll_mode;
42 int pciehp_poll_time;
43 int pciehp_force;
44 struct controller *pciehp_ctrl_list;
45 
46 #define DRIVER_VERSION	"0.4"
47 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
48 #define DRIVER_DESC	"PCI Express Hot Plug Controller Driver"
49 
50 MODULE_AUTHOR(DRIVER_AUTHOR);
51 MODULE_DESCRIPTION(DRIVER_DESC);
52 MODULE_LICENSE("GPL");
53 
54 module_param(pciehp_debug, bool, 0644);
55 module_param(pciehp_poll_mode, bool, 0644);
56 module_param(pciehp_poll_time, int, 0644);
57 module_param(pciehp_force, bool, 0644);
58 MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
59 MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
60 MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
61 MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing");
62 
63 #define PCIE_MODULE_NAME "pciehp"
64 
65 static int pcie_start_thread (void);
66 static int set_attention_status (struct hotplug_slot *slot, u8 value);
67 static int enable_slot		(struct hotplug_slot *slot);
68 static int disable_slot		(struct hotplug_slot *slot);
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_latch_status	(struct hotplug_slot *slot, u8 *value);
72 static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
73 static int get_address		(struct hotplug_slot *slot, u32 *value);
74 static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
75 static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
76 
77 static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
78 	.owner =		THIS_MODULE,
79 	.set_attention_status =	set_attention_status,
80 	.enable_slot =		enable_slot,
81 	.disable_slot =		disable_slot,
82 	.get_power_status =	get_power_status,
83 	.get_attention_status =	get_attention_status,
84 	.get_latch_status =	get_latch_status,
85 	.get_adapter_status =	get_adapter_status,
86 	.get_address =		get_address,
87   	.get_max_bus_speed =	get_max_bus_speed,
88   	.get_cur_bus_speed =	get_cur_bus_speed,
89 };
90 
91 /*
92  * Check the status of the Electro Mechanical Interlock (EMI)
93  */
94 static int get_lock_status(struct hotplug_slot *hotplug_slot, u8 *value)
95 {
96 	struct slot *slot = hotplug_slot->private;
97 	return (slot->hpc_ops->get_emi_status(slot, value));
98 }
99 
100 /*
101  * sysfs interface for the Electro Mechanical Interlock (EMI)
102  * 1 == locked, 0 == unlocked
103  */
104 static ssize_t lock_read_file(struct hotplug_slot *slot, char *buf)
105 {
106 	int retval;
107 	u8 value;
108 
109 	retval = get_lock_status(slot, &value);
110 	if (retval)
111 		goto lock_read_exit;
112 	retval = sprintf (buf, "%d\n", value);
113 
114 lock_read_exit:
115 	return retval;
116 }
117 
118 /*
119  * Change the status of the Electro Mechanical Interlock (EMI)
120  * This is a toggle - in addition there must be at least 1 second
121  * in between toggles.
122  */
123 static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status)
124 {
125 	struct slot *slot = hotplug_slot->private;
126 	int retval;
127 	u8 value;
128 
129 	mutex_lock(&slot->ctrl->crit_sect);
130 
131 	/* has it been >1 sec since our last toggle? */
132 	if ((get_seconds() - slot->last_emi_toggle) < 1)
133 		return -EINVAL;
134 
135 	/* see what our current state is */
136 	retval = get_lock_status(hotplug_slot, &value);
137 	if (retval || (value == status))
138 		goto set_lock_exit;
139 
140 	slot->hpc_ops->toggle_emi(slot);
141 set_lock_exit:
142 	mutex_unlock(&slot->ctrl->crit_sect);
143 	return 0;
144 }
145 
146 /*
147  * sysfs interface which allows the user to toggle the Electro Mechanical
148  * Interlock.  Valid values are either 0 or 1.  0 == unlock, 1 == lock
149  */
150 static ssize_t lock_write_file(struct hotplug_slot *slot, const char *buf,
151 		size_t count)
152 {
153 	unsigned long llock;
154 	u8 lock;
155 	int retval = 0;
156 
157 	llock = simple_strtoul(buf, NULL, 10);
158 	lock = (u8)(llock & 0xff);
159 
160 	switch (lock) {
161 		case 0:
162 		case 1:
163 			retval = set_lock_status(slot, lock);
164 			break;
165 		default:
166 			err ("%d is an invalid lock value\n", lock);
167 			retval = -EINVAL;
168 	}
169 	if (retval)
170 		return retval;
171 	return count;
172 }
173 
174 static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
175 	.attr = {.name = "lock", .mode = S_IFREG | S_IRUGO | S_IWUSR},
176 	.show = lock_read_file,
177 	.store = lock_write_file
178 };
179 
180 /**
181  * release_slot - free up the memory used by a slot
182  * @hotplug_slot: slot to free
183  */
184 static void release_slot(struct hotplug_slot *hotplug_slot)
185 {
186 	struct slot *slot = hotplug_slot->private;
187 
188 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
189 
190 	kfree(slot->hotplug_slot->info);
191 	kfree(slot->hotplug_slot);
192 	kfree(slot);
193 }
194 
195 static void make_slot_name(struct slot *slot)
196 {
197 	snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
198 		 slot->bus, slot->number);
199 }
200 
201 static int init_slots(struct controller *ctrl)
202 {
203 	struct slot *slot;
204 	struct hotplug_slot *hotplug_slot;
205 	struct hotplug_slot_info *info;
206 	int retval = -ENOMEM;
207 	int i;
208 
209 	for (i = 0; i < ctrl->num_slots; i++) {
210 		slot = kzalloc(sizeof(*slot), GFP_KERNEL);
211 		if (!slot)
212 			goto error;
213 
214 		hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
215 		if (!hotplug_slot)
216 			goto error_slot;
217 		slot->hotplug_slot = hotplug_slot;
218 
219 		info = kzalloc(sizeof(*info), GFP_KERNEL);
220 		if (!info)
221 			goto error_hpslot;
222 		hotplug_slot->info = info;
223 
224 		hotplug_slot->name = slot->name;
225 
226 		slot->hp_slot = i;
227 		slot->ctrl = ctrl;
228 		slot->bus = ctrl->pci_dev->subordinate->number;
229 		slot->device = ctrl->slot_device_offset + i;
230 		slot->hpc_ops = ctrl->hpc_ops;
231 		slot->number = ctrl->first_slot;
232 
233 		/* register this slot with the hotplug pci core */
234 		hotplug_slot->private = slot;
235 		hotplug_slot->release = &release_slot;
236 		make_slot_name(slot);
237 		hotplug_slot->ops = &pciehp_hotplug_slot_ops;
238 
239 		get_power_status(hotplug_slot, &info->power_status);
240 		get_attention_status(hotplug_slot, &info->attention_status);
241 		get_latch_status(hotplug_slot, &info->latch_status);
242 		get_adapter_status(hotplug_slot, &info->adapter_status);
243 
244 		dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
245 		    "slot_device_offset=%x\n", slot->bus, slot->device,
246 		    slot->hp_slot, slot->number, ctrl->slot_device_offset);
247 		retval = pci_hp_register(hotplug_slot);
248 		if (retval) {
249 			err ("pci_hp_register failed with error %d\n", retval);
250 			goto error_info;
251 		}
252 		/* create additional sysfs entries */
253 		if (EMI(ctrl->ctrlcap)) {
254 			retval = sysfs_create_file(&hotplug_slot->kobj,
255 				&hotplug_slot_attr_lock.attr);
256 			if (retval) {
257 				pci_hp_deregister(hotplug_slot);
258 				err("cannot create additional sysfs entries\n");
259 				goto error_info;
260 			}
261 		}
262 
263 		list_add(&slot->slot_list, &ctrl->slot_list);
264 	}
265 
266 	return 0;
267 error_info:
268 	kfree(info);
269 error_hpslot:
270 	kfree(hotplug_slot);
271 error_slot:
272 	kfree(slot);
273 error:
274 	return retval;
275 }
276 
277 static void cleanup_slots(struct controller *ctrl)
278 {
279 	struct list_head *tmp;
280 	struct list_head *next;
281 	struct slot *slot;
282 
283 	list_for_each_safe(tmp, next, &ctrl->slot_list) {
284 		slot = list_entry(tmp, struct slot, slot_list);
285 		list_del(&slot->slot_list);
286 		if (EMI(ctrl->ctrlcap))
287 			sysfs_remove_file(&slot->hotplug_slot->kobj,
288 				&hotplug_slot_attr_lock.attr);
289 		pci_hp_deregister(slot->hotplug_slot);
290 	}
291 }
292 
293 /*
294  * set_attention_status - Turns the Amber LED for a slot on, off or blink
295  */
296 static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
297 {
298 	struct slot *slot = hotplug_slot->private;
299 
300 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
301 
302 	hotplug_slot->info->attention_status = status;
303 
304 	if (ATTN_LED(slot->ctrl->ctrlcap))
305 		slot->hpc_ops->set_attention_status(slot, status);
306 
307 	return 0;
308 }
309 
310 
311 static int enable_slot(struct hotplug_slot *hotplug_slot)
312 {
313 	struct slot *slot = hotplug_slot->private;
314 
315 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
316 
317 	return pciehp_enable_slot(slot);
318 }
319 
320 
321 static int disable_slot(struct hotplug_slot *hotplug_slot)
322 {
323 	struct slot *slot = hotplug_slot->private;
324 
325 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
326 
327 	return pciehp_disable_slot(slot);
328 }
329 
330 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
331 {
332 	struct slot *slot = hotplug_slot->private;
333 	int retval;
334 
335 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
336 
337 	retval = slot->hpc_ops->get_power_status(slot, value);
338 	if (retval < 0)
339 		*value = hotplug_slot->info->power_status;
340 
341 	return 0;
342 }
343 
344 static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
345 {
346 	struct slot *slot = hotplug_slot->private;
347 	int retval;
348 
349 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
350 
351 	retval = slot->hpc_ops->get_attention_status(slot, value);
352 	if (retval < 0)
353 		*value = hotplug_slot->info->attention_status;
354 
355 	return 0;
356 }
357 
358 static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
359 {
360 	struct slot *slot = hotplug_slot->private;
361 	int retval;
362 
363 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
364 
365 	retval = slot->hpc_ops->get_latch_status(slot, value);
366 	if (retval < 0)
367 		*value = hotplug_slot->info->latch_status;
368 
369 	return 0;
370 }
371 
372 static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
373 {
374 	struct slot *slot = hotplug_slot->private;
375 	int retval;
376 
377 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
378 
379 	retval = slot->hpc_ops->get_adapter_status(slot, value);
380 	if (retval < 0)
381 		*value = hotplug_slot->info->adapter_status;
382 
383 	return 0;
384 }
385 
386 static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
387 {
388 	struct slot *slot = hotplug_slot->private;
389 	struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
390 
391 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
392 
393 	*value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
394 
395 	return 0;
396 }
397 
398 static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
399 {
400 	struct slot *slot = hotplug_slot->private;
401 	int retval;
402 
403 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
404 
405 	retval = slot->hpc_ops->get_max_bus_speed(slot, value);
406 	if (retval < 0)
407 		*value = PCI_SPEED_UNKNOWN;
408 
409 	return 0;
410 }
411 
412 static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
413 {
414 	struct slot *slot = hotplug_slot->private;
415 	int retval;
416 
417 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
418 
419 	retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
420 	if (retval < 0)
421 		*value = PCI_SPEED_UNKNOWN;
422 
423 	return 0;
424 }
425 
426 static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_id *id)
427 {
428 	int rc;
429 	struct controller *ctrl;
430 	struct slot *t_slot;
431 	u8 value;
432 	struct pci_dev *pdev;
433 
434 	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
435 	if (!ctrl) {
436 		err("%s : out of memory\n", __FUNCTION__);
437 		goto err_out_none;
438 	}
439 	INIT_LIST_HEAD(&ctrl->slot_list);
440 
441 	pdev = dev->port;
442 	ctrl->pci_dev = pdev;
443 
444 	rc = pcie_init(ctrl, dev);
445 	if (rc) {
446 		dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
447 		goto err_out_free_ctrl;
448 	}
449 
450 	pci_set_drvdata(pdev, ctrl);
451 
452 	ctrl->bus = pdev->bus->number;  /* ctrl bus */
453 	ctrl->slot_bus = pdev->subordinate->number;  /* bus controlled by this HPC */
454 
455 	ctrl->device = PCI_SLOT(pdev->devfn);
456 	ctrl->function = PCI_FUNC(pdev->devfn);
457 	dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__,
458 		ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
459 
460 	/* Setup the slot information structures */
461 	rc = init_slots(ctrl);
462 	if (rc) {
463 		err("%s: slot initialization failed\n", PCIE_MODULE_NAME);
464 		goto err_out_release_ctlr;
465 	}
466 
467 	t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
468 
469 	/*	Finish setting up the hot plug ctrl device */
470 	ctrl->next_event = 0;
471 
472 	if (!pciehp_ctrl_list) {
473 		pciehp_ctrl_list = ctrl;
474 		ctrl->next = NULL;
475 	} else {
476 		ctrl->next = pciehp_ctrl_list;
477 		pciehp_ctrl_list = ctrl;
478 	}
479 
480 	t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
481 	if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
482 		rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
483 		if (rc)
484 			goto err_out_free_ctrl_slot;
485 	}
486 
487 	return 0;
488 
489 err_out_free_ctrl_slot:
490 	cleanup_slots(ctrl);
491 err_out_release_ctlr:
492 	ctrl->hpc_ops->release_ctlr(ctrl);
493 err_out_free_ctrl:
494 	kfree(ctrl);
495 err_out_none:
496 	return -ENODEV;
497 }
498 
499 
500 static int pcie_start_thread(void)
501 {
502 	int retval = 0;
503 
504 	dbg("Initialize + Start the notification/polling mechanism \n");
505 
506 	retval = pciehp_event_start_thread();
507 	if (retval) {
508 		dbg("pciehp_event_start_thread() failed\n");
509 		return retval;
510 	}
511 
512 	return retval;
513 }
514 
515 static void __exit unload_pciehpd(void)
516 {
517 	struct controller *ctrl;
518 	struct controller *tctrl;
519 
520 	ctrl = pciehp_ctrl_list;
521 
522 	while (ctrl) {
523 		cleanup_slots(ctrl);
524 
525 		ctrl->hpc_ops->release_ctlr(ctrl);
526 
527 		tctrl = ctrl;
528 		ctrl = ctrl->next;
529 
530 		kfree(tctrl);
531 	}
532 
533 	/* Stop the notification mechanism */
534 	pciehp_event_stop_thread();
535 
536 }
537 
538 static void pciehp_remove (struct pcie_device *device)
539 {
540 	/* XXX - Needs to be adapted to device driver model */
541 }
542 
543 #ifdef CONFIG_PM
544 static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
545 {
546 	printk("%s ENTRY\n", __FUNCTION__);
547 	return 0;
548 }
549 
550 static int pciehp_resume (struct pcie_device *dev)
551 {
552 	printk("%s ENTRY\n", __FUNCTION__);
553 	return 0;
554 }
555 #endif
556 
557 static struct pcie_port_service_id port_pci_ids[] = { {
558 	.vendor = PCI_ANY_ID,
559 	.device = PCI_ANY_ID,
560 	.port_type = PCIE_ANY_PORT,
561 	.service_type = PCIE_PORT_SERVICE_HP,
562 	.driver_data =	0,
563 	}, { /* end: all zeroes */ }
564 };
565 static const char device_name[] = "hpdriver";
566 
567 static struct pcie_port_service_driver hpdriver_portdrv = {
568 	.name		= (char *)device_name,
569 	.id_table	= &port_pci_ids[0],
570 
571 	.probe		= pciehp_probe,
572 	.remove		= pciehp_remove,
573 
574 #ifdef	CONFIG_PM
575 	.suspend	= pciehp_suspend,
576 	.resume		= pciehp_resume,
577 #endif	/* PM */
578 };
579 
580 static int __init pcied_init(void)
581 {
582 	int retval = 0;
583 
584 #ifdef CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
585 	pciehp_poll_mode = 1;
586 #endif
587 
588 	retval = pcie_start_thread();
589 	if (retval)
590 		goto error_hpc_init;
591 
592 	retval = pcie_port_service_register(&hpdriver_portdrv);
593  	dbg("pcie_port_service_register = %d\n", retval);
594   	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
595  	if (retval)
596 		dbg("%s: Failure to register service\n", __FUNCTION__);
597 
598 error_hpc_init:
599 	if (retval) {
600 		pciehp_event_stop_thread();
601 	};
602 
603 	return retval;
604 }
605 
606 static void __exit pcied_cleanup(void)
607 {
608 	dbg("unload_pciehpd()\n");
609 	unload_pciehpd();
610 
611 	pcie_port_service_unregister(&hpdriver_portdrv);
612 
613 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
614 }
615 
616 module_init(pcied_init);
617 module_exit(pcied_cleanup);
618