• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) International Business Machines  Corp., 2001
3  * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
4  *
5  * This program is free software;  you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  * the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program;  if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *
19  * This pci and pci-express testing kernel module will allow test calls
20  * to be driven through various ioctl calls in a
21  * user space program that has attained the appropriate
22  * file descriptor for this device. For the functions of
23  * this module to work correctly there must be a pci / pci-express
24  * device somewhere in the system. The tests do not need
25  * a specific device, and the first pci device available
26  * will be grabbed.
27  *
28  * author: Sean Ruyle (srruyle@us.ibm.com)
29  * date:   5/20/2003
30  * PCI-Express test scripts author: Amit Khanna (amit.khanna@intel.com)
31  * date:   8/20/2004
32  *
33  * file:   tpci.c,
34  * module: tpci
35  */
36 
37 #include <linux/types.h>
38 #include <linux/kernel.h>
39 #include <linux/fs.h>
40 #include <linux/ioctl.h>
41 #include <linux/module.h>
42 #include <linux/init.h>
43 #include <linux/pci.h>
44 
45 #include "tpci.h"
46 
47 MODULE_AUTHOR("Sean Ruyle <srruyle@us.ibm.com>");
48 MODULE_AUTHOR("Amit Khanna <amit.khanna@intel.com>");
49 MODULE_AUTHOR("Copyright (c) 2013 Oracle and/or its affiliates");
50 MODULE_DESCRIPTION("LTP PCI Test");
51 MODULE_LICENSE("GPL");
52 
53 #define prk_err(fmt, ...) \
54 	pr_err(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
55 #define prk_info(fmt, ...) \
56 	pr_info(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
57 #define prk_debug(fmt, ...) \
58 	pr_debug(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
59 
60 #define TPASS	0
61 #define TFAIL	1
62 #define TSKIP	32
63 
64 static DEFINE_PCI_DEVICE_TABLE(ltp_pci_tbl) = {
65 	{ PCI_DEVICE(PCI_ANY_ID, PCI_ANY_ID) },
66 	{ 0, }
67 };
68 
69 MODULE_DEVICE_TABLE(pci, ltp_pci_tbl);
70 
ltp_pci_probe(struct pci_dev * pci_dev,const struct pci_device_id * pci_ent)71 static int ltp_pci_probe(struct pci_dev *pci_dev,
72 	const struct pci_device_id *pci_ent)
73 {
74 	return 0;
75 }
76 
77 static struct pci_driver ltp_pci_driver = {
78 	.name     = "LTP_PCI_DRIVER",
79 	.id_table = ltp_pci_tbl,
80 	.probe    = ltp_pci_probe,
81 };
82 
83 static int pci_registered;
84 
85 struct tpci_user {
86 	struct pci_dev		*dev;
87 	struct pci_bus		*bus;
88 	struct pci_driver	*drv;
89 	uint32_t		state[16];
90 };
91 static struct tpci_user ltp_pci;
92 
93 /*
94  * probe_pci_dev
95  *	find a pci device that can be used for other test
96  *	calls in this kernel module.
97  */
probe_pci_dev(unsigned int bus,unsigned int slot)98 static int probe_pci_dev(unsigned int bus, unsigned int slot)
99 {
100 	struct pci_dev *dev;
101 
102 	if (ltp_pci.dev) {
103 		pci_dev_put(ltp_pci.dev);
104 		ltp_pci.dev = NULL;
105 	}
106 
107 	dev = pci_get_bus_and_slot(bus, slot);
108 	if (!dev || !dev->driver)
109 		return -ENODEV;
110 
111 	prk_info("found pci_dev '%s', bus %u, devfn %u",
112 		pci_name(dev), bus, slot);
113 
114 	ltp_pci.dev = dev;
115 	ltp_pci.bus = dev->bus;
116 	prk_info("Bus number: %d", dev->bus->number);
117 	return 0;
118 }
119 
120 /*
121  * pci_enable
122  *	enable a pci device so that it may be used in
123  *	later testing in the user test program
124  */
pci_enable(void)125 static int pci_enable(void)
126 {
127 	struct pci_dev *dev = ltp_pci.dev;
128 
129 	prk_info("enable pci device");
130 
131 	/* check if can enable the device pointer */
132 	if (!dev) {
133 		prk_err("dev is NULL");
134 		return TFAIL;
135 	}
136 
137 	if (pci_enable_device(dev)) {
138 		prk_err("failed to enable pci device");
139 		return TFAIL;
140 	}
141 
142 	prk_info("enabled pci device");
143 	return TPASS;
144 }
145 
pci_disable(void)146 static int pci_disable(void)
147 {
148 	struct pci_dev *dev = ltp_pci.dev;
149 
150 	prk_info("disable pci device");
151 
152 	/* check if device pointer exists */
153 	if (!dev) {
154 		prk_err("dev is NULL");
155 		return TFAIL;
156 	}
157 
158 	prk_info("is pci enabled '%d', is managed '%d'",
159 		pci_is_enabled(dev), pci_is_managed(dev));
160 
161 	pci_release_regions(dev);
162 	pci_disable_device(dev);
163 
164 	if (dev->current_state == PCI_D3hot ||
165 		dev->current_state == PCI_D3cold) {
166 
167 		prk_info("disabled pci device, state '%s'",
168 			pci_power_name(dev->current_state));
169 		return TPASS;
170 
171 	}
172 
173 	prk_err("failed to disable pci device, state '%s'",
174 		pci_power_name(dev->current_state));
175 	return TFAIL;
176 }
177 
178 /*
179  * find_bus
180  *	call to pci_find_bus, use values from bus
181  *	pointer in ltp_pci, make sure that returns
182  *	bus with same values
183  */
test_find_bus(void)184 static int test_find_bus(void)
185 {
186 	int num = ltp_pci.bus->number;
187 	struct pci_bus *temp = NULL;
188 
189 	prk_info("find bus");
190 
191 	temp = pci_find_bus(pci_domain_nr(ltp_pci.bus), num);
192 
193 	if (!temp) {
194 		prk_info("pci_find_bus failed");
195 		return TFAIL;
196 	} else if (temp->number != num) {
197 		prk_err("returned bus pointer w/ wrong bus number");
198 		return TFAIL;
199 	}
200 
201 	prk_info("success returned bus pointer");
202 	return TPASS;
203 }
204 
205 /*
206  * find_class
207  *	call to pci_find_class, using values from the
208  *	pci_dev pointer in ltp_pci structure
209  */
test_find_class(void)210 static int test_find_class(void)
211 {
212 	unsigned int num = ltp_pci.dev->class;
213 	struct pci_dev *temp = NULL;
214 
215 	prk_info("find pci class");
216 
217 	temp = pci_get_class(num, NULL);
218 
219 	if (!temp) {
220 		prk_err("failed to find pci device from class number");
221 		return TFAIL;
222 	}
223 
224 	prk_info("found pci device from class number");
225 	pci_dev_put(temp);
226 
227 	return TPASS;
228 }
229 
230 /*
231  * find_device
232  *	call to pci_find_device, using values for
233  *	parameters from pci_dev pointer in the
234  *	ltp_pci structure
235  */
test_find_device(void)236 static int test_find_device(void)
237 {
238 	struct pci_dev *temp = NULL;
239 	unsigned short ven = ltp_pci.dev->vendor, dev = ltp_pci.dev->device;
240 
241 	prk_info("get pci device");
242 
243 	temp = pci_get_device(ven, dev, NULL);
244 
245 	if (!temp) {
246 		prk_err("failed to find pci device from device info");
247 		return TFAIL;
248 	}
249 
250 	prk_info("found pci device from device info");
251 	pci_dev_put(temp);
252 
253 	return TPASS;
254 }
255 
256 /*
257  * find_subsys
258  *	call to pci_find_subsys, use valued from
259  *	pci_dev pointer in ltp_pci structure to
260  *	find pci_dev from subsys info
261  */
test_find_subsys(void)262 static int test_find_subsys(void)
263 {
264 	struct pci_dev *temp;
265 	unsigned short ven = ltp_pci.dev->vendor,
266 		dev = ltp_pci.dev->device,
267 		ss_ven = ltp_pci.dev->subsystem_vendor,
268 		ss_dev = ltp_pci.dev->subsystem_device;
269 
270 	prk_info("get pci subsys");
271 	temp = pci_get_subsys(ven, dev, ss_ven, ss_dev, NULL);
272 
273 	if (!temp) {
274 		prk_err("failed to find pci device from subsys info");
275 		return TFAIL;
276 	}
277 
278 	prk_info("found pci device from subsys info");
279 	pci_dev_put(temp);
280 
281 	return TPASS;
282 }
283 
284 /*
285  * test_scan_bus
286  *	call to pci_do_scan_bus,  which takes
287  *	a struct pci_bus pointer, which will
288  *	return an integer for how far the
289  *	function got in scanning bus
290  */
test_scan_bus(void)291 static int test_scan_bus(void)
292 {
293 #ifdef CONFIG_HOTPLUG
294 	int num;
295 	struct pci_bus *bus = ltp_pci.bus;
296 
297 	prk_info("scan pci bus");
298 
299 	num = pci_rescan_bus(bus);
300 	/*
301 	 * check if returned number is greater than
302 	 * max number of bus or less than 0
303 	 */
304 	if (num > MAX_BUS || num < 0) {
305 		prk_err("failed scan bus");
306 		return TFAIL;
307 	}
308 	prk_info("success scan bus");
309 	return TPASS;
310 #else
311 	prk_info("pci_rescan_bus() is not supported");
312 	return TSKIP;
313 #endif
314 }
315 
316 /*
317  * test_slot_scan
318  *	make call to pci_scan_slot, which will
319  *	find the device pointer and setup the
320  *	device info
321  */
test_slot_scan(void)322 static int test_slot_scan(void)
323 {
324 	int ret, num = ltp_pci.dev->devfn;
325 	struct pci_bus *bus = ltp_pci.bus;
326 
327 	prk_info("scan pci slot");
328 
329 	ret = pci_scan_slot(bus, num);
330 	if (ret >= 0) {
331 		prk_info("found '%d' devices from scan slot", ret);
332 		return TPASS;
333 	}
334 
335 	prk_err("pci_scan_slot failed");
336 	return TFAIL;
337 }
338 
339 /*
340  * test_bus_add_devices
341  *	make call to pci_bus_add_devices,
342  *	which will check the device pointer
343  *	that is passed in for more devices
344  *	that it can add
345  */
test_bus_add_devices(void)346 static int test_bus_add_devices(void)
347 {
348 	struct pci_bus *bus = ltp_pci.bus;
349 
350 	prk_info("add bus device");
351 
352 	pci_bus_add_devices(bus);
353 
354 	if (bus) {
355 		prk_info("called bus_add_device");
356 		return TPASS;
357 	}
358 
359 	prk_err("bus_add_device failed");
360 	return TFAIL;
361 }
362 
363 /*
364  * test_enable_bridges
365  *	make call to pci_enable_bridges,
366  *	use bus pointer from the ltp_pci
367  *	structure
368  */
test_enable_bridges(void)369 static int test_enable_bridges(void)
370 {
371 	struct pci_bus *bus = ltp_pci.bus;
372 
373 	prk_info("enable bridges");
374 
375 	pci_enable_bridges(bus);
376 
377 	if (bus) {
378 		prk_info("called enable bridges");
379 		return TPASS;
380 	}
381 
382 	prk_err("enable_bridges failed");
383 	return TFAIL;
384 }
385 
386 /*
387  * test_match_device
388  *	make call to pci_match_device, returns a
389  *	pci_device_id pointer
390  */
test_match_device(void)391 static int test_match_device(void)
392 {
393 	struct pci_dev *dev = ltp_pci.dev;
394 	struct pci_driver *drv;
395 	const struct pci_device_id *id;
396 
397 	prk_info("test pci_device_id()");
398 
399 	drv = pci_dev_driver(dev);
400 
401 	if (!drv) {
402 		prk_err("driver pointer not allocated for pci_dev");
403 		return TFAIL;
404 	}
405 
406 	id = pci_match_id(drv->id_table, dev);
407 
408 	if (id) {
409 		prk_info("match device success");
410 		return TPASS;
411 	}
412 
413 	prk_err("failed return pci_device_id");
414 	return TFAIL;
415 }
416 
417 
418 /*
419  * test_reg_driver
420  *	make call to pci_register_driver, which will
421  *	register the driver for a device with the
422  *	system
423  */
test_reg_driver(void)424 static int test_reg_driver(void)
425 {
426 	prk_info("test pci_register_driver");
427 	if (pci_register_driver(&ltp_pci_driver)) {
428 		prk_err("unsuccessful registering pci driver");
429 		return TFAIL;
430 	}
431 	pci_registered = 1;
432 	prk_info("success driver register");
433 	return TPASS;
434 }
435 
436 /*
437  * test_unreg_driver
438  *	make call to pci_unregister_driver, which will
439  *	unregister the driver for a device from the system
440  */
test_unreg_driver(void)441 static int test_unreg_driver(void)
442 {
443 	pci_unregister_driver(&ltp_pci_driver);
444 	pci_registered = 0;
445 	return TPASS;
446 }
447 
448 /*
449  * test_assign_resources
450  *	make calls to pci_assign_resource, will need
451  *	to setup a dev pointer and resource pointer,
452  */
test_assign_resources(void)453 static int test_assign_resources(void)
454 {
455 	int i, ret, rc = 0;
456 	struct pci_dev *dev = ltp_pci.dev;
457 	struct resource *r;
458 
459 	prk_info("assign resources");
460 
461 	for (i = 0; i < 7; ++i) {
462 		prk_info("assign resource #%d", i);
463 		r = &dev->resource[i];
464 		prk_info("name = %s, flags = %lu, start 0x%lx, end 0x%lx",
465 			r->name, r->flags,
466 			(unsigned long)r->start, (unsigned long)r->end);
467 
468 		if (r->flags & IORESOURCE_MEM &&
469 			r->flags & IORESOURCE_PREFETCH) {
470 			ret = pci_assign_resource(dev, i);
471 			prk_info("assign resource to '%d', ret '%d'", i, ret);
472 			rc |= (ret < 0 && ret != -EBUSY) ? TFAIL : TPASS;
473 		}
474 	}
475 
476 	/*
477 	 * enable device after call to assign resource
478 	 * because might error if (!r->start && r->end)
479 	 */
480 	if (pci_enable_device(dev))
481 		return TFAIL;
482 
483 	return rc;
484 }
485 
486 /*
487  * test_save_state
488  *	make call to pci_save_state, takes in a u32*
489  *	buffer
490  */
test_save_state(void)491 static int test_save_state(void)
492 {
493 	struct pci_dev *dev = ltp_pci.dev;
494 
495 	prk_info("save state");
496 
497 	if (pci_save_state(dev)) {
498 		prk_err("failed save state");
499 		return TFAIL;
500 	}
501 
502 	prk_info("saved state of device");
503 	return TPASS;
504 }
505 
506 /*
507  * test_restore_state
508  *	make call to pci_restore_state, get the state buffer
509  *	should have been previously filled out by save state
510  */
test_restore_state(void)511 static int test_restore_state(void)
512 {
513 	struct pci_dev *dev = ltp_pci.dev;
514 
515 	prk_info("restore state");
516 
517 	pci_restore_state(dev);
518 
519 	return TPASS;
520 }
521 
522 /*
523  * test_find_cap
524  *	make call to pci_find_capability, which
525  *	will determine if a device has a certain
526  *	capability, use second parameter to specify
527  *	which capability you are looking for
528  */
test_find_cap(void)529 static int test_find_cap(void)
530 {
531 	struct pci_dev *dev = ltp_pci.dev;
532 
533 	prk_info("find device capability");
534 
535 	if (pci_find_capability(dev, PCI_CAP_ID_PM))
536 		prk_info("does not have tested capability");
537 	else
538 		prk_info("device has PM capability");
539 
540 	return TPASS;
541 }
542 
543 /*
544  * test_read_pci_exp_config
545  *	make call to pci_config_read and determine if
546  *	the PCI-Express enhanced config space of this
547  *	device can be read successfully.
548  */
test_read_pci_exp_config(void)549 static int test_read_pci_exp_config(void)
550 {
551 	int pos;
552 	u32 header;
553 	struct pci_dev *dev = ltp_pci.dev;
554 
555 	/* skip the test if device doesn't have PCIe capability */
556 	pos = pci_pcie_cap(dev);
557 	if (!pos) {
558 		prk_info("device doesn't have PCI-EXP capability");
559 		return TSKIP;
560 	}
561 	prk_info("read the PCI Express configuration registers at 0x%x", pos);
562 
563 	if (pci_read_config_dword(dev, pos, &header)) {
564 		prk_err("failed to read config dword");
565 		return TFAIL;
566 	}
567 
568 	/* comparing the value read with PCI_CAP_ID_EXP macro */
569 	if ((header & 0x000000ff) == PCI_CAP_ID_EXP) {
570 		prk_info("correct val read using PCIE driver installed: 0x%x",
571 			header);
572 		return TPASS;
573 	}
574 
575 	prk_err("incorrect val read. PCIE driver/device not installed: 0x%x",
576 		header);
577 	return TFAIL;
578 }
579 
test_case(unsigned int cmd)580 static int test_case(unsigned int cmd)
581 {
582 	int rc = TSKIP;
583 
584 	switch (cmd) {
585 	case PCI_ENABLE:
586 		rc = pci_enable();
587 		break;
588 	case PCI_DISABLE:
589 		rc = pci_disable();
590 		break;
591 	case FIND_BUS:
592 		rc = test_find_bus();
593 		break;
594 	case FIND_CLASS:
595 		rc = test_find_class();
596 		break;
597 	case FIND_DEVICE:
598 		rc = test_find_device();
599 		break;
600 	case FIND_SUBSYS:
601 		rc = test_find_subsys();
602 		break;
603 	case BUS_SCAN:
604 		rc = test_scan_bus();
605 		break;
606 	case SLOT_SCAN:
607 		rc = test_slot_scan();
608 		break;
609 	case BUS_ADD_DEVICES:
610 		rc = test_bus_add_devices();
611 		break;
612 	case ENABLE_BRIDGES:
613 		rc = test_enable_bridges();
614 		break;
615 	case MATCH_DEVICE:
616 		rc = test_match_device();
617 		break;
618 	case REG_DRIVER:
619 		rc = test_reg_driver();
620 		break;
621 	case UNREG_DRIVER:
622 		rc = test_unreg_driver();
623 		break;
624 	case PCI_RESOURCES:
625 		rc = test_assign_resources();
626 		break;
627 	case SAVE_STATE:
628 		rc = test_save_state();
629 		break;
630 	case RESTORE_STATE:
631 		rc = test_restore_state();
632 		break;
633 	case FIND_CAP:
634 		rc = test_find_cap();
635 		break;
636 	case PCI_EXP_CAP_CONFIG:
637 		rc = test_read_pci_exp_config();
638 		break;
639 	default:
640 		prk_info("mismatching test-case command %d", cmd);
641 		break;
642 	}
643 
644 	return rc;
645 }
646 
647 /*
648  * Test-case result,
649  * if test is passed, value will be set to 0
650  */
651 static int test_result;
652 
device_release(struct device * dev)653 static void device_release(struct device *dev)
654 {
655 	prk_info("device released\n");
656 }
657 
658 static struct device tdev = {
659 	.init_name	= PCI_DEVICE_NAME,
660 	.release	= device_release,
661 };
662 
663 /* print test result to sysfs file */
sys_result(struct device * dev,struct device_attribute * attr,char * buf)664 static ssize_t sys_result(struct device *dev,
665 	struct device_attribute *attr, char *buf)
666 {
667 	return scnprintf(buf, PAGE_SIZE, "%d\n", test_result);
668 }
669 static DEVICE_ATTR(result, S_IRUSR, sys_result, NULL);
670 
sys_tcase(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)671 static ssize_t sys_tcase(struct device *dev,
672 	struct device_attribute *attr,  const char *buf, size_t count)
673 {
674 	int tc = 0;
675 
676 	sscanf(buf, "%d", &tc);
677 	prk_info("test-case %d", tc);
678 
679 	test_result = test_case(tc);
680 
681 	return count;
682 }
683 static DEVICE_ATTR(tcase, S_IWUSR, NULL, sys_tcase);
684 
sys_bus_slot(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)685 static ssize_t sys_bus_slot(struct device *dev,
686 	struct device_attribute *attr,  const char *buf, size_t count)
687 {
688 	unsigned int res, bus, slot;
689 	int ret;
690 
691 	sscanf(buf, "%u", &res);
692 
693 	bus = res >> 8 & 0xFF;
694 	slot = res & 0xFF;
695 
696 	ret = probe_pci_dev(bus, slot);
697 	if (ret)
698 		return ret;
699 
700 	return count;
701 }
702 static DEVICE_ATTR(bus_slot, S_IWUSR, NULL, sys_bus_slot);
703 
tpci_init_module(void)704 static int tpci_init_module(void)
705 {
706 	int err = 0;
707 	prk_info("Starting module");
708 
709 	err = device_register(&tdev);
710 	if (err) {
711 		prk_err("Unable to register device");
712 		goto err0;
713 	}
714 	prk_info("device registered\n");
715 
716 	err = device_create_file(&tdev, &dev_attr_result);
717 	if (err) {
718 		prk_err("Can't create sysfs file 'result'");
719 		goto err1;
720 	}
721 
722 	err = device_create_file(&tdev, &dev_attr_tcase);
723 	if (err) {
724 		prk_err(": Can't create sysfs file 'tc'");
725 		goto err2;
726 	}
727 
728 	err = device_create_file(&tdev, &dev_attr_bus_slot);
729 	if (err) {
730 		prk_err(": Can't create sysfs file 'bus_slot'");
731 		goto err3;
732 	}
733 
734 	return 0;
735 
736 err3:
737 	device_remove_file(&tdev, &dev_attr_tcase);
738 err2:
739 	device_remove_file(&tdev, &dev_attr_result);
740 err1:
741 	device_unregister(&tdev);
742 err0:
743 	return err;
744 }
module_init(tpci_init_module)745 module_init(tpci_init_module)
746 
747 static void tpci_exit_module(void)
748 {
749 	prk_debug("Unloading module\n");
750 	if (ltp_pci.dev)
751 		pci_dev_put(ltp_pci.dev);
752 
753 	if (pci_registered)
754 		pci_unregister_driver(&ltp_pci_driver);
755 
756 	device_remove_file(&tdev, &dev_attr_result);
757 	device_remove_file(&tdev, &dev_attr_tcase);
758 	device_remove_file(&tdev, &dev_attr_bus_slot);
759 	device_unregister(&tdev);
760 }
761 module_exit(tpci_exit_module)
762