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 IRQ_TYPE_UNDEFINED -1 41 #define IRQ_TYPE_LEGACY 0 42 #define IRQ_TYPE_MSI 1 43 #define IRQ_TYPE_MSIX 2 44 45 #define PCI_ENDPOINT_TEST_MAGIC 0x0 46 47 #define PCI_ENDPOINT_TEST_COMMAND 0x4 48 #define COMMAND_RAISE_LEGACY_IRQ BIT(0) 49 #define COMMAND_RAISE_MSI_IRQ BIT(1) 50 #define COMMAND_RAISE_MSIX_IRQ BIT(2) 51 #define COMMAND_READ BIT(3) 52 #define COMMAND_WRITE BIT(4) 53 #define COMMAND_COPY BIT(5) 54 55 #define PCI_ENDPOINT_TEST_STATUS 0x8 56 #define STATUS_READ_SUCCESS BIT(0) 57 #define STATUS_READ_FAIL BIT(1) 58 #define STATUS_WRITE_SUCCESS BIT(2) 59 #define STATUS_WRITE_FAIL BIT(3) 60 #define STATUS_COPY_SUCCESS BIT(4) 61 #define STATUS_COPY_FAIL BIT(5) 62 #define STATUS_IRQ_RAISED BIT(6) 63 #define STATUS_SRC_ADDR_INVALID BIT(7) 64 #define STATUS_DST_ADDR_INVALID BIT(8) 65 66 #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0x0c 67 #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10 68 69 #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14 70 #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18 71 72 #define PCI_ENDPOINT_TEST_SIZE 0x1c 73 #define PCI_ENDPOINT_TEST_CHECKSUM 0x20 74 75 #define PCI_ENDPOINT_TEST_IRQ_TYPE 0x24 76 #define PCI_ENDPOINT_TEST_IRQ_NUMBER 0x28 77 78 #define PCI_DEVICE_ID_TI_AM654 0xb00c 79 80 #define is_am654_pci_dev(pdev) \ 81 ((pdev)->device == PCI_DEVICE_ID_TI_AM654) 82 83 static DEFINE_IDA(pci_endpoint_test_ida); 84 85 #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \ 86 miscdev) 87 88 static bool no_msi; 89 module_param(no_msi, bool, 0444); 90 MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test"); 91 92 static int irq_type = IRQ_TYPE_MSI; 93 module_param(irq_type, int, 0444); 94 MODULE_PARM_DESC(irq_type, "IRQ mode selection in pci_endpoint_test (0 - Legacy, 1 - MSI, 2 - MSI-X)"); 95 96 enum pci_barno { 97 BAR_0, 98 BAR_1, 99 BAR_2, 100 BAR_3, 101 BAR_4, 102 BAR_5, 103 }; 104 105 struct pci_endpoint_test { 106 struct pci_dev *pdev; 107 void __iomem *base; 108 void __iomem *bar[6]; 109 struct completion irq_raised; 110 int last_irq; 111 int num_irqs; 112 /* mutex to protect the ioctls */ 113 struct mutex mutex; 114 struct miscdevice miscdev; 115 enum pci_barno test_reg_bar; 116 size_t alignment; 117 }; 118 119 struct pci_endpoint_test_data { 120 enum pci_barno test_reg_bar; 121 size_t alignment; 122 int irq_type; 123 }; 124 125 static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test, 126 u32 offset) 127 { 128 return readl(test->base + offset); 129 } 130 131 static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test, 132 u32 offset, u32 value) 133 { 134 writel(value, test->base + offset); 135 } 136 137 static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test *test, 138 int bar, int offset) 139 { 140 return readl(test->bar[bar] + offset); 141 } 142 143 static inline void pci_endpoint_test_bar_writel(struct pci_endpoint_test *test, 144 int bar, u32 offset, u32 value) 145 { 146 writel(value, test->bar[bar] + offset); 147 } 148 149 static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id) 150 { 151 struct pci_endpoint_test *test = dev_id; 152 u32 reg; 153 154 reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); 155 if (reg & STATUS_IRQ_RAISED) { 156 test->last_irq = irq; 157 complete(&test->irq_raised); 158 reg &= ~STATUS_IRQ_RAISED; 159 } 160 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS, 161 reg); 162 163 return IRQ_HANDLED; 164 } 165 166 static void pci_endpoint_test_free_irq_vectors(struct pci_endpoint_test *test) 167 { 168 struct pci_dev *pdev = test->pdev; 169 170 pci_free_irq_vectors(pdev); 171 } 172 173 static bool pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test, 174 int type) 175 { 176 int irq = -1; 177 struct pci_dev *pdev = test->pdev; 178 struct device *dev = &pdev->dev; 179 bool res = true; 180 181 switch (type) { 182 case IRQ_TYPE_LEGACY: 183 irq = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_LEGACY); 184 if (irq < 0) 185 dev_err(dev, "Failed to get Legacy interrupt\n"); 186 break; 187 case IRQ_TYPE_MSI: 188 irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); 189 if (irq < 0) 190 dev_err(dev, "Failed to get MSI interrupts\n"); 191 break; 192 case IRQ_TYPE_MSIX: 193 irq = pci_alloc_irq_vectors(pdev, 1, 2048, PCI_IRQ_MSIX); 194 if (irq < 0) 195 dev_err(dev, "Failed to get MSI-X interrupts\n"); 196 break; 197 default: 198 dev_err(dev, "Invalid IRQ type selected\n"); 199 } 200 201 if (irq < 0) { 202 irq = 0; 203 res = false; 204 } 205 test->num_irqs = irq; 206 207 return res; 208 } 209 210 static void pci_endpoint_test_release_irq(struct pci_endpoint_test *test) 211 { 212 int i; 213 struct pci_dev *pdev = test->pdev; 214 struct device *dev = &pdev->dev; 215 216 for (i = 0; i < test->num_irqs; i++) 217 devm_free_irq(dev, pci_irq_vector(pdev, i), test); 218 219 test->num_irqs = 0; 220 } 221 222 static bool pci_endpoint_test_request_irq(struct pci_endpoint_test *test) 223 { 224 int i; 225 int err; 226 struct pci_dev *pdev = test->pdev; 227 struct device *dev = &pdev->dev; 228 229 for (i = 0; i < test->num_irqs; i++) { 230 err = devm_request_irq(dev, pci_irq_vector(pdev, i), 231 pci_endpoint_test_irqhandler, 232 IRQF_SHARED, DRV_MODULE_NAME, test); 233 if (err) 234 goto fail; 235 } 236 237 return true; 238 239 fail: 240 switch (irq_type) { 241 case IRQ_TYPE_LEGACY: 242 dev_err(dev, "Failed to request IRQ %d for Legacy\n", 243 pci_irq_vector(pdev, i)); 244 break; 245 case IRQ_TYPE_MSI: 246 dev_err(dev, "Failed to request IRQ %d for MSI %d\n", 247 pci_irq_vector(pdev, i), 248 i + 1); 249 break; 250 case IRQ_TYPE_MSIX: 251 dev_err(dev, "Failed to request IRQ %d for MSI-X %d\n", 252 pci_irq_vector(pdev, i), 253 i + 1); 254 break; 255 } 256 257 return false; 258 } 259 260 static bool pci_endpoint_test_bar(struct pci_endpoint_test *test, 261 enum pci_barno barno) 262 { 263 int j; 264 u32 val; 265 int size; 266 struct pci_dev *pdev = test->pdev; 267 268 if (!test->bar[barno]) 269 return false; 270 271 size = pci_resource_len(pdev, barno); 272 273 if (barno == test->test_reg_bar) 274 size = 0x4; 275 276 for (j = 0; j < size; j += 4) 277 pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0); 278 279 for (j = 0; j < size; j += 4) { 280 val = pci_endpoint_test_bar_readl(test, barno, j); 281 if (val != 0xA0A0A0A0) 282 return false; 283 } 284 285 return true; 286 } 287 288 static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test) 289 { 290 u32 val; 291 292 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, 293 IRQ_TYPE_LEGACY); 294 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 0); 295 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 296 COMMAND_RAISE_LEGACY_IRQ); 297 val = wait_for_completion_timeout(&test->irq_raised, 298 msecs_to_jiffies(1000)); 299 if (!val) 300 return false; 301 302 return true; 303 } 304 305 static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, 306 u16 msi_num, bool msix) 307 { 308 u32 val; 309 struct pci_dev *pdev = test->pdev; 310 311 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, 312 msix == false ? IRQ_TYPE_MSI : 313 IRQ_TYPE_MSIX); 314 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, msi_num); 315 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 316 msix == false ? COMMAND_RAISE_MSI_IRQ : 317 COMMAND_RAISE_MSIX_IRQ); 318 val = wait_for_completion_timeout(&test->irq_raised, 319 msecs_to_jiffies(1000)); 320 if (!val) 321 return false; 322 323 if (pci_irq_vector(pdev, msi_num - 1) == test->last_irq) 324 return true; 325 326 return false; 327 } 328 329 static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) 330 { 331 bool ret = false; 332 void *src_addr; 333 void *dst_addr; 334 dma_addr_t src_phys_addr; 335 dma_addr_t dst_phys_addr; 336 struct pci_dev *pdev = test->pdev; 337 struct device *dev = &pdev->dev; 338 void *orig_src_addr; 339 dma_addr_t orig_src_phys_addr; 340 void *orig_dst_addr; 341 dma_addr_t orig_dst_phys_addr; 342 size_t offset; 343 size_t alignment = test->alignment; 344 u32 src_crc32; 345 u32 dst_crc32; 346 347 if (size > SIZE_MAX - alignment) 348 goto err; 349 350 if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { 351 dev_err(dev, "Invalid IRQ type option\n"); 352 goto err; 353 } 354 355 orig_src_addr = dma_alloc_coherent(dev, size + alignment, 356 &orig_src_phys_addr, GFP_KERNEL); 357 if (!orig_src_addr) { 358 dev_err(dev, "Failed to allocate source buffer\n"); 359 ret = false; 360 goto err; 361 } 362 363 if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) { 364 src_phys_addr = PTR_ALIGN(orig_src_phys_addr, alignment); 365 offset = src_phys_addr - orig_src_phys_addr; 366 src_addr = orig_src_addr + offset; 367 } else { 368 src_phys_addr = orig_src_phys_addr; 369 src_addr = orig_src_addr; 370 } 371 372 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR, 373 lower_32_bits(src_phys_addr)); 374 375 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR, 376 upper_32_bits(src_phys_addr)); 377 378 get_random_bytes(src_addr, size); 379 src_crc32 = crc32_le(~0, src_addr, size); 380 381 orig_dst_addr = dma_alloc_coherent(dev, size + alignment, 382 &orig_dst_phys_addr, GFP_KERNEL); 383 if (!orig_dst_addr) { 384 dev_err(dev, "Failed to allocate destination address\n"); 385 ret = false; 386 goto err_orig_src_addr; 387 } 388 389 if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) { 390 dst_phys_addr = PTR_ALIGN(orig_dst_phys_addr, alignment); 391 offset = dst_phys_addr - orig_dst_phys_addr; 392 dst_addr = orig_dst_addr + offset; 393 } else { 394 dst_phys_addr = orig_dst_phys_addr; 395 dst_addr = orig_dst_addr; 396 } 397 398 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR, 399 lower_32_bits(dst_phys_addr)); 400 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR, 401 upper_32_bits(dst_phys_addr)); 402 403 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, 404 size); 405 406 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); 407 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); 408 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 409 COMMAND_COPY); 410 411 wait_for_completion(&test->irq_raised); 412 413 dst_crc32 = crc32_le(~0, dst_addr, size); 414 if (dst_crc32 == src_crc32) 415 ret = true; 416 417 dma_free_coherent(dev, size + alignment, orig_dst_addr, 418 orig_dst_phys_addr); 419 420 err_orig_src_addr: 421 dma_free_coherent(dev, size + alignment, orig_src_addr, 422 orig_src_phys_addr); 423 424 err: 425 return ret; 426 } 427 428 static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size) 429 { 430 bool ret = false; 431 u32 reg; 432 void *addr; 433 dma_addr_t phys_addr; 434 struct pci_dev *pdev = test->pdev; 435 struct device *dev = &pdev->dev; 436 void *orig_addr; 437 dma_addr_t orig_phys_addr; 438 size_t offset; 439 size_t alignment = test->alignment; 440 u32 crc32; 441 442 if (size > SIZE_MAX - alignment) 443 goto err; 444 445 if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { 446 dev_err(dev, "Invalid IRQ type option\n"); 447 goto err; 448 } 449 450 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, 451 GFP_KERNEL); 452 if (!orig_addr) { 453 dev_err(dev, "Failed to allocate address\n"); 454 ret = false; 455 goto err; 456 } 457 458 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) { 459 phys_addr = PTR_ALIGN(orig_phys_addr, alignment); 460 offset = phys_addr - orig_phys_addr; 461 addr = orig_addr + offset; 462 } else { 463 phys_addr = orig_phys_addr; 464 addr = orig_addr; 465 } 466 467 get_random_bytes(addr, size); 468 469 crc32 = crc32_le(~0, addr, size); 470 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_CHECKSUM, 471 crc32); 472 473 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR, 474 lower_32_bits(phys_addr)); 475 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR, 476 upper_32_bits(phys_addr)); 477 478 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); 479 480 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); 481 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); 482 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 483 COMMAND_READ); 484 485 wait_for_completion(&test->irq_raised); 486 487 reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); 488 if (reg & STATUS_READ_SUCCESS) 489 ret = true; 490 491 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr); 492 493 err: 494 return ret; 495 } 496 497 static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size) 498 { 499 bool ret = false; 500 void *addr; 501 dma_addr_t phys_addr; 502 struct pci_dev *pdev = test->pdev; 503 struct device *dev = &pdev->dev; 504 void *orig_addr; 505 dma_addr_t orig_phys_addr; 506 size_t offset; 507 size_t alignment = test->alignment; 508 u32 crc32; 509 510 if (size > SIZE_MAX - alignment) 511 goto err; 512 513 if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { 514 dev_err(dev, "Invalid IRQ type option\n"); 515 goto err; 516 } 517 518 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, 519 GFP_KERNEL); 520 if (!orig_addr) { 521 dev_err(dev, "Failed to allocate destination address\n"); 522 ret = false; 523 goto err; 524 } 525 526 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) { 527 phys_addr = PTR_ALIGN(orig_phys_addr, alignment); 528 offset = phys_addr - orig_phys_addr; 529 addr = orig_addr + offset; 530 } else { 531 phys_addr = orig_phys_addr; 532 addr = orig_addr; 533 } 534 535 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR, 536 lower_32_bits(phys_addr)); 537 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR, 538 upper_32_bits(phys_addr)); 539 540 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); 541 542 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); 543 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); 544 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 545 COMMAND_WRITE); 546 547 wait_for_completion(&test->irq_raised); 548 549 crc32 = crc32_le(~0, addr, size); 550 if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM)) 551 ret = true; 552 553 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr); 554 err: 555 return ret; 556 } 557 558 static bool pci_endpoint_test_set_irq(struct pci_endpoint_test *test, 559 int req_irq_type) 560 { 561 struct pci_dev *pdev = test->pdev; 562 struct device *dev = &pdev->dev; 563 564 if (req_irq_type < IRQ_TYPE_LEGACY || req_irq_type > IRQ_TYPE_MSIX) { 565 dev_err(dev, "Invalid IRQ type option\n"); 566 return false; 567 } 568 569 if (irq_type == req_irq_type) 570 return true; 571 572 pci_endpoint_test_release_irq(test); 573 pci_endpoint_test_free_irq_vectors(test); 574 575 if (!pci_endpoint_test_alloc_irq_vectors(test, req_irq_type)) 576 goto err; 577 578 if (!pci_endpoint_test_request_irq(test)) 579 goto err; 580 581 irq_type = req_irq_type; 582 return true; 583 584 err: 585 pci_endpoint_test_free_irq_vectors(test); 586 irq_type = IRQ_TYPE_UNDEFINED; 587 return false; 588 } 589 590 static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, 591 unsigned long arg) 592 { 593 int ret = -EINVAL; 594 enum pci_barno bar; 595 struct pci_endpoint_test *test = to_endpoint_test(file->private_data); 596 struct pci_dev *pdev = test->pdev; 597 598 mutex_lock(&test->mutex); 599 switch (cmd) { 600 case PCITEST_BAR: 601 bar = arg; 602 if (bar < 0 || bar > 5) 603 goto ret; 604 if (is_am654_pci_dev(pdev) && bar == BAR_0) 605 goto ret; 606 ret = pci_endpoint_test_bar(test, bar); 607 break; 608 case PCITEST_LEGACY_IRQ: 609 ret = pci_endpoint_test_legacy_irq(test); 610 break; 611 case PCITEST_MSI: 612 case PCITEST_MSIX: 613 ret = pci_endpoint_test_msi_irq(test, arg, cmd == PCITEST_MSIX); 614 break; 615 case PCITEST_WRITE: 616 ret = pci_endpoint_test_write(test, arg); 617 break; 618 case PCITEST_READ: 619 ret = pci_endpoint_test_read(test, arg); 620 break; 621 case PCITEST_COPY: 622 ret = pci_endpoint_test_copy(test, arg); 623 break; 624 case PCITEST_SET_IRQTYPE: 625 ret = pci_endpoint_test_set_irq(test, arg); 626 break; 627 case PCITEST_GET_IRQTYPE: 628 ret = irq_type; 629 break; 630 } 631 632 ret: 633 mutex_unlock(&test->mutex); 634 return ret; 635 } 636 637 static const struct file_operations pci_endpoint_test_fops = { 638 .owner = THIS_MODULE, 639 .unlocked_ioctl = pci_endpoint_test_ioctl, 640 }; 641 642 static int pci_endpoint_test_probe(struct pci_dev *pdev, 643 const struct pci_device_id *ent) 644 { 645 int err; 646 int id; 647 char name[20]; 648 enum pci_barno bar; 649 void __iomem *base; 650 struct device *dev = &pdev->dev; 651 struct pci_endpoint_test *test; 652 struct pci_endpoint_test_data *data; 653 enum pci_barno test_reg_bar = BAR_0; 654 struct miscdevice *misc_device; 655 656 if (pci_is_bridge(pdev)) 657 return -ENODEV; 658 659 test = devm_kzalloc(dev, sizeof(*test), GFP_KERNEL); 660 if (!test) 661 return -ENOMEM; 662 663 test->test_reg_bar = 0; 664 test->alignment = 0; 665 test->pdev = pdev; 666 667 if (no_msi) 668 irq_type = IRQ_TYPE_LEGACY; 669 670 data = (struct pci_endpoint_test_data *)ent->driver_data; 671 if (data) { 672 test_reg_bar = data->test_reg_bar; 673 test->test_reg_bar = test_reg_bar; 674 test->alignment = data->alignment; 675 irq_type = data->irq_type; 676 } 677 678 init_completion(&test->irq_raised); 679 mutex_init(&test->mutex); 680 681 err = pci_enable_device(pdev); 682 if (err) { 683 dev_err(dev, "Cannot enable PCI device\n"); 684 return err; 685 } 686 687 err = pci_request_regions(pdev, DRV_MODULE_NAME); 688 if (err) { 689 dev_err(dev, "Cannot obtain PCI resources\n"); 690 goto err_disable_pdev; 691 } 692 693 pci_set_master(pdev); 694 695 if (!pci_endpoint_test_alloc_irq_vectors(test, irq_type)) 696 goto err_disable_irq; 697 698 if (!pci_endpoint_test_request_irq(test)) 699 goto err_disable_irq; 700 701 for (bar = BAR_0; bar <= BAR_5; bar++) { 702 if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { 703 base = pci_ioremap_bar(pdev, bar); 704 if (!base) { 705 dev_err(dev, "Failed to read BAR%d\n", bar); 706 WARN_ON(bar == test_reg_bar); 707 } 708 test->bar[bar] = base; 709 } 710 } 711 712 test->base = test->bar[test_reg_bar]; 713 if (!test->base) { 714 err = -ENOMEM; 715 dev_err(dev, "Cannot perform PCI test without BAR%d\n", 716 test_reg_bar); 717 goto err_iounmap; 718 } 719 720 pci_set_drvdata(pdev, test); 721 722 id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL); 723 if (id < 0) { 724 err = id; 725 dev_err(dev, "Unable to get id\n"); 726 goto err_iounmap; 727 } 728 729 snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id); 730 misc_device = &test->miscdev; 731 misc_device->minor = MISC_DYNAMIC_MINOR; 732 misc_device->name = kstrdup(name, GFP_KERNEL); 733 if (!misc_device->name) { 734 err = -ENOMEM; 735 goto err_ida_remove; 736 } 737 misc_device->fops = &pci_endpoint_test_fops, 738 739 err = misc_register(misc_device); 740 if (err) { 741 dev_err(dev, "Failed to register device\n"); 742 goto err_kfree_name; 743 } 744 745 return 0; 746 747 err_kfree_name: 748 kfree(misc_device->name); 749 750 err_ida_remove: 751 ida_simple_remove(&pci_endpoint_test_ida, id); 752 753 err_iounmap: 754 for (bar = BAR_0; bar <= BAR_5; bar++) { 755 if (test->bar[bar]) 756 pci_iounmap(pdev, test->bar[bar]); 757 } 758 pci_endpoint_test_release_irq(test); 759 760 err_disable_irq: 761 pci_endpoint_test_free_irq_vectors(test); 762 pci_release_regions(pdev); 763 764 err_disable_pdev: 765 pci_disable_device(pdev); 766 767 return err; 768 } 769 770 static void pci_endpoint_test_remove(struct pci_dev *pdev) 771 { 772 int id; 773 enum pci_barno bar; 774 struct pci_endpoint_test *test = pci_get_drvdata(pdev); 775 struct miscdevice *misc_device = &test->miscdev; 776 777 if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1) 778 return; 779 if (id < 0) 780 return; 781 782 misc_deregister(&test->miscdev); 783 kfree(misc_device->name); 784 ida_simple_remove(&pci_endpoint_test_ida, id); 785 for (bar = BAR_0; bar <= BAR_5; bar++) { 786 if (test->bar[bar]) 787 pci_iounmap(pdev, test->bar[bar]); 788 } 789 790 pci_endpoint_test_release_irq(test); 791 pci_endpoint_test_free_irq_vectors(test); 792 793 pci_release_regions(pdev); 794 pci_disable_device(pdev); 795 } 796 797 static const struct pci_endpoint_test_data am654_data = { 798 .test_reg_bar = BAR_2, 799 .alignment = SZ_64K, 800 .irq_type = IRQ_TYPE_MSI, 801 }; 802 803 static const struct pci_device_id pci_endpoint_test_tbl[] = { 804 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x) }, 805 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x) }, 806 { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, 0x81c0) }, 807 { PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, 0xedda) }, 808 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654), 809 .driver_data = (kernel_ulong_t)&am654_data 810 }, 811 { } 812 }; 813 MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl); 814 815 static struct pci_driver pci_endpoint_test_driver = { 816 .name = DRV_MODULE_NAME, 817 .id_table = pci_endpoint_test_tbl, 818 .probe = pci_endpoint_test_probe, 819 .remove = pci_endpoint_test_remove, 820 }; 821 module_pci_driver(pci_endpoint_test_driver); 822 823 MODULE_DESCRIPTION("PCI ENDPOINT TEST HOST DRIVER"); 824 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); 825 MODULE_LICENSE("GPL v2"); 826