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
47MODULE_AUTHOR("Sean Ruyle <srruyle@us.ibm.com>");
48MODULE_AUTHOR("Amit Khanna <amit.khanna@intel.com>");
49MODULE_AUTHOR("Copyright (c) 2013 Oracle and/or its affiliates");
50MODULE_DESCRIPTION("LTP PCI Test");
51MODULE_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
64static DEFINE_PCI_DEVICE_TABLE(ltp_pci_tbl) = {
65	{ PCI_DEVICE(PCI_ANY_ID, PCI_ANY_ID) },
66	{ 0, }
67};
68
69MODULE_DEVICE_TABLE(pci, ltp_pci_tbl);
70
71static int ltp_pci_probe(struct pci_dev *pci_dev,
72	const struct pci_device_id *pci_ent)
73{
74	return 0;
75}
76
77static struct pci_driver ltp_pci_driver = {
78	.name     = "LTP_PCI_DRIVER",
79	.id_table = ltp_pci_tbl,
80	.probe    = ltp_pci_probe,
81};
82
83static int pci_registered;
84
85struct tpci_user {
86	struct pci_dev		*dev;
87	struct pci_bus		*bus;
88	struct pci_driver	*drv;
89	uint32_t		state[16];
90};
91static 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 */
98static 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 */
125static 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
146static 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 */
184static 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 */
210static 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 */
236static 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 */
262static 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 */
291static 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 */
322static 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 */
346static 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 */
369static 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 */
391static 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 */
424static 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 */
441static 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 */
453static 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 */
491static 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 */
511static 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 */
529static 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 */
549static 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
580static 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 */
651static int test_result;
652
653static void device_release(struct device *dev)
654{
655	prk_info("device released\n");
656}
657
658static struct device tdev = {
659	.init_name	= PCI_DEVICE_NAME,
660	.release	= device_release,
661};
662
663/* print test result to sysfs file */
664static 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}
669static DEVICE_ATTR(result, S_IRUSR, sys_result, NULL);
670
671static 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}
683static DEVICE_ATTR(tcase, S_IWUSR, NULL, sys_tcase);
684
685static 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}
702static DEVICE_ATTR(bus_slot, S_IWUSR, NULL, sys_bus_slot);
703
704static 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
736err3:
737	device_remove_file(&tdev, &dev_attr_tcase);
738err2:
739	device_remove_file(&tdev, &dev_attr_result);
740err1:
741	device_unregister(&tdev);
742err0:
743	return err;
744}
745module_init(tpci_init_module)
746
747static 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}
761module_exit(tpci_exit_module)
762