Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: endpoint: functions: Add an EP function to test PCI

Adds a new endpoint function driver (to program the virtual test device)
making use of the EP-core library.

[bhelgaas: fold in pci_epf_test_probe() -ENOMEM test from Wei Yongjun
<weiyongjun1@huawei.com>]
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

authored by

Kishon Vijay Abraham I and committed by
Bjorn Helgaas
349e7a85 42fc2ac6

+530 -1
+2
drivers/pci/endpoint/Kconfig
··· 26 26 configure the endpoint function and used to bind the 27 27 function with a endpoint controller. 28 28 29 + source "drivers/pci/endpoint/functions/Kconfig" 30 + 29 31 endmenu
+1 -1
drivers/pci/endpoint/Makefile
··· 4 4 5 5 obj-$(CONFIG_PCI_ENDPOINT_CONFIGFS) += pci-ep-cfs.o 6 6 obj-$(CONFIG_PCI_ENDPOINT) += pci-epc-core.o pci-epf-core.o\ 7 - pci-epc-mem.o 7 + pci-epc-mem.o functions/
+12
drivers/pci/endpoint/functions/Kconfig
··· 1 + # 2 + # PCI Endpoint Functions 3 + # 4 + 5 + config PCI_EPF_TEST 6 + tristate "PCI Endpoint Test driver" 7 + depends on PCI_ENDPOINT 8 + help 9 + Enable this configuration option to enable the test driver 10 + for PCI Endpoint. 11 + 12 + If in doubt, say "N" to disable Endpoint test driver.
+5
drivers/pci/endpoint/functions/Makefile
··· 1 + # 2 + # Makefile for PCI Endpoint Functions 3 + # 4 + 5 + obj-$(CONFIG_PCI_EPF_TEST) += pci-epf-test.o
+510
drivers/pci/endpoint/functions/pci-epf-test.c
··· 1 + /** 2 + * 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/io.h> 23 + #include <linux/module.h> 24 + #include <linux/slab.h> 25 + #include <linux/pci_ids.h> 26 + #include <linux/random.h> 27 + 28 + #include <linux/pci-epc.h> 29 + #include <linux/pci-epf.h> 30 + #include <linux/pci_regs.h> 31 + 32 + #define COMMAND_RAISE_LEGACY_IRQ BIT(0) 33 + #define COMMAND_RAISE_MSI_IRQ BIT(1) 34 + #define MSI_NUMBER_SHIFT 2 35 + #define MSI_NUMBER_MASK (0x3f << MSI_NUMBER_SHIFT) 36 + #define COMMAND_READ BIT(8) 37 + #define COMMAND_WRITE BIT(9) 38 + #define COMMAND_COPY BIT(10) 39 + 40 + #define STATUS_READ_SUCCESS BIT(0) 41 + #define STATUS_READ_FAIL BIT(1) 42 + #define STATUS_WRITE_SUCCESS BIT(2) 43 + #define STATUS_WRITE_FAIL BIT(3) 44 + #define STATUS_COPY_SUCCESS BIT(4) 45 + #define STATUS_COPY_FAIL BIT(5) 46 + #define STATUS_IRQ_RAISED BIT(6) 47 + #define STATUS_SRC_ADDR_INVALID BIT(7) 48 + #define STATUS_DST_ADDR_INVALID BIT(8) 49 + 50 + #define TIMER_RESOLUTION 1 51 + 52 + static struct workqueue_struct *kpcitest_workqueue; 53 + 54 + struct pci_epf_test { 55 + void *reg[6]; 56 + struct pci_epf *epf; 57 + struct delayed_work cmd_handler; 58 + }; 59 + 60 + struct pci_epf_test_reg { 61 + u32 magic; 62 + u32 command; 63 + u32 status; 64 + u64 src_addr; 65 + u64 dst_addr; 66 + u32 size; 67 + u32 checksum; 68 + } __packed; 69 + 70 + static struct pci_epf_header test_header = { 71 + .vendorid = PCI_ANY_ID, 72 + .deviceid = PCI_ANY_ID, 73 + .baseclass_code = PCI_CLASS_OTHERS, 74 + .interrupt_pin = PCI_INTERRUPT_INTA, 75 + }; 76 + 77 + static int bar_size[] = { 512, 1024, 16384, 131072, 1048576 }; 78 + 79 + static int pci_epf_test_copy(struct pci_epf_test *epf_test) 80 + { 81 + int ret; 82 + void __iomem *src_addr; 83 + void __iomem *dst_addr; 84 + phys_addr_t src_phys_addr; 85 + phys_addr_t dst_phys_addr; 86 + struct pci_epf *epf = epf_test->epf; 87 + struct device *dev = &epf->dev; 88 + struct pci_epc *epc = epf->epc; 89 + struct pci_epf_test_reg *reg = epf_test->reg[0]; 90 + 91 + src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size); 92 + if (!src_addr) { 93 + dev_err(dev, "failed to allocate source address\n"); 94 + reg->status = STATUS_SRC_ADDR_INVALID; 95 + ret = -ENOMEM; 96 + goto err; 97 + } 98 + 99 + ret = pci_epc_map_addr(epc, src_phys_addr, reg->src_addr, reg->size); 100 + if (ret) { 101 + dev_err(dev, "failed to map source address\n"); 102 + reg->status = STATUS_SRC_ADDR_INVALID; 103 + goto err_src_addr; 104 + } 105 + 106 + dst_addr = pci_epc_mem_alloc_addr(epc, &dst_phys_addr, reg->size); 107 + if (!dst_addr) { 108 + dev_err(dev, "failed to allocate destination address\n"); 109 + reg->status = STATUS_DST_ADDR_INVALID; 110 + ret = -ENOMEM; 111 + goto err_src_map_addr; 112 + } 113 + 114 + ret = pci_epc_map_addr(epc, dst_phys_addr, reg->dst_addr, reg->size); 115 + if (ret) { 116 + dev_err(dev, "failed to map destination address\n"); 117 + reg->status = STATUS_DST_ADDR_INVALID; 118 + goto err_dst_addr; 119 + } 120 + 121 + memcpy(dst_addr, src_addr, reg->size); 122 + 123 + pci_epc_unmap_addr(epc, dst_phys_addr); 124 + 125 + err_dst_addr: 126 + pci_epc_mem_free_addr(epc, dst_phys_addr, dst_addr, reg->size); 127 + 128 + err_src_map_addr: 129 + pci_epc_unmap_addr(epc, src_phys_addr); 130 + 131 + err_src_addr: 132 + pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size); 133 + 134 + err: 135 + return ret; 136 + } 137 + 138 + static int pci_epf_test_read(struct pci_epf_test *epf_test) 139 + { 140 + int ret; 141 + void __iomem *src_addr; 142 + void *buf; 143 + u32 crc32; 144 + phys_addr_t phys_addr; 145 + struct pci_epf *epf = epf_test->epf; 146 + struct device *dev = &epf->dev; 147 + struct pci_epc *epc = epf->epc; 148 + struct pci_epf_test_reg *reg = epf_test->reg[0]; 149 + 150 + src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size); 151 + if (!src_addr) { 152 + dev_err(dev, "failed to allocate address\n"); 153 + reg->status = STATUS_SRC_ADDR_INVALID; 154 + ret = -ENOMEM; 155 + goto err; 156 + } 157 + 158 + ret = pci_epc_map_addr(epc, phys_addr, reg->src_addr, reg->size); 159 + if (ret) { 160 + dev_err(dev, "failed to map address\n"); 161 + reg->status = STATUS_SRC_ADDR_INVALID; 162 + goto err_addr; 163 + } 164 + 165 + buf = kzalloc(reg->size, GFP_KERNEL); 166 + if (!buf) { 167 + ret = -ENOMEM; 168 + goto err_map_addr; 169 + } 170 + 171 + memcpy(buf, src_addr, reg->size); 172 + 173 + crc32 = crc32_le(~0, buf, reg->size); 174 + if (crc32 != reg->checksum) 175 + ret = -EIO; 176 + 177 + kfree(buf); 178 + 179 + err_map_addr: 180 + pci_epc_unmap_addr(epc, phys_addr); 181 + 182 + err_addr: 183 + pci_epc_mem_free_addr(epc, phys_addr, src_addr, reg->size); 184 + 185 + err: 186 + return ret; 187 + } 188 + 189 + static int pci_epf_test_write(struct pci_epf_test *epf_test) 190 + { 191 + int ret; 192 + void __iomem *dst_addr; 193 + void *buf; 194 + phys_addr_t phys_addr; 195 + struct pci_epf *epf = epf_test->epf; 196 + struct device *dev = &epf->dev; 197 + struct pci_epc *epc = epf->epc; 198 + struct pci_epf_test_reg *reg = epf_test->reg[0]; 199 + 200 + dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size); 201 + if (!dst_addr) { 202 + dev_err(dev, "failed to allocate address\n"); 203 + reg->status = STATUS_DST_ADDR_INVALID; 204 + ret = -ENOMEM; 205 + goto err; 206 + } 207 + 208 + ret = pci_epc_map_addr(epc, phys_addr, reg->dst_addr, reg->size); 209 + if (ret) { 210 + dev_err(dev, "failed to map address\n"); 211 + reg->status = STATUS_DST_ADDR_INVALID; 212 + goto err_addr; 213 + } 214 + 215 + buf = kzalloc(reg->size, GFP_KERNEL); 216 + if (!buf) { 217 + ret = -ENOMEM; 218 + goto err_map_addr; 219 + } 220 + 221 + get_random_bytes(buf, reg->size); 222 + reg->checksum = crc32_le(~0, buf, reg->size); 223 + 224 + memcpy(dst_addr, buf, reg->size); 225 + 226 + /* 227 + * wait 1ms inorder for the write to complete. Without this delay L3 228 + * error in observed in the host system. 229 + */ 230 + mdelay(1); 231 + 232 + kfree(buf); 233 + 234 + err_map_addr: 235 + pci_epc_unmap_addr(epc, phys_addr); 236 + 237 + err_addr: 238 + pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size); 239 + 240 + err: 241 + return ret; 242 + } 243 + 244 + static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test) 245 + { 246 + u8 irq; 247 + u8 msi_count; 248 + struct pci_epf *epf = epf_test->epf; 249 + struct pci_epc *epc = epf->epc; 250 + struct pci_epf_test_reg *reg = epf_test->reg[0]; 251 + 252 + reg->status |= STATUS_IRQ_RAISED; 253 + msi_count = pci_epc_get_msi(epc); 254 + irq = (reg->command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT; 255 + if (irq > msi_count || msi_count <= 0) 256 + pci_epc_raise_irq(epc, PCI_EPC_IRQ_LEGACY, 0); 257 + else 258 + pci_epc_raise_irq(epc, PCI_EPC_IRQ_MSI, irq); 259 + } 260 + 261 + static void pci_epf_test_cmd_handler(struct work_struct *work) 262 + { 263 + int ret; 264 + u8 irq; 265 + u8 msi_count; 266 + struct pci_epf_test *epf_test = container_of(work, struct pci_epf_test, 267 + cmd_handler.work); 268 + struct pci_epf *epf = epf_test->epf; 269 + struct pci_epc *epc = epf->epc; 270 + struct pci_epf_test_reg *reg = epf_test->reg[0]; 271 + 272 + if (!reg->command) 273 + goto reset_handler; 274 + 275 + if (reg->command & COMMAND_RAISE_LEGACY_IRQ) { 276 + reg->status = STATUS_IRQ_RAISED; 277 + pci_epc_raise_irq(epc, PCI_EPC_IRQ_LEGACY, 0); 278 + goto reset_handler; 279 + } 280 + 281 + if (reg->command & COMMAND_WRITE) { 282 + ret = pci_epf_test_write(epf_test); 283 + if (ret) 284 + reg->status |= STATUS_WRITE_FAIL; 285 + else 286 + reg->status |= STATUS_WRITE_SUCCESS; 287 + pci_epf_test_raise_irq(epf_test); 288 + goto reset_handler; 289 + } 290 + 291 + if (reg->command & COMMAND_READ) { 292 + ret = pci_epf_test_read(epf_test); 293 + if (!ret) 294 + reg->status |= STATUS_READ_SUCCESS; 295 + else 296 + reg->status |= STATUS_READ_FAIL; 297 + pci_epf_test_raise_irq(epf_test); 298 + goto reset_handler; 299 + } 300 + 301 + if (reg->command & COMMAND_COPY) { 302 + ret = pci_epf_test_copy(epf_test); 303 + if (!ret) 304 + reg->status |= STATUS_COPY_SUCCESS; 305 + else 306 + reg->status |= STATUS_COPY_FAIL; 307 + pci_epf_test_raise_irq(epf_test); 308 + goto reset_handler; 309 + } 310 + 311 + if (reg->command & COMMAND_RAISE_MSI_IRQ) { 312 + msi_count = pci_epc_get_msi(epc); 313 + irq = (reg->command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT; 314 + if (irq > msi_count || msi_count <= 0) 315 + goto reset_handler; 316 + reg->status = STATUS_IRQ_RAISED; 317 + pci_epc_raise_irq(epc, PCI_EPC_IRQ_MSI, irq); 318 + goto reset_handler; 319 + } 320 + 321 + reset_handler: 322 + reg->command = 0; 323 + 324 + queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler, 325 + msecs_to_jiffies(1)); 326 + } 327 + 328 + static void pci_epf_test_linkup(struct pci_epf *epf) 329 + { 330 + struct pci_epf_test *epf_test = epf_get_drvdata(epf); 331 + 332 + queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler, 333 + msecs_to_jiffies(1)); 334 + } 335 + 336 + static void pci_epf_test_unbind(struct pci_epf *epf) 337 + { 338 + struct pci_epf_test *epf_test = epf_get_drvdata(epf); 339 + struct pci_epc *epc = epf->epc; 340 + int bar; 341 + 342 + cancel_delayed_work(&epf_test->cmd_handler); 343 + pci_epc_stop(epc); 344 + for (bar = BAR_0; bar <= BAR_5; bar++) { 345 + if (epf_test->reg[bar]) { 346 + pci_epf_free_space(epf, epf_test->reg[bar], bar); 347 + pci_epc_clear_bar(epc, bar); 348 + } 349 + } 350 + } 351 + 352 + static int pci_epf_test_set_bar(struct pci_epf *epf) 353 + { 354 + int flags; 355 + int bar; 356 + int ret; 357 + struct pci_epf_bar *epf_bar; 358 + struct pci_epc *epc = epf->epc; 359 + struct device *dev = &epf->dev; 360 + struct pci_epf_test *epf_test = epf_get_drvdata(epf); 361 + 362 + flags = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_32; 363 + if (sizeof(dma_addr_t) == 0x8) 364 + flags |= PCI_BASE_ADDRESS_MEM_TYPE_64; 365 + 366 + for (bar = BAR_0; bar <= BAR_5; bar++) { 367 + epf_bar = &epf->bar[bar]; 368 + ret = pci_epc_set_bar(epc, bar, epf_bar->phys_addr, 369 + epf_bar->size, flags); 370 + if (ret) { 371 + pci_epf_free_space(epf, epf_test->reg[bar], bar); 372 + dev_err(dev, "failed to set BAR%d\n", bar); 373 + if (bar == BAR_0) 374 + return ret; 375 + } 376 + } 377 + 378 + return 0; 379 + } 380 + 381 + static int pci_epf_test_alloc_space(struct pci_epf *epf) 382 + { 383 + struct pci_epf_test *epf_test = epf_get_drvdata(epf); 384 + struct device *dev = &epf->dev; 385 + void *base; 386 + int bar; 387 + 388 + base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg), 389 + BAR_0); 390 + if (!base) { 391 + dev_err(dev, "failed to allocated register space\n"); 392 + return -ENOMEM; 393 + } 394 + epf_test->reg[0] = base; 395 + 396 + for (bar = BAR_1; bar <= BAR_5; bar++) { 397 + base = pci_epf_alloc_space(epf, bar_size[bar - 1], bar); 398 + if (!base) 399 + dev_err(dev, "failed to allocate space for BAR%d\n", 400 + bar); 401 + epf_test->reg[bar] = base; 402 + } 403 + 404 + return 0; 405 + } 406 + 407 + static int pci_epf_test_bind(struct pci_epf *epf) 408 + { 409 + int ret; 410 + struct pci_epf_header *header = epf->header; 411 + struct pci_epc *epc = epf->epc; 412 + struct device *dev = &epf->dev; 413 + 414 + if (WARN_ON_ONCE(!epc)) 415 + return -EINVAL; 416 + 417 + ret = pci_epc_write_header(epc, header); 418 + if (ret) { 419 + dev_err(dev, "configuration header write failed\n"); 420 + return ret; 421 + } 422 + 423 + ret = pci_epf_test_alloc_space(epf); 424 + if (ret) 425 + return ret; 426 + 427 + ret = pci_epf_test_set_bar(epf); 428 + if (ret) 429 + return ret; 430 + 431 + ret = pci_epc_set_msi(epc, epf->msi_interrupts); 432 + if (ret) 433 + return ret; 434 + 435 + return 0; 436 + } 437 + 438 + static int pci_epf_test_probe(struct pci_epf *epf) 439 + { 440 + struct pci_epf_test *epf_test; 441 + struct device *dev = &epf->dev; 442 + 443 + epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL); 444 + if (!epf_test) 445 + return -ENOMEM; 446 + 447 + epf->header = &test_header; 448 + epf_test->epf = epf; 449 + 450 + INIT_DELAYED_WORK(&epf_test->cmd_handler, pci_epf_test_cmd_handler); 451 + 452 + epf_set_drvdata(epf, epf_test); 453 + return 0; 454 + } 455 + 456 + static int pci_epf_test_remove(struct pci_epf *epf) 457 + { 458 + struct pci_epf_test *epf_test = epf_get_drvdata(epf); 459 + 460 + kfree(epf_test); 461 + return 0; 462 + } 463 + 464 + static struct pci_epf_ops ops = { 465 + .unbind = pci_epf_test_unbind, 466 + .bind = pci_epf_test_bind, 467 + .linkup = pci_epf_test_linkup, 468 + }; 469 + 470 + static const struct pci_epf_device_id pci_epf_test_ids[] = { 471 + { 472 + .name = "pci_epf_test", 473 + }, 474 + {}, 475 + }; 476 + 477 + static struct pci_epf_driver test_driver = { 478 + .driver.name = "pci_epf_test", 479 + .probe = pci_epf_test_probe, 480 + .remove = pci_epf_test_remove, 481 + .id_table = pci_epf_test_ids, 482 + .ops = &ops, 483 + .owner = THIS_MODULE, 484 + }; 485 + 486 + static int __init pci_epf_test_init(void) 487 + { 488 + int ret; 489 + 490 + kpcitest_workqueue = alloc_workqueue("kpcitest", 491 + WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); 492 + ret = pci_epf_register_driver(&test_driver); 493 + if (ret) { 494 + pr_err("failed to register pci epf test driver --> %d\n", ret); 495 + return ret; 496 + } 497 + 498 + return 0; 499 + } 500 + module_init(pci_epf_test_init); 501 + 502 + static void __exit pci_epf_test_exit(void) 503 + { 504 + pci_epf_unregister_driver(&test_driver); 505 + } 506 + module_exit(pci_epf_test_exit); 507 + 508 + MODULE_DESCRIPTION("PCI EPF TEST DRIVER"); 509 + MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); 510 + MODULE_LICENSE("GPL v2");