1 /** 2 * Host side test driver to test endpoint functionality 3 * 4 * Copyright (C) 2017 Texas Instruments 5 * Author: Kishon Vijay Abraham I <kishon@ti.com> 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 of 9 * the License as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include <linux/crc32.h> 21 #include <linux/delay.h> 22 #include <linux/fs.h> 23 #include <linux/io.h> 24 #include <linux/interrupt.h> 25 #include <linux/irq.h> 26 #include <linux/miscdevice.h> 27 #include <linux/module.h> 28 #include <linux/mutex.h> 29 #include <linux/random.h> 30 #include <linux/slab.h> 31 #include <linux/pci.h> 32 #include <linux/pci_ids.h> 33 34 #include <linux/pci_regs.h> 35 36 #include <uapi/linux/pcitest.h> 37 38 #define DRV_MODULE_NAME "pci-endpoint-test" 39 40 #define PCI_ENDPOINT_TEST_MAGIC 0x0 41 42 #define PCI_ENDPOINT_TEST_COMMAND 0x4 43 #define COMMAND_RAISE_LEGACY_IRQ BIT(0) 44 #define COMMAND_RAISE_MSI_IRQ BIT(1) 45 #define MSI_NUMBER_SHIFT 2 46 /* 6 bits for MSI number */ 47 #define COMMAND_READ BIT(8) 48 #define COMMAND_WRITE BIT(9) 49 #define COMMAND_COPY BIT(10) 50 51 #define PCI_ENDPOINT_TEST_STATUS 0x8 52 #define STATUS_READ_SUCCESS BIT(0) 53 #define STATUS_READ_FAIL BIT(1) 54 #define STATUS_WRITE_SUCCESS BIT(2) 55 #define STATUS_WRITE_FAIL BIT(3) 56 #define STATUS_COPY_SUCCESS BIT(4) 57 #define STATUS_COPY_FAIL BIT(5) 58 #define STATUS_IRQ_RAISED BIT(6) 59 #define STATUS_SRC_ADDR_INVALID BIT(7) 60 #define STATUS_DST_ADDR_INVALID BIT(8) 61 62 #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0xc 63 #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10 64 65 #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14 66 #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18 67 68 #define PCI_ENDPOINT_TEST_SIZE 0x1c 69 #define PCI_ENDPOINT_TEST_CHECKSUM 0x20 70 71 static DEFINE_IDA(pci_endpoint_test_ida); 72 73 #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \ 74 miscdev) 75 76 static bool no_msi; 77 module_param(no_msi, bool, 0444); 78 MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test"); 79 80 enum pci_barno { 81 BAR_0, 82 BAR_1, 83 BAR_2, 84 BAR_3, 85 BAR_4, 86 BAR_5, 87 }; 88 89 struct pci_endpoint_test { 90 struct pci_dev *pdev; 91 void __iomem *base; 92 void __iomem *bar[6]; 93 struct completion irq_raised; 94 int last_irq; 95 /* mutex to protect the ioctls */ 96 struct mutex mutex; 97 struct miscdevice miscdev; 98 enum pci_barno test_reg_bar; 99 size_t alignment; 100 }; 101 102 struct pci_endpoint_test_data { 103 enum pci_barno test_reg_bar; 104 size_t alignment; 105 bool no_msi; 106 }; 107 108 static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test, 109 u32 offset) 110 { 111 return readl(test->base + offset); 112 } 113 114 static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test, 115 u32 offset, u32 value) 116 { 117 writel(value, test->base + offset); 118 } 119 120 static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test *test, 121 int bar, int offset) 122 { 123 return readl(test->bar[bar] + offset); 124 } 125 126 static inline void pci_endpoint_test_bar_writel(struct pci_endpoint_test *test, 127 int bar, u32 offset, u32 value) 128 { 129 writel(value, test->bar[bar] + offset); 130 } 131 132 static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id) 133 { 134 struct pci_endpoint_test *test = dev_id; 135 u32 reg; 136 137 reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); 138 if (reg & STATUS_IRQ_RAISED) { 139 test->last_irq = irq; 140 complete(&test->irq_raised); 141 reg &= ~STATUS_IRQ_RAISED; 142 } 143 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS, 144 reg); 145 146 return IRQ_HANDLED; 147 } 148 149 static bool pci_endpoint_test_bar(struct pci_endpoint_test *test, 150 enum pci_barno barno) 151 { 152 int j; 153 u32 val; 154 int size; 155 struct pci_dev *pdev = test->pdev; 156 157 if (!test->bar[barno]) 158 return false; 159 160 size = pci_resource_len(pdev, barno); 161 162 if (barno == test->test_reg_bar) 163 size = 0x4; 164 165 for (j = 0; j < size; j += 4) 166 pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0); 167 168 for (j = 0; j < size; j += 4) { 169 val = pci_endpoint_test_bar_readl(test, barno, j); 170 if (val != 0xA0A0A0A0) 171 return false; 172 } 173 174 return true; 175 } 176 177 static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test) 178 { 179 u32 val; 180 181 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 182 COMMAND_RAISE_LEGACY_IRQ); 183 val = wait_for_completion_timeout(&test->irq_raised, 184 msecs_to_jiffies(1000)); 185 if (!val) 186 return false; 187 188 return true; 189 } 190 191 static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, 192 u8 msi_num) 193 { 194 u32 val; 195 struct pci_dev *pdev = test->pdev; 196 197 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 198 msi_num << MSI_NUMBER_SHIFT | 199 COMMAND_RAISE_MSI_IRQ); 200 val = wait_for_completion_timeout(&test->irq_raised, 201 msecs_to_jiffies(1000)); 202 if (!val) 203 return false; 204 205 if (test->last_irq - pdev->irq == msi_num - 1) 206 return true; 207 208 return false; 209 } 210 211 static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) 212 { 213 bool ret = false; 214 void *src_addr; 215 void *dst_addr; 216 dma_addr_t src_phys_addr; 217 dma_addr_t dst_phys_addr; 218 struct pci_dev *pdev = test->pdev; 219 struct device *dev = &pdev->dev; 220 void *orig_src_addr; 221 dma_addr_t orig_src_phys_addr; 222 void *orig_dst_addr; 223 dma_addr_t orig_dst_phys_addr; 224 size_t offset; 225 size_t alignment = test->alignment; 226 u32 src_crc32; 227 u32 dst_crc32; 228 229 orig_src_addr = dma_alloc_coherent(dev, size + alignment, 230 &orig_src_phys_addr, GFP_KERNEL); 231 if (!orig_src_addr) { 232 dev_err(dev, "failed to allocate source buffer\n"); 233 ret = false; 234 goto err; 235 } 236 237 if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) { 238 src_phys_addr = PTR_ALIGN(orig_src_phys_addr, alignment); 239 offset = src_phys_addr - orig_src_phys_addr; 240 src_addr = orig_src_addr + offset; 241 } else { 242 src_phys_addr = orig_src_phys_addr; 243 src_addr = orig_src_addr; 244 } 245 246 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR, 247 lower_32_bits(src_phys_addr)); 248 249 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR, 250 upper_32_bits(src_phys_addr)); 251 252 get_random_bytes(src_addr, size); 253 src_crc32 = crc32_le(~0, src_addr, size); 254 255 orig_dst_addr = dma_alloc_coherent(dev, size + alignment, 256 &orig_dst_phys_addr, GFP_KERNEL); 257 if (!orig_dst_addr) { 258 dev_err(dev, "failed to allocate destination address\n"); 259 ret = false; 260 goto err_orig_src_addr; 261 } 262 263 if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) { 264 dst_phys_addr = PTR_ALIGN(orig_dst_phys_addr, alignment); 265 offset = dst_phys_addr - orig_dst_phys_addr; 266 dst_addr = orig_dst_addr + offset; 267 } else { 268 dst_phys_addr = orig_dst_phys_addr; 269 dst_addr = orig_dst_addr; 270 } 271 272 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR, 273 lower_32_bits(dst_phys_addr)); 274 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR, 275 upper_32_bits(dst_phys_addr)); 276 277 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, 278 size); 279 280 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 281 1 << MSI_NUMBER_SHIFT | COMMAND_COPY); 282 283 wait_for_completion(&test->irq_raised); 284 285 dst_crc32 = crc32_le(~0, dst_addr, size); 286 if (dst_crc32 == src_crc32) 287 ret = true; 288 289 dma_free_coherent(dev, size + alignment, orig_dst_addr, 290 orig_dst_phys_addr); 291 292 err_orig_src_addr: 293 dma_free_coherent(dev, size + alignment, orig_src_addr, 294 orig_src_phys_addr); 295 296 err: 297 return ret; 298 } 299 300 static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size) 301 { 302 bool ret = false; 303 u32 reg; 304 void *addr; 305 dma_addr_t phys_addr; 306 struct pci_dev *pdev = test->pdev; 307 struct device *dev = &pdev->dev; 308 void *orig_addr; 309 dma_addr_t orig_phys_addr; 310 size_t offset; 311 size_t alignment = test->alignment; 312 u32 crc32; 313 314 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, 315 GFP_KERNEL); 316 if (!orig_addr) { 317 dev_err(dev, "failed to allocate address\n"); 318 ret = false; 319 goto err; 320 } 321 322 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) { 323 phys_addr = PTR_ALIGN(orig_phys_addr, alignment); 324 offset = phys_addr - orig_phys_addr; 325 addr = orig_addr + offset; 326 } else { 327 phys_addr = orig_phys_addr; 328 addr = orig_addr; 329 } 330 331 get_random_bytes(addr, size); 332 333 crc32 = crc32_le(~0, addr, size); 334 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_CHECKSUM, 335 crc32); 336 337 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR, 338 lower_32_bits(phys_addr)); 339 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR, 340 upper_32_bits(phys_addr)); 341 342 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); 343 344 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 345 1 << MSI_NUMBER_SHIFT | COMMAND_READ); 346 347 wait_for_completion(&test->irq_raised); 348 349 reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); 350 if (reg & STATUS_READ_SUCCESS) 351 ret = true; 352 353 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr); 354 355 err: 356 return ret; 357 } 358 359 static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size) 360 { 361 bool ret = false; 362 void *addr; 363 dma_addr_t phys_addr; 364 struct pci_dev *pdev = test->pdev; 365 struct device *dev = &pdev->dev; 366 void *orig_addr; 367 dma_addr_t orig_phys_addr; 368 size_t offset; 369 size_t alignment = test->alignment; 370 u32 crc32; 371 372 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, 373 GFP_KERNEL); 374 if (!orig_addr) { 375 dev_err(dev, "failed to allocate destination address\n"); 376 ret = false; 377 goto err; 378 } 379 380 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) { 381 phys_addr = PTR_ALIGN(orig_phys_addr, alignment); 382 offset = phys_addr - orig_phys_addr; 383 addr = orig_addr + offset; 384 } else { 385 phys_addr = orig_phys_addr; 386 addr = orig_addr; 387 } 388 389 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR, 390 lower_32_bits(phys_addr)); 391 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR, 392 upper_32_bits(phys_addr)); 393 394 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); 395 396 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 397 1 << MSI_NUMBER_SHIFT | COMMAND_WRITE); 398 399 wait_for_completion(&test->irq_raised); 400 401 crc32 = crc32_le(~0, addr, size); 402 if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM)) 403 ret = true; 404 405 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr); 406 err: 407 return ret; 408 } 409 410 static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, 411 unsigned long arg) 412 { 413 int ret = -EINVAL; 414 enum pci_barno bar; 415 struct pci_endpoint_test *test = to_endpoint_test(file->private_data); 416 417 mutex_lock(&test->mutex); 418 switch (cmd) { 419 case PCITEST_BAR: 420 bar = arg; 421 if (bar < 0 || bar > 5) 422 goto ret; 423 ret = pci_endpoint_test_bar(test, bar); 424 break; 425 case PCITEST_LEGACY_IRQ: 426 ret = pci_endpoint_test_legacy_irq(test); 427 break; 428 case PCITEST_MSI: 429 ret = pci_endpoint_test_msi_irq(test, arg); 430 break; 431 case PCITEST_WRITE: 432 ret = pci_endpoint_test_write(test, arg); 433 break; 434 case PCITEST_READ: 435 ret = pci_endpoint_test_read(test, arg); 436 break; 437 case PCITEST_COPY: 438 ret = pci_endpoint_test_copy(test, arg); 439 break; 440 } 441 442 ret: 443 mutex_unlock(&test->mutex); 444 return ret; 445 } 446 447 static const struct file_operations pci_endpoint_test_fops = { 448 .owner = THIS_MODULE, 449 .unlocked_ioctl = pci_endpoint_test_ioctl, 450 }; 451 452 static int pci_endpoint_test_probe(struct pci_dev *pdev, 453 const struct pci_device_id *ent) 454 { 455 int i; 456 int err; 457 int irq = 0; 458 int id; 459 char name[20]; 460 enum pci_barno bar; 461 void __iomem *base; 462 struct device *dev = &pdev->dev; 463 struct pci_endpoint_test *test; 464 struct pci_endpoint_test_data *data; 465 enum pci_barno test_reg_bar = BAR_0; 466 struct miscdevice *misc_device; 467 468 if (pci_is_bridge(pdev)) 469 return -ENODEV; 470 471 test = devm_kzalloc(dev, sizeof(*test), GFP_KERNEL); 472 if (!test) 473 return -ENOMEM; 474 475 test->test_reg_bar = 0; 476 test->alignment = 0; 477 test->pdev = pdev; 478 479 data = (struct pci_endpoint_test_data *)ent->driver_data; 480 if (data) { 481 test_reg_bar = data->test_reg_bar; 482 test->alignment = data->alignment; 483 no_msi = data->no_msi; 484 } 485 486 init_completion(&test->irq_raised); 487 mutex_init(&test->mutex); 488 489 err = pci_enable_device(pdev); 490 if (err) { 491 dev_err(dev, "Cannot enable PCI device\n"); 492 return err; 493 } 494 495 err = pci_request_regions(pdev, DRV_MODULE_NAME); 496 if (err) { 497 dev_err(dev, "Cannot obtain PCI resources\n"); 498 goto err_disable_pdev; 499 } 500 501 pci_set_master(pdev); 502 503 if (!no_msi) { 504 irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); 505 if (irq < 0) 506 dev_err(dev, "failed to get MSI interrupts\n"); 507 } 508 509 err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, 510 IRQF_SHARED, DRV_MODULE_NAME, test); 511 if (err) { 512 dev_err(dev, "failed to request IRQ %d\n", pdev->irq); 513 goto err_disable_msi; 514 } 515 516 for (i = 1; i < irq; i++) { 517 err = devm_request_irq(dev, pdev->irq + i, 518 pci_endpoint_test_irqhandler, 519 IRQF_SHARED, DRV_MODULE_NAME, test); 520 if (err) 521 dev_err(dev, "failed to request IRQ %d for MSI %d\n", 522 pdev->irq + i, i + 1); 523 } 524 525 for (bar = BAR_0; bar <= BAR_5; bar++) { 526 base = pci_ioremap_bar(pdev, bar); 527 if (!base) { 528 dev_err(dev, "failed to read BAR%d\n", bar); 529 WARN_ON(bar == test_reg_bar); 530 } 531 test->bar[bar] = base; 532 } 533 534 test->base = test->bar[test_reg_bar]; 535 if (!test->base) { 536 dev_err(dev, "Cannot perform PCI test without BAR%d\n", 537 test_reg_bar); 538 goto err_iounmap; 539 } 540 541 pci_set_drvdata(pdev, test); 542 543 id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL); 544 if (id < 0) { 545 dev_err(dev, "unable to get id\n"); 546 goto err_iounmap; 547 } 548 549 snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id); 550 misc_device = &test->miscdev; 551 misc_device->minor = MISC_DYNAMIC_MINOR; 552 misc_device->name = name; 553 misc_device->fops = &pci_endpoint_test_fops, 554 555 err = misc_register(misc_device); 556 if (err) { 557 dev_err(dev, "failed to register device\n"); 558 goto err_ida_remove; 559 } 560 561 return 0; 562 563 err_ida_remove: 564 ida_simple_remove(&pci_endpoint_test_ida, id); 565 566 err_iounmap: 567 for (bar = BAR_0; bar <= BAR_5; bar++) { 568 if (test->bar[bar]) 569 pci_iounmap(pdev, test->bar[bar]); 570 } 571 572 err_disable_msi: 573 pci_disable_msi(pdev); 574 pci_release_regions(pdev); 575 576 err_disable_pdev: 577 pci_disable_device(pdev); 578 579 return err; 580 } 581 582 static void pci_endpoint_test_remove(struct pci_dev *pdev) 583 { 584 int id; 585 enum pci_barno bar; 586 struct pci_endpoint_test *test = pci_get_drvdata(pdev); 587 struct miscdevice *misc_device = &test->miscdev; 588 589 if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1) 590 return; 591 592 misc_deregister(&test->miscdev); 593 ida_simple_remove(&pci_endpoint_test_ida, id); 594 for (bar = BAR_0; bar <= BAR_5; bar++) { 595 if (test->bar[bar]) 596 pci_iounmap(pdev, test->bar[bar]); 597 } 598 pci_disable_msi(pdev); 599 pci_release_regions(pdev); 600 pci_disable_device(pdev); 601 } 602 603 static const struct pci_device_id pci_endpoint_test_tbl[] = { 604 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x) }, 605 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x) }, 606 { } 607 }; 608 MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl); 609 610 static struct pci_driver pci_endpoint_test_driver = { 611 .name = DRV_MODULE_NAME, 612 .id_table = pci_endpoint_test_tbl, 613 .probe = pci_endpoint_test_probe, 614 .remove = pci_endpoint_test_remove, 615 }; 616 module_pci_driver(pci_endpoint_test_driver); 617 618 MODULE_DESCRIPTION("PCI ENDPOINT TEST HOST DRIVER"); 619 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); 620 MODULE_LICENSE("GPL v2"); 621