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