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 const struct pci_device_id 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_domain_bus_and_slot(0, 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 int num;
294 struct pci_bus *bus = ltp_pci.bus;
295
296 prk_info("scan pci bus");
297
298 num = pci_rescan_bus(bus);
299 /*
300 * check if returned number is greater than
301 * max number of bus or less than 0
302 */
303 if (num > MAX_BUS || num < 0) {
304 prk_err("failed scan bus");
305 return TFAIL;
306 }
307 prk_info("success scan bus");
308 return TPASS;
309 }
310
311 /*
312 * test_slot_scan
313 * make call to pci_scan_slot, which will
314 * find the device pointer and setup the
315 * device info
316 */
test_slot_scan(void)317 static int test_slot_scan(void)
318 {
319 int ret, num = ltp_pci.dev->devfn;
320 struct pci_bus *bus = ltp_pci.bus;
321
322 prk_info("scan pci slot");
323
324 if ((num % 8) != 0)
325 return TPASS;
326
327 ret = pci_scan_slot(bus, num);
328 if (ret >= 0) {
329 prk_info("found '%d' devices from scan slot", ret);
330 return TPASS;
331 }
332
333 prk_err("pci_scan_slot failed");
334 return TFAIL;
335 }
336
337 /*
338 * test_bus_add_devices
339 * make call to pci_bus_add_devices,
340 * which will check the device pointer
341 * that is passed in for more devices
342 * that it can add
343 */
test_bus_add_devices(void)344 static int test_bus_add_devices(void)
345 {
346 struct pci_bus *bus = ltp_pci.bus;
347
348 prk_info("add bus device");
349
350 pci_bus_add_devices(bus);
351
352 if (bus) {
353 prk_info("called bus_add_device");
354 return TPASS;
355 }
356
357 prk_err("bus_add_device failed");
358 return TFAIL;
359 }
360
361 /*
362 * test_match_device
363 * make call to pci_match_device, returns a
364 * pci_device_id pointer
365 */
test_match_device(void)366 static int test_match_device(void)
367 {
368 struct pci_dev *dev = ltp_pci.dev;
369 struct pci_driver *drv;
370 const struct pci_device_id *id;
371
372 prk_info("test pci_device_id()");
373
374 drv = pci_dev_driver(dev);
375
376 if (!drv) {
377 prk_err("driver pointer not allocated for pci_dev");
378 return TFAIL;
379 }
380
381 id = pci_match_id(drv->id_table, dev);
382
383 if (id) {
384 prk_info("match device success");
385 return TPASS;
386 }
387
388 prk_err("failed return pci_device_id");
389 return TFAIL;
390 }
391
392
393 /*
394 * test_reg_driver
395 * make call to pci_register_driver, which will
396 * register the driver for a device with the
397 * system
398 */
test_reg_driver(void)399 static int test_reg_driver(void)
400 {
401 prk_info("test pci_register_driver");
402 if (pci_register_driver(<p_pci_driver)) {
403 prk_err("unsuccessful registering pci driver");
404 return TFAIL;
405 }
406 pci_registered = 1;
407 prk_info("success driver register");
408 return TPASS;
409 }
410
411 /*
412 * test_unreg_driver
413 * make call to pci_unregister_driver, which will
414 * unregister the driver for a device from the system
415 */
test_unreg_driver(void)416 static int test_unreg_driver(void)
417 {
418 pci_unregister_driver(<p_pci_driver);
419 pci_registered = 0;
420 return TPASS;
421 }
422
423 /*
424 * test_assign_resources
425 * make calls to pci_assign_resource, will need
426 * to setup a dev pointer and resource pointer,
427 */
test_assign_resources(void)428 static int test_assign_resources(void)
429 {
430 int i, ret, rc = 0;
431 struct pci_dev *dev = ltp_pci.dev;
432 struct resource *r;
433
434 prk_info("assign resources");
435
436 for (i = 0; i < 7; ++i) {
437 prk_info("assign resource #%d", i);
438 r = &dev->resource[i];
439 prk_info("name = %s, flags = %lu, start 0x%lx, end 0x%lx",
440 r->name, r->flags,
441 (unsigned long)r->start, (unsigned long)r->end);
442
443 if (r->flags & IORESOURCE_MEM &&
444 r->flags & IORESOURCE_PREFETCH) {
445 pci_release_resource(dev, i);
446 ret = pci_assign_resource(dev, i);
447 prk_info("assign resource to '%d', ret '%d'", i, ret);
448 rc |= (ret < 0 && ret != -EBUSY) ? TFAIL : TPASS;
449 }
450 }
451
452 /*
453 * enable device after call to assign resource
454 * because might error if (!r->start && r->end)
455 */
456 if (pci_enable_device(dev))
457 return TFAIL;
458
459 return rc;
460 }
461
462 /*
463 * test_save_state
464 * make call to pci_save_state, takes in a u32*
465 * buffer
466 */
test_save_state(void)467 static int test_save_state(void)
468 {
469 struct pci_dev *dev = ltp_pci.dev;
470
471 prk_info("save state");
472
473 if (pci_save_state(dev)) {
474 prk_err("failed save state");
475 return TFAIL;
476 }
477
478 prk_info("saved state of device");
479 return TPASS;
480 }
481
482 /*
483 * test_restore_state
484 * make call to pci_restore_state, get the state buffer
485 * should have been previously filled out by save state
486 */
test_restore_state(void)487 static int test_restore_state(void)
488 {
489 struct pci_dev *dev = ltp_pci.dev;
490
491 prk_info("restore state");
492
493 pci_restore_state(dev);
494
495 return TPASS;
496 }
497
498 /*
499 * test_find_cap
500 * make call to pci_find_capability, which
501 * will determine if a device has a certain
502 * capability, use second parameter to specify
503 * which capability you are looking for
504 */
test_find_cap(void)505 static int test_find_cap(void)
506 {
507 struct pci_dev *dev = ltp_pci.dev;
508
509 prk_info("find device capability");
510
511 if (pci_find_capability(dev, PCI_CAP_ID_PM))
512 prk_info("does not have tested capability");
513 else
514 prk_info("device has PM capability");
515
516 return TPASS;
517 }
518
519 /*
520 * test_read_pci_exp_config
521 * make call to pci_config_read and determine if
522 * the PCI-Express enhanced config space of this
523 * device can be read successfully.
524 */
test_read_pci_exp_config(void)525 static int test_read_pci_exp_config(void)
526 {
527 int pos;
528 u32 header;
529 struct pci_dev *dev = ltp_pci.dev;
530
531 /* skip the test if device doesn't have PCIe capability */
532 pos = pci_pcie_cap(dev);
533 if (!pos) {
534 prk_info("device doesn't have PCI-EXP capability");
535 return TSKIP;
536 }
537 prk_info("read the PCI Express configuration registers at 0x%x", pos);
538
539 if (pci_read_config_dword(dev, pos, &header)) {
540 prk_err("failed to read config dword");
541 return TFAIL;
542 }
543
544 /* comparing the value read with PCI_CAP_ID_EXP macro */
545 if ((header & 0x000000ff) == PCI_CAP_ID_EXP) {
546 prk_info("correct val read using PCIE driver installed: 0x%x",
547 header);
548 return TPASS;
549 }
550
551 prk_err("incorrect val read. PCIE driver/device not installed: 0x%x",
552 header);
553 return TFAIL;
554 }
555
test_case(unsigned int cmd)556 static int test_case(unsigned int cmd)
557 {
558 int rc = TSKIP;
559
560 if (!ltp_pci.dev || !ltp_pci.bus) {
561 prk_err("device or bus not selected for test");
562 return TFAIL;
563 }
564
565 switch (cmd) {
566 case PCI_ENABLE:
567 rc = pci_enable();
568 break;
569 case PCI_DISABLE:
570 rc = pci_disable();
571 break;
572 case FIND_BUS:
573 rc = test_find_bus();
574 break;
575 case FIND_CLASS:
576 rc = test_find_class();
577 break;
578 case FIND_DEVICE:
579 rc = test_find_device();
580 break;
581 case FIND_SUBSYS:
582 rc = test_find_subsys();
583 break;
584 case BUS_SCAN:
585 rc = test_scan_bus();
586 break;
587 case SLOT_SCAN:
588 rc = test_slot_scan();
589 break;
590 case BUS_ADD_DEVICES:
591 rc = test_bus_add_devices();
592 break;
593 case MATCH_DEVICE:
594 rc = test_match_device();
595 break;
596 case REG_DRIVER:
597 rc = test_reg_driver();
598 break;
599 case UNREG_DRIVER:
600 rc = test_unreg_driver();
601 break;
602 case PCI_RESOURCES:
603 rc = test_assign_resources();
604 break;
605 case SAVE_STATE:
606 rc = test_save_state();
607 break;
608 case RESTORE_STATE:
609 rc = test_restore_state();
610 break;
611 case FIND_CAP:
612 rc = test_find_cap();
613 break;
614 case PCI_EXP_CAP_CONFIG:
615 rc = test_read_pci_exp_config();
616 break;
617 default:
618 prk_info("mismatching test-case command %d", cmd);
619 break;
620 }
621
622 return rc;
623 }
624
625 /*
626 * Test-case result,
627 * if test is passed, value will be set to 0
628 */
629 static int test_result;
630
device_release(struct device * dev)631 static void device_release(struct device *dev)
632 {
633 prk_info("device released\n");
634 }
635
636 static struct device tdev = {
637 .init_name = PCI_DEVICE_NAME,
638 .release = device_release,
639 };
640
641 /* print test result to sysfs file */
sys_result(struct device * dev,struct device_attribute * attr,char * buf)642 static ssize_t sys_result(struct device *dev,
643 struct device_attribute *attr, char *buf)
644 {
645 return scnprintf(buf, PAGE_SIZE, "%d\n", test_result);
646 }
647 static DEVICE_ATTR(result, S_IRUSR, sys_result, NULL);
648
sys_tcase(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)649 static ssize_t sys_tcase(struct device *dev,
650 struct device_attribute *attr, const char *buf, size_t count)
651 {
652 int tc = 0;
653
654 sscanf(buf, "%d", &tc);
655 prk_info("test-case %d", tc);
656
657 test_result = test_case(tc);
658
659 return count;
660 }
661 static DEVICE_ATTR(tcase, S_IWUSR, NULL, sys_tcase);
662
sys_bus_slot(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)663 static ssize_t sys_bus_slot(struct device *dev,
664 struct device_attribute *attr, const char *buf, size_t count)
665 {
666 unsigned int res, bus, slot;
667 int ret;
668
669 sscanf(buf, "%u", &res);
670
671 bus = res >> 8 & 0xFF;
672 slot = res & 0xFF;
673
674 ret = probe_pci_dev(bus, slot);
675 if (ret)
676 return ret;
677
678 return count;
679 }
680 static DEVICE_ATTR(bus_slot, S_IWUSR, NULL, sys_bus_slot);
681
tpci_init_module(void)682 static int tpci_init_module(void)
683 {
684 int err = 0;
685 prk_info("Starting module");
686
687 err = device_register(&tdev);
688 if (err) {
689 prk_err("Unable to register device");
690 goto err0;
691 }
692 prk_info("device registered\n");
693
694 err = device_create_file(&tdev, &dev_attr_result);
695 if (err) {
696 prk_err("Can't create sysfs file 'result'");
697 goto err1;
698 }
699
700 err = device_create_file(&tdev, &dev_attr_tcase);
701 if (err) {
702 prk_err(": Can't create sysfs file 'tc'");
703 goto err2;
704 }
705
706 err = device_create_file(&tdev, &dev_attr_bus_slot);
707 if (err) {
708 prk_err(": Can't create sysfs file 'bus_slot'");
709 goto err3;
710 }
711
712 return 0;
713
714 err3:
715 device_remove_file(&tdev, &dev_attr_tcase);
716 err2:
717 device_remove_file(&tdev, &dev_attr_result);
718 err1:
719 device_unregister(&tdev);
720 err0:
721 return err;
722 }
module_init(tpci_init_module)723 module_init(tpci_init_module)
724
725 static void tpci_exit_module(void)
726 {
727 prk_debug("Unloading module\n");
728 if (ltp_pci.dev)
729 pci_dev_put(ltp_pci.dev);
730
731 if (pci_registered)
732 pci_unregister_driver(<p_pci_driver);
733
734 device_remove_file(&tdev, &dev_attr_result);
735 device_remove_file(&tdev, &dev_attr_tcase);
736 device_remove_file(&tdev, &dev_attr_bus_slot);
737 device_unregister(&tdev);
738 }
739 module_exit(tpci_exit_module)
740