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

Merge branch 'remotes/lorenzo/pci/dwc'

- Add Kirin MSI support (Xiaowei Song)

- Drop unnecessary root_bus_nr setting from exynos, imx6, keystone,
armada8k, artpec6, designware-plat, histb, qcom, spear13xx (Shawn Guo)

- Move link notification settings from DesignWare core to individual
drivers (Gustavo Pimentel)

- Add endpoint library MSI-X interfaces (Gustavo Pimentel)

- Correct signature of endpoint library IRQ interfaces (Gustavo Pimentel)

- Add DesignWare endpoint library MSI-X callbacks (Gustavo Pimentel)

- Add endpoint library MSI-X test support (Gustavo Pimentel)

* remotes/lorenzo/pci/dwc:
PCI: endpoint: Add MSI set maximum restriction
tools: PCI: Add MSI-X support
pci_endpoint_test: Add 2 ioctl commands
pci-epf-test/pci_endpoint_test: Add MSI-X support
pci-epf-test/pci_endpoint_test: Use irq_type module parameter
pci-epf-test/pci_endpoint_test: Cleanup PCI_ENDPOINT_TEST memspace
PCI: dwc: Add legacy interrupt callback handler
PCI: dwc: Rework MSI callbacks handler
PCI: dwc: Add MSI-X callbacks handler
PCI: Update xxx_pcie_ep_raise_irq() and pci_epc_raise_irq() signatures
PCI: endpoint: Add MSI-X interfaces
PCI: dwc: Fix EP link notification implementation
PCI: spear13xx: Drop unnecessary root_bus_nr setting
PCI: qcom: Drop unnecessary root_bus_nr setting
PCI: histb: Drop unnecessary root_bus_nr setting
PCI: designware-plat: Drop unnecessary root_bus_nr setting
PCI: artpec6: Drop unnecessary root_bus_nr setting
PCI: armada8k: Drop unnecessary root_bus_nr setting
PCI: keystone: Drop unnecessary root_bus_nr setting
PCI: imx6: Drop unnecessary root_bus_nr setting
PCI: exynos: Drop unnecessary root_bus_nr setting
PCI: kirin: Add MSI support

+759 -155
+2
Documentation/PCI/endpoint/function/binding/pci-test.txt
··· 15 15 interrupt_pin : Should be 1 - INTA, 2 - INTB, 3 - INTC, 4 -INTD 16 16 msi_interrupts : Should be 1 to 32 depending on the number of MSI interrupts 17 17 to test 18 + msix_interrupts : Should be 1 to 2048 depending on the number of MSI-X 19 + interrupts to test
+2 -2
Documentation/PCI/endpoint/pci-endpoint.txt
··· 44 44 * clear_bar: ops to reset the BAR 45 45 * alloc_addr_space: ops to allocate in PCI controller address space 46 46 * free_addr_space: ops to free the allocated address space 47 - * raise_irq: ops to raise a legacy or MSI interrupt 47 + * raise_irq: ops to raise a legacy, MSI or MSI-X interrupt 48 48 * start: ops to start the PCI link 49 49 * stop: ops to stop the PCI link 50 50 ··· 96 96 *) pci_epc_raise_irq() 97 97 98 98 The PCI endpoint function driver should use pci_epc_raise_irq() to raise 99 - Legacy Interrupt or MSI Interrupt. 99 + Legacy Interrupt, MSI or MSI-X Interrupt. 100 100 101 101 *) pci_epc_mem_alloc_addr() 102 102
+25 -4
Documentation/PCI/endpoint/pci-test-function.txt
··· 20 20 5) PCI_ENDPOINT_TEST_DST_ADDR 21 21 6) PCI_ENDPOINT_TEST_SIZE 22 22 7) PCI_ENDPOINT_TEST_CHECKSUM 23 + 8) PCI_ENDPOINT_TEST_IRQ_TYPE 24 + 9) PCI_ENDPOINT_TEST_IRQ_NUMBER 23 25 24 26 *) PCI_ENDPOINT_TEST_MAGIC 25 27 ··· 36 34 Bitfield Description: 37 35 Bit 0 : raise legacy IRQ 38 36 Bit 1 : raise MSI IRQ 39 - Bit 2 - 7 : MSI interrupt number 40 - Bit 8 : read command (read data from RC buffer) 41 - Bit 9 : write command (write data to RC buffer) 42 - Bit 10 : copy command (copy data from one RC buffer to another 37 + Bit 2 : raise MSI-X IRQ 38 + Bit 3 : read command (read data from RC buffer) 39 + Bit 4 : write command (write data to RC buffer) 40 + Bit 5 : copy command (copy data from one RC buffer to another 43 41 RC buffer) 44 42 45 43 *) PCI_ENDPOINT_TEST_STATUS ··· 66 64 67 65 This register contains the destination address (RC buffer address) for 68 66 the COPY/WRITE command. 67 + 68 + *) PCI_ENDPOINT_TEST_IRQ_TYPE 69 + 70 + This register contains the interrupt type (Legacy/MSI) triggered 71 + for the READ/WRITE/COPY and raise IRQ (Legacy/MSI) commands. 72 + 73 + Possible types: 74 + - Legacy : 0 75 + - MSI : 1 76 + - MSI-X : 2 77 + 78 + *) PCI_ENDPOINT_TEST_IRQ_NUMBER 79 + 80 + This register contains the triggered ID interrupt. 81 + 82 + Admissible values: 83 + - Legacy : 0 84 + - MSI : [1 .. 32] 85 + - MSI-X : [1 .. 2048]
+27 -3
Documentation/PCI/endpoint/pci-test-howto.txt
··· 45 45 configurable fields. 46 46 47 47 # ls functions/pci_epf_test/func1 48 - baseclass_code interrupt_pin revid subsys_vendor_id 49 - cache_line_size msi_interrupts subclass_code vendorid 50 - deviceid progif_code subsys_id 48 + baseclass_code interrupt_pin progif_code subsys_id 49 + cache_line_size msi_interrupts revid subsys_vendorid 50 + deviceid msix_interrupts subclass_code vendorid 51 51 52 52 The PCI endpoint function driver populates these entries with default values 53 53 when the device is bound to the driver. The pci-epf-test driver populates ··· 67 67 # echo 0x104c > functions/pci_epf_test/func1/vendorid 68 68 # echo 0xb500 > functions/pci_epf_test/func1/deviceid 69 69 # echo 16 > functions/pci_epf_test/func1/msi_interrupts 70 + # echo 8 > functions/pci_epf_test/func1/msix_interrupts 70 71 71 72 1.5 Binding pci-epf-test Device to EP Controller 72 73 ··· 121 120 122 121 Interrupt tests 123 122 123 + SET IRQ TYPE TO LEGACY: OKAY 124 124 LEGACY IRQ: NOT OKAY 125 + SET IRQ TYPE TO MSI: OKAY 125 126 MSI1: OKAY 126 127 MSI2: OKAY 127 128 MSI3: OKAY ··· 156 153 MSI30: NOT OKAY 157 154 MSI31: NOT OKAY 158 155 MSI32: NOT OKAY 156 + SET IRQ TYPE TO MSI-X: OKAY 157 + MSI-X1: OKAY 158 + MSI-X2: OKAY 159 + MSI-X3: OKAY 160 + MSI-X4: OKAY 161 + MSI-X5: OKAY 162 + MSI-X6: OKAY 163 + MSI-X7: OKAY 164 + MSI-X8: OKAY 165 + MSI-X9: NOT OKAY 166 + MSI-X10: NOT OKAY 167 + MSI-X11: NOT OKAY 168 + MSI-X12: NOT OKAY 169 + MSI-X13: NOT OKAY 170 + MSI-X14: NOT OKAY 171 + MSI-X15: NOT OKAY 172 + MSI-X16: NOT OKAY 173 + [...] 174 + MSI-X2047: NOT OKAY 175 + MSI-X2048: NOT OKAY 159 176 160 177 Read Tests 161 178 179 + SET IRQ TYPE TO MSI: OKAY 162 180 READ ( 1 bytes): OKAY 163 181 READ ( 1024 bytes): OKAY 164 182 READ ( 1025 bytes): OKAY
+1
Documentation/ioctl/ioctl-number.txt
··· 166 166 'P' all linux/soundcard.h conflict! 167 167 'P' 60-6F sound/sscape_ioctl.h conflict! 168 168 'P' 00-0F drivers/usb/class/usblp.c conflict! 169 + 'P' 01-09 drivers/misc/pci_endpoint_test.c conflict! 169 170 'Q' all linux/soundcard.h 170 171 'R' 00-1F linux/random.h conflict! 171 172 'R' 01 linux/rfkill.h conflict!
+6
Documentation/misc-devices/pci-endpoint-test.txt
··· 10 10 *) verifying addresses programmed in BAR 11 11 *) raise legacy IRQ 12 12 *) raise MSI IRQ 13 + *) raise MSI-X IRQ 13 14 *) read data 14 15 *) write data 15 16 *) copy data ··· 26 25 PCITEST_LEGACY_IRQ: Tests legacy IRQ 27 26 PCITEST_MSI: Tests message signalled interrupts. The MSI number 28 27 to be tested should be passed as argument. 28 + PCITEST_MSIX: Tests message signalled interrupts. The MSI-X number 29 + to be tested should be passed as argument. 30 + PCITEST_SET_IRQTYPE: Changes driver IRQ type configuration. The IRQ type 31 + should be passed as argument (0: Legacy, 1:MSI, 2:MSI-X). 32 + PCITEST_GET_IRQTYPE: Gets driver IRQ type configuration. 29 33 PCITEST_WRITE: Perform write tests. The size of the buffer should be passed 30 34 as argument. 31 35 PCITEST_READ: Perform read tests. The size of the buffer should be passed
+218 -64
drivers/misc/pci_endpoint_test.c
··· 35 35 36 36 #include <uapi/linux/pcitest.h> 37 37 38 - #define DRV_MODULE_NAME "pci-endpoint-test" 38 + #define DRV_MODULE_NAME "pci-endpoint-test" 39 39 40 - #define PCI_ENDPOINT_TEST_MAGIC 0x0 40 + #define IRQ_TYPE_UNDEFINED -1 41 + #define IRQ_TYPE_LEGACY 0 42 + #define IRQ_TYPE_MSI 1 43 + #define IRQ_TYPE_MSIX 2 41 44 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) 45 + #define PCI_ENDPOINT_TEST_MAGIC 0x0 50 46 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) 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) 61 54 62 - #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0xc 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 63 67 #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10 64 68 65 69 #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14 66 70 #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18 67 71 68 - #define PCI_ENDPOINT_TEST_SIZE 0x1c 69 - #define PCI_ENDPOINT_TEST_CHECKSUM 0x20 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 70 77 71 78 static DEFINE_IDA(pci_endpoint_test_ida); 72 79 ··· 83 76 static bool no_msi; 84 77 module_param(no_msi, bool, 0444); 85 78 MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test"); 79 + 80 + static int irq_type = IRQ_TYPE_MSI; 81 + module_param(irq_type, int, 0444); 82 + MODULE_PARM_DESC(irq_type, "IRQ mode selection in pci_endpoint_test (0 - Legacy, 1 - MSI, 2 - MSI-X)"); 86 83 87 84 enum pci_barno { 88 85 BAR_0, ··· 114 103 struct pci_endpoint_test_data { 115 104 enum pci_barno test_reg_bar; 116 105 size_t alignment; 117 - bool no_msi; 106 + int irq_type; 118 107 }; 119 108 120 109 static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test, ··· 158 147 return IRQ_HANDLED; 159 148 } 160 149 150 + static void pci_endpoint_test_free_irq_vectors(struct pci_endpoint_test *test) 151 + { 152 + struct pci_dev *pdev = test->pdev; 153 + 154 + pci_free_irq_vectors(pdev); 155 + } 156 + 157 + static bool pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test, 158 + int type) 159 + { 160 + int irq = -1; 161 + struct pci_dev *pdev = test->pdev; 162 + struct device *dev = &pdev->dev; 163 + bool res = true; 164 + 165 + switch (type) { 166 + case IRQ_TYPE_LEGACY: 167 + irq = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_LEGACY); 168 + if (irq < 0) 169 + dev_err(dev, "Failed to get Legacy interrupt\n"); 170 + break; 171 + case IRQ_TYPE_MSI: 172 + irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); 173 + if (irq < 0) 174 + dev_err(dev, "Failed to get MSI interrupts\n"); 175 + break; 176 + case IRQ_TYPE_MSIX: 177 + irq = pci_alloc_irq_vectors(pdev, 1, 2048, PCI_IRQ_MSIX); 178 + if (irq < 0) 179 + dev_err(dev, "Failed to get MSI-X interrupts\n"); 180 + break; 181 + default: 182 + dev_err(dev, "Invalid IRQ type selected\n"); 183 + } 184 + 185 + if (irq < 0) { 186 + irq = 0; 187 + res = false; 188 + } 189 + test->num_irqs = irq; 190 + 191 + return res; 192 + } 193 + 194 + static void pci_endpoint_test_release_irq(struct pci_endpoint_test *test) 195 + { 196 + int i; 197 + struct pci_dev *pdev = test->pdev; 198 + struct device *dev = &pdev->dev; 199 + 200 + for (i = 0; i < test->num_irqs; i++) 201 + devm_free_irq(dev, pci_irq_vector(pdev, i), test); 202 + 203 + test->num_irqs = 0; 204 + } 205 + 206 + static bool pci_endpoint_test_request_irq(struct pci_endpoint_test *test) 207 + { 208 + int i; 209 + int err; 210 + struct pci_dev *pdev = test->pdev; 211 + struct device *dev = &pdev->dev; 212 + 213 + for (i = 0; i < test->num_irqs; i++) { 214 + err = devm_request_irq(dev, pci_irq_vector(pdev, i), 215 + pci_endpoint_test_irqhandler, 216 + IRQF_SHARED, DRV_MODULE_NAME, test); 217 + if (err) 218 + goto fail; 219 + } 220 + 221 + return true; 222 + 223 + fail: 224 + switch (irq_type) { 225 + case IRQ_TYPE_LEGACY: 226 + dev_err(dev, "Failed to request IRQ %d for Legacy\n", 227 + pci_irq_vector(pdev, i)); 228 + break; 229 + case IRQ_TYPE_MSI: 230 + dev_err(dev, "Failed to request IRQ %d for MSI %d\n", 231 + pci_irq_vector(pdev, i), 232 + i + 1); 233 + break; 234 + case IRQ_TYPE_MSIX: 235 + dev_err(dev, "Failed to request IRQ %d for MSI-X %d\n", 236 + pci_irq_vector(pdev, i), 237 + i + 1); 238 + break; 239 + } 240 + 241 + return false; 242 + } 243 + 161 244 static bool pci_endpoint_test_bar(struct pci_endpoint_test *test, 162 245 enum pci_barno barno) 163 246 { ··· 284 179 { 285 180 u32 val; 286 181 182 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, 183 + IRQ_TYPE_LEGACY); 184 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 0); 287 185 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 288 186 COMMAND_RAISE_LEGACY_IRQ); 289 187 val = wait_for_completion_timeout(&test->irq_raised, ··· 298 190 } 299 191 300 192 static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, 301 - u8 msi_num) 193 + u16 msi_num, bool msix) 302 194 { 303 195 u32 val; 304 196 struct pci_dev *pdev = test->pdev; 305 197 198 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, 199 + msix == false ? IRQ_TYPE_MSI : 200 + IRQ_TYPE_MSIX); 201 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, msi_num); 306 202 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 307 - msi_num << MSI_NUMBER_SHIFT | 308 - COMMAND_RAISE_MSI_IRQ); 203 + msix == false ? COMMAND_RAISE_MSI_IRQ : 204 + COMMAND_RAISE_MSIX_IRQ); 309 205 val = wait_for_completion_timeout(&test->irq_raised, 310 206 msecs_to_jiffies(1000)); 311 207 if (!val) ··· 341 229 342 230 if (size > SIZE_MAX - alignment) 343 231 goto err; 232 + 233 + if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { 234 + dev_err(dev, "Invalid IRQ type option\n"); 235 + goto err; 236 + } 344 237 345 238 orig_src_addr = dma_alloc_coherent(dev, size + alignment, 346 239 &orig_src_phys_addr, GFP_KERNEL); ··· 398 281 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, 399 282 size); 400 283 284 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); 285 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); 401 286 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 402 - 1 << MSI_NUMBER_SHIFT | COMMAND_COPY); 287 + COMMAND_COPY); 403 288 404 289 wait_for_completion(&test->irq_raised); 405 290 ··· 437 318 if (size > SIZE_MAX - alignment) 438 319 goto err; 439 320 321 + if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { 322 + dev_err(dev, "Invalid IRQ type option\n"); 323 + goto err; 324 + } 325 + 440 326 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, 441 327 GFP_KERNEL); 442 328 if (!orig_addr) { ··· 472 348 473 349 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); 474 350 351 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); 352 + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); 475 353 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 476 - 1 << MSI_NUMBER_SHIFT | COMMAND_READ); 354 + COMMAND_READ); 477 355 478 356 wait_for_completion(&test->irq_raised); 479 357 ··· 505 379 if (size > SIZE_MAX - alignment) 506 380 goto err; 507 381 382 + if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { 383 + dev_err(dev, "Invalid IRQ type option\n"); 384 + goto err; 385 + } 386 + 508 387 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, 509 388 GFP_KERNEL); 510 389 if (!orig_addr) { ··· 534 403 535 404 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); 536 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); 537 408 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, 538 - 1 << MSI_NUMBER_SHIFT | COMMAND_WRITE); 409 + COMMAND_WRITE); 539 410 540 411 wait_for_completion(&test->irq_raised); 541 412 ··· 548 415 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr); 549 416 err: 550 417 return ret; 418 + } 419 + 420 + static bool pci_endpoint_test_set_irq(struct pci_endpoint_test *test, 421 + int req_irq_type) 422 + { 423 + struct pci_dev *pdev = test->pdev; 424 + struct device *dev = &pdev->dev; 425 + 426 + if (req_irq_type < IRQ_TYPE_LEGACY || req_irq_type > IRQ_TYPE_MSIX) { 427 + dev_err(dev, "Invalid IRQ type option\n"); 428 + return false; 429 + } 430 + 431 + if (irq_type == req_irq_type) 432 + return true; 433 + 434 + pci_endpoint_test_release_irq(test); 435 + pci_endpoint_test_free_irq_vectors(test); 436 + 437 + if (!pci_endpoint_test_alloc_irq_vectors(test, req_irq_type)) 438 + goto err; 439 + 440 + if (!pci_endpoint_test_request_irq(test)) 441 + goto err; 442 + 443 + irq_type = req_irq_type; 444 + return true; 445 + 446 + err: 447 + pci_endpoint_test_free_irq_vectors(test); 448 + irq_type = IRQ_TYPE_UNDEFINED; 449 + return false; 551 450 } 552 451 553 452 static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, ··· 601 436 ret = pci_endpoint_test_legacy_irq(test); 602 437 break; 603 438 case PCITEST_MSI: 604 - ret = pci_endpoint_test_msi_irq(test, arg); 439 + case PCITEST_MSIX: 440 + ret = pci_endpoint_test_msi_irq(test, arg, cmd == PCITEST_MSIX); 605 441 break; 606 442 case PCITEST_WRITE: 607 443 ret = pci_endpoint_test_write(test, arg); ··· 612 446 break; 613 447 case PCITEST_COPY: 614 448 ret = pci_endpoint_test_copy(test, arg); 449 + break; 450 + case PCITEST_SET_IRQTYPE: 451 + ret = pci_endpoint_test_set_irq(test, arg); 452 + break; 453 + case PCITEST_GET_IRQTYPE: 454 + ret = irq_type; 615 455 break; 616 456 } 617 457 ··· 634 462 static int pci_endpoint_test_probe(struct pci_dev *pdev, 635 463 const struct pci_device_id *ent) 636 464 { 637 - int i; 638 465 int err; 639 - int irq = 0; 640 466 int id; 641 467 char name[20]; 642 468 enum pci_barno bar; ··· 656 486 test->alignment = 0; 657 487 test->pdev = pdev; 658 488 489 + if (no_msi) 490 + irq_type = IRQ_TYPE_LEGACY; 491 + 659 492 data = (struct pci_endpoint_test_data *)ent->driver_data; 660 493 if (data) { 661 494 test_reg_bar = data->test_reg_bar; 662 495 test->alignment = data->alignment; 663 - no_msi = data->no_msi; 496 + irq_type = data->irq_type; 664 497 } 665 498 666 499 init_completion(&test->irq_raised); ··· 683 510 684 511 pci_set_master(pdev); 685 512 686 - if (!no_msi) { 687 - irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); 688 - if (irq < 0) 689 - dev_err(dev, "Failed to get MSI interrupts\n"); 690 - test->num_irqs = irq; 691 - } 513 + if (!pci_endpoint_test_alloc_irq_vectors(test, irq_type)) 514 + goto err_disable_irq; 692 515 693 - err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, 694 - IRQF_SHARED, DRV_MODULE_NAME, test); 695 - if (err) { 696 - dev_err(dev, "Failed to request IRQ %d\n", pdev->irq); 697 - goto err_disable_msi; 698 - } 699 - 700 - for (i = 1; i < irq; i++) { 701 - err = devm_request_irq(dev, pci_irq_vector(pdev, i), 702 - pci_endpoint_test_irqhandler, 703 - IRQF_SHARED, DRV_MODULE_NAME, test); 704 - if (err) 705 - dev_err(dev, "failed to request IRQ %d for MSI %d\n", 706 - pci_irq_vector(pdev, i), i + 1); 707 - } 516 + if (!pci_endpoint_test_request_irq(test)) 517 + goto err_disable_irq; 708 518 709 519 for (bar = BAR_0; bar <= BAR_5; bar++) { 710 520 if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { ··· 746 590 if (test->bar[bar]) 747 591 pci_iounmap(pdev, test->bar[bar]); 748 592 } 593 + pci_endpoint_test_release_irq(test); 749 594 750 - for (i = 0; i < irq; i++) 751 - devm_free_irq(&pdev->dev, pci_irq_vector(pdev, i), test); 752 - 753 - err_disable_msi: 754 - pci_disable_msi(pdev); 595 + err_disable_irq: 596 + pci_endpoint_test_free_irq_vectors(test); 755 597 pci_release_regions(pdev); 756 598 757 599 err_disable_pdev: ··· 761 607 static void pci_endpoint_test_remove(struct pci_dev *pdev) 762 608 { 763 609 int id; 764 - int i; 765 610 enum pci_barno bar; 766 611 struct pci_endpoint_test *test = pci_get_drvdata(pdev); 767 612 struct miscdevice *misc_device = &test->miscdev; ··· 777 624 if (test->bar[bar]) 778 625 pci_iounmap(pdev, test->bar[bar]); 779 626 } 780 - for (i = 0; i < test->num_irqs; i++) 781 - devm_free_irq(&pdev->dev, pci_irq_vector(pdev, i), test); 782 - pci_disable_msi(pdev); 627 + 628 + pci_endpoint_test_release_irq(test); 629 + pci_endpoint_test_free_irq_vectors(test); 630 + 783 631 pci_release_regions(pdev); 784 632 pci_disable_device(pdev); 785 633 }
+1 -1
drivers/pci/controller/dwc/pci-dra7xx.c
··· 370 370 } 371 371 372 372 static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, 373 - enum pci_epc_irq_type type, u8 interrupt_num) 373 + enum pci_epc_irq_type type, u16 interrupt_num) 374 374 { 375 375 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 376 376 struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
-1
drivers/pci/controller/dwc/pci-exynos.c
··· 421 421 } 422 422 } 423 423 424 - pp->root_bus_nr = -1; 425 424 pp->ops = &exynos_pcie_host_ops; 426 425 427 426 ret = dw_pcie_host_init(pp);
-1
drivers/pci/controller/dwc/pci-imx6.c
··· 667 667 } 668 668 } 669 669 670 - pp->root_bus_nr = -1; 671 670 pp->ops = &imx6_pcie_host_ops; 672 671 673 672 ret = dw_pcie_host_init(pp);
-1
drivers/pci/controller/dwc/pci-keystone.c
··· 347 347 } 348 348 } 349 349 350 - pp->root_bus_nr = -1; 351 350 pp->ops = &keystone_pcie_host_ops; 352 351 ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np); 353 352 if (ret) {
-1
drivers/pci/controller/dwc/pcie-armada8k.c
··· 172 172 struct device *dev = &pdev->dev; 173 173 int ret; 174 174 175 - pp->root_bus_nr = -1; 176 175 pp->ops = &armada8k_pcie_host_ops; 177 176 178 177 pp->irq = platform_get_irq(pdev, 0);
+1 -2
drivers/pci/controller/dwc/pcie-artpec6.c
··· 399 399 } 400 400 } 401 401 402 - pp->root_bus_nr = -1; 403 402 pp->ops = &artpec6_pcie_host_ops; 404 403 405 404 ret = dw_pcie_host_init(pp); ··· 427 428 } 428 429 429 430 static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, 430 - enum pci_epc_irq_type type, u8 interrupt_num) 431 + enum pci_epc_irq_type type, u16 interrupt_num) 431 432 { 432 433 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 433 434
+185 -25
drivers/pci/controller/dwc/pcie-designware-ep.c
··· 40 40 __dw_pcie_ep_reset_bar(pci, bar, 0); 41 41 } 42 42 43 + static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie *pci, u8 cap_ptr, 44 + u8 cap) 45 + { 46 + u8 cap_id, next_cap_ptr; 47 + u16 reg; 48 + 49 + reg = dw_pcie_readw_dbi(pci, cap_ptr); 50 + next_cap_ptr = (reg & 0xff00) >> 8; 51 + cap_id = (reg & 0x00ff); 52 + 53 + if (!next_cap_ptr || cap_id > PCI_CAP_ID_MAX) 54 + return 0; 55 + 56 + if (cap_id == cap) 57 + return cap_ptr; 58 + 59 + return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap); 60 + } 61 + 62 + static u8 dw_pcie_ep_find_capability(struct dw_pcie *pci, u8 cap) 63 + { 64 + u8 next_cap_ptr; 65 + u16 reg; 66 + 67 + reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST); 68 + next_cap_ptr = (reg & 0x00ff); 69 + 70 + if (!next_cap_ptr) 71 + return 0; 72 + 73 + return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap); 74 + } 75 + 43 76 static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, 44 77 struct pci_epf_header *hdr) 45 78 { ··· 246 213 247 214 static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no) 248 215 { 249 - int val; 250 216 struct dw_pcie_ep *ep = epc_get_drvdata(epc); 251 217 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 218 + u32 val, reg; 252 219 253 - val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); 254 - if (!(val & MSI_CAP_MSI_EN_MASK)) 220 + if (!ep->msi_cap) 255 221 return -EINVAL; 256 222 257 - val = (val & MSI_CAP_MME_MASK) >> MSI_CAP_MME_SHIFT; 223 + reg = ep->msi_cap + PCI_MSI_FLAGS; 224 + val = dw_pcie_readw_dbi(pci, reg); 225 + if (!(val & PCI_MSI_FLAGS_ENABLE)) 226 + return -EINVAL; 227 + 228 + val = (val & PCI_MSI_FLAGS_QSIZE) >> 4; 229 + 258 230 return val; 259 231 } 260 232 261 - static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 encode_int) 233 + static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts) 262 234 { 263 - int val; 264 235 struct dw_pcie_ep *ep = epc_get_drvdata(epc); 265 236 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 237 + u32 val, reg; 266 238 267 - val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); 268 - val &= ~MSI_CAP_MMC_MASK; 269 - val |= (encode_int << MSI_CAP_MMC_SHIFT) & MSI_CAP_MMC_MASK; 239 + if (!ep->msi_cap) 240 + return -EINVAL; 241 + 242 + reg = ep->msi_cap + PCI_MSI_FLAGS; 243 + val = dw_pcie_readw_dbi(pci, reg); 244 + val &= ~PCI_MSI_FLAGS_QMASK; 245 + val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK; 270 246 dw_pcie_dbi_ro_wr_en(pci); 271 - dw_pcie_writew_dbi(pci, MSI_MESSAGE_CONTROL, val); 247 + dw_pcie_writew_dbi(pci, reg, val); 248 + dw_pcie_dbi_ro_wr_dis(pci); 249 + 250 + return 0; 251 + } 252 + 253 + static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no) 254 + { 255 + struct dw_pcie_ep *ep = epc_get_drvdata(epc); 256 + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 257 + u32 val, reg; 258 + 259 + if (!ep->msix_cap) 260 + return -EINVAL; 261 + 262 + reg = ep->msix_cap + PCI_MSIX_FLAGS; 263 + val = dw_pcie_readw_dbi(pci, reg); 264 + if (!(val & PCI_MSIX_FLAGS_ENABLE)) 265 + return -EINVAL; 266 + 267 + val &= PCI_MSIX_FLAGS_QSIZE; 268 + 269 + return val; 270 + } 271 + 272 + static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts) 273 + { 274 + struct dw_pcie_ep *ep = epc_get_drvdata(epc); 275 + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 276 + u32 val, reg; 277 + 278 + if (!ep->msix_cap) 279 + return -EINVAL; 280 + 281 + reg = ep->msix_cap + PCI_MSIX_FLAGS; 282 + val = dw_pcie_readw_dbi(pci, reg); 283 + val &= ~PCI_MSIX_FLAGS_QSIZE; 284 + val |= interrupts; 285 + dw_pcie_dbi_ro_wr_en(pci); 286 + dw_pcie_writew_dbi(pci, reg, val); 272 287 dw_pcie_dbi_ro_wr_dis(pci); 273 288 274 289 return 0; 275 290 } 276 291 277 292 static int dw_pcie_ep_raise_irq(struct pci_epc *epc, u8 func_no, 278 - enum pci_epc_irq_type type, u8 interrupt_num) 293 + enum pci_epc_irq_type type, u16 interrupt_num) 279 294 { 280 295 struct dw_pcie_ep *ep = epc_get_drvdata(epc); 281 296 ··· 363 282 .unmap_addr = dw_pcie_ep_unmap_addr, 364 283 .set_msi = dw_pcie_ep_set_msi, 365 284 .get_msi = dw_pcie_ep_get_msi, 285 + .set_msix = dw_pcie_ep_set_msix, 286 + .get_msix = dw_pcie_ep_get_msix, 366 287 .raise_irq = dw_pcie_ep_raise_irq, 367 288 .start = dw_pcie_ep_start, 368 289 .stop = dw_pcie_ep_stop, 369 290 }; 291 + 292 + int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no) 293 + { 294 + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 295 + struct device *dev = pci->dev; 296 + 297 + dev_err(dev, "EP cannot trigger legacy IRQs\n"); 298 + 299 + return -EINVAL; 300 + } 370 301 371 302 int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, 372 303 u8 interrupt_num) ··· 386 293 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 387 294 struct pci_epc *epc = ep->epc; 388 295 u16 msg_ctrl, msg_data; 389 - u32 msg_addr_lower, msg_addr_upper; 296 + u32 msg_addr_lower, msg_addr_upper, reg; 390 297 u64 msg_addr; 391 298 bool has_upper; 392 299 int ret; 393 300 301 + if (!ep->msi_cap) 302 + return -EINVAL; 303 + 394 304 /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */ 395 - msg_ctrl = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); 305 + reg = ep->msi_cap + PCI_MSI_FLAGS; 306 + msg_ctrl = dw_pcie_readw_dbi(pci, reg); 396 307 has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT); 397 - msg_addr_lower = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_L32); 308 + reg = ep->msi_cap + PCI_MSI_ADDRESS_LO; 309 + msg_addr_lower = dw_pcie_readl_dbi(pci, reg); 398 310 if (has_upper) { 399 - msg_addr_upper = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_U32); 400 - msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_64); 311 + reg = ep->msi_cap + PCI_MSI_ADDRESS_HI; 312 + msg_addr_upper = dw_pcie_readl_dbi(pci, reg); 313 + reg = ep->msi_cap + PCI_MSI_DATA_64; 314 + msg_data = dw_pcie_readw_dbi(pci, reg); 401 315 } else { 402 316 msg_addr_upper = 0; 403 - msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_32); 317 + reg = ep->msi_cap + PCI_MSI_DATA_32; 318 + msg_data = dw_pcie_readw_dbi(pci, reg); 404 319 } 405 320 msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower; 406 321 ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr, ··· 417 316 return ret; 418 317 419 318 writel(msg_data | (interrupt_num - 1), ep->msi_mem); 319 + 320 + dw_pcie_ep_unmap_addr(epc, func_no, ep->msi_mem_phys); 321 + 322 + return 0; 323 + } 324 + 325 + int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no, 326 + u16 interrupt_num) 327 + { 328 + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 329 + struct pci_epc *epc = ep->epc; 330 + u16 tbl_offset, bir; 331 + u32 bar_addr_upper, bar_addr_lower; 332 + u32 msg_addr_upper, msg_addr_lower; 333 + u32 reg, msg_data, vec_ctrl; 334 + u64 tbl_addr, msg_addr, reg_u64; 335 + void __iomem *msix_tbl; 336 + int ret; 337 + 338 + reg = ep->msix_cap + PCI_MSIX_TABLE; 339 + tbl_offset = dw_pcie_readl_dbi(pci, reg); 340 + bir = (tbl_offset & PCI_MSIX_TABLE_BIR); 341 + tbl_offset &= PCI_MSIX_TABLE_OFFSET; 342 + tbl_offset >>= 3; 343 + 344 + reg = PCI_BASE_ADDRESS_0 + (4 * bir); 345 + bar_addr_upper = 0; 346 + bar_addr_lower = dw_pcie_readl_dbi(pci, reg); 347 + reg_u64 = (bar_addr_lower & PCI_BASE_ADDRESS_MEM_TYPE_MASK); 348 + if (reg_u64 == PCI_BASE_ADDRESS_MEM_TYPE_64) 349 + bar_addr_upper = dw_pcie_readl_dbi(pci, reg + 4); 350 + 351 + tbl_addr = ((u64) bar_addr_upper) << 32 | bar_addr_lower; 352 + tbl_addr += (tbl_offset + ((interrupt_num - 1) * PCI_MSIX_ENTRY_SIZE)); 353 + tbl_addr &= PCI_BASE_ADDRESS_MEM_MASK; 354 + 355 + msix_tbl = ioremap_nocache(ep->phys_base + tbl_addr, 356 + PCI_MSIX_ENTRY_SIZE); 357 + if (!msix_tbl) 358 + return -EINVAL; 359 + 360 + msg_addr_lower = readl(msix_tbl + PCI_MSIX_ENTRY_LOWER_ADDR); 361 + msg_addr_upper = readl(msix_tbl + PCI_MSIX_ENTRY_UPPER_ADDR); 362 + msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower; 363 + msg_data = readl(msix_tbl + PCI_MSIX_ENTRY_DATA); 364 + vec_ctrl = readl(msix_tbl + PCI_MSIX_ENTRY_VECTOR_CTRL); 365 + 366 + iounmap(msix_tbl); 367 + 368 + if (vec_ctrl & PCI_MSIX_ENTRY_CTRL_MASKBIT) 369 + return -EPERM; 370 + 371 + ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr, 372 + epc->mem->page_size); 373 + if (ret) 374 + return ret; 375 + 376 + writel(msg_data, ep->msi_mem); 420 377 421 378 dw_pcie_ep_unmap_addr(epc, func_no, ep->msi_mem_phys); 422 379 ··· 545 386 return -ENOMEM; 546 387 ep->outbound_addr = addr; 547 388 548 - if (ep->ops->ep_init) 549 - ep->ops->ep_init(ep); 550 - 551 389 epc = devm_pci_epc_create(dev, &epc_ops); 552 390 if (IS_ERR(epc)) { 553 391 dev_err(dev, "Failed to create epc device\n"); 554 392 return PTR_ERR(epc); 555 393 } 394 + 395 + ep->epc = epc; 396 + epc_set_drvdata(epc, ep); 397 + 398 + if (ep->ops->ep_init) 399 + ep->ops->ep_init(ep); 556 400 557 401 ret = of_property_read_u8(np, "max-functions", &epc->max_functions); 558 402 if (ret < 0) ··· 571 409 ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep->msi_mem_phys, 572 410 epc->mem->page_size); 573 411 if (!ep->msi_mem) { 574 - dev_err(dev, "Failed to reserve memory for MSI\n"); 412 + dev_err(dev, "Failed to reserve memory for MSI/MSI-X\n"); 575 413 return -ENOMEM; 576 414 } 415 + ep->msi_cap = dw_pcie_ep_find_capability(pci, PCI_CAP_ID_MSI); 577 416 578 - epc->features = EPC_FEATURE_NO_LINKUP_NOTIFIER; 579 - EPC_FEATURE_SET_BAR(epc->features, BAR_0); 417 + ep->msix_cap = dw_pcie_ep_find_capability(pci, PCI_CAP_ID_MSIX); 580 418 581 - ep->epc = epc; 582 - epc_set_drvdata(epc, ep); 583 419 dw_pcie_setup(pci); 584 420 585 421 return 0;
+8 -4
drivers/pci/controller/dwc/pcie-designware-plat.c
··· 70 70 static void dw_plat_pcie_ep_init(struct dw_pcie_ep *ep) 71 71 { 72 72 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 73 + struct pci_epc *epc = ep->epc; 73 74 enum pci_barno bar; 74 75 75 76 for (bar = BAR_0; bar <= BAR_5; bar++) 76 77 dw_pcie_ep_reset_bar(pci, bar); 78 + 79 + epc->features |= EPC_FEATURE_NO_LINKUP_NOTIFIER; 80 + epc->features |= EPC_FEATURE_MSIX_AVAILABLE; 77 81 } 78 82 79 83 static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, 80 84 enum pci_epc_irq_type type, 81 - u8 interrupt_num) 85 + u16 interrupt_num) 82 86 { 83 87 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 84 88 85 89 switch (type) { 86 90 case PCI_EPC_IRQ_LEGACY: 87 - dev_err(pci->dev, "EP cannot trigger legacy IRQs\n"); 88 - return -EINVAL; 91 + return dw_pcie_ep_raise_legacy_irq(ep, func_no); 89 92 case PCI_EPC_IRQ_MSI: 90 93 return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); 94 + case PCI_EPC_IRQ_MSIX: 95 + return dw_pcie_ep_raise_msix_irq(ep, func_no, interrupt_num); 91 96 default: 92 97 dev_err(pci->dev, "UNKNOWN IRQ type\n"); 93 98 } ··· 123 118 return pp->msi_irq; 124 119 } 125 120 126 - pp->root_bus_nr = -1; 127 121 pp->ops = &dw_plat_pcie_host_ops; 128 122 129 123 ret = dw_pcie_host_init(pp);
+17 -12
drivers/pci/controller/dwc/pcie-designware.h
··· 96 96 #define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \ 97 97 ((0x3 << 20) | ((region) << 9) | (0x1 << 8)) 98 98 99 - #define MSI_MESSAGE_CONTROL 0x52 100 - #define MSI_CAP_MMC_SHIFT 1 101 - #define MSI_CAP_MMC_MASK (7 << MSI_CAP_MMC_SHIFT) 102 - #define MSI_CAP_MME_SHIFT 4 103 - #define MSI_CAP_MSI_EN_MASK 0x1 104 - #define MSI_CAP_MME_MASK (7 << MSI_CAP_MME_SHIFT) 105 - #define MSI_MESSAGE_ADDR_L32 0x54 106 - #define MSI_MESSAGE_ADDR_U32 0x58 107 - #define MSI_MESSAGE_DATA_32 0x58 108 - #define MSI_MESSAGE_DATA_64 0x5C 109 - 110 99 #define MAX_MSI_IRQS 256 111 100 #define MAX_MSI_IRQS_PER_CTRL 32 112 101 #define MAX_MSI_CTRLS (MAX_MSI_IRQS / MAX_MSI_IRQS_PER_CTRL) ··· 180 191 struct dw_pcie_ep_ops { 181 192 void (*ep_init)(struct dw_pcie_ep *ep); 182 193 int (*raise_irq)(struct dw_pcie_ep *ep, u8 func_no, 183 - enum pci_epc_irq_type type, u8 interrupt_num); 194 + enum pci_epc_irq_type type, u16 interrupt_num); 184 195 }; 185 196 186 197 struct dw_pcie_ep { ··· 197 208 u32 num_ob_windows; 198 209 void __iomem *msi_mem; 199 210 phys_addr_t msi_mem_phys; 211 + u8 msi_cap; /* MSI capability offset */ 212 + u8 msix_cap; /* MSI-X capability offset */ 200 213 }; 201 214 202 215 struct dw_pcie_ops { ··· 348 357 void dw_pcie_ep_linkup(struct dw_pcie_ep *ep); 349 358 int dw_pcie_ep_init(struct dw_pcie_ep *ep); 350 359 void dw_pcie_ep_exit(struct dw_pcie_ep *ep); 360 + int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no); 351 361 int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, 352 362 u8 interrupt_num); 363 + int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no, 364 + u16 interrupt_num); 353 365 void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar); 354 366 #else 355 367 static inline void dw_pcie_ep_linkup(struct dw_pcie_ep *ep) ··· 368 374 { 369 375 } 370 376 377 + static inline int dw_pcie_ep_raise_legacy_irq(struct dw_pcie_ep *ep, u8 func_no) 378 + { 379 + return 0; 380 + } 381 + 371 382 static inline int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, 372 383 u8 interrupt_num) 384 + { 385 + return 0; 386 + } 387 + 388 + static inline int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no, 389 + u16 interrupt_num) 373 390 { 374 391 return 0; 375 392 }
-1
drivers/pci/controller/dwc/pcie-histb.c
··· 420 420 phy_init(hipcie->phy); 421 421 } 422 422 423 - pp->root_bus_nr = -1; 424 423 pp->ops = &histb_pcie_host_ops; 425 424 426 425 platform_set_drvdata(pdev, hipcie);
+28
drivers/pci/controller/dwc/pcie-kirin.c
··· 430 430 { 431 431 kirin_pcie_establish_link(pp); 432 432 433 + if (IS_ENABLED(CONFIG_PCI_MSI)) 434 + dw_pcie_msi_init(pp); 435 + 433 436 return 0; 434 437 } 435 438 ··· 448 445 .host_init = kirin_pcie_host_init, 449 446 }; 450 447 448 + static int kirin_pcie_add_msi(struct dw_pcie *pci, 449 + struct platform_device *pdev) 450 + { 451 + int irq; 452 + 453 + if (IS_ENABLED(CONFIG_PCI_MSI)) { 454 + irq = platform_get_irq(pdev, 0); 455 + if (irq < 0) { 456 + dev_err(&pdev->dev, 457 + "failed to get MSI IRQ (%d)\n", irq); 458 + return irq; 459 + } 460 + 461 + pci->pp.msi_irq = irq; 462 + } 463 + 464 + return 0; 465 + } 466 + 451 467 static int __init kirin_add_pcie_port(struct dw_pcie *pci, 452 468 struct platform_device *pdev) 453 469 { 470 + int ret; 471 + 472 + ret = kirin_pcie_add_msi(pci, pdev); 473 + if (ret) 474 + return ret; 475 + 454 476 pci->pp.ops = &kirin_pcie_host_ops; 455 477 456 478 return dw_pcie_host_init(&pci->pp);
-1
drivers/pci/controller/dwc/pcie-qcom.c
··· 1251 1251 if (ret) 1252 1252 return ret; 1253 1253 1254 - pp->root_bus_nr = -1; 1255 1254 pp->ops = &qcom_pcie_dw_ops; 1256 1255 1257 1256 if (IS_ENABLED(CONFIG_PCI_MSI)) {
-1
drivers/pci/controller/dwc/pcie-spear13xx.c
··· 210 210 return ret; 211 211 } 212 212 213 - pp->root_bus_nr = -1; 214 213 pp->ops = &spear13xx_pcie_host_ops; 215 214 216 215 ret = dw_pcie_host_init(pp);
+2 -1
drivers/pci/controller/pcie-cadence-ep.c
··· 362 362 } 363 363 364 364 static int cdns_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn, 365 - enum pci_epc_irq_type type, u8 interrupt_num) 365 + enum pci_epc_irq_type type, 366 + u16 interrupt_num) 366 367 { 367 368 struct cdns_pcie_ep *ep = epc_get_drvdata(epc); 368 369
+1 -1
drivers/pci/controller/pcie-rockchip-ep.c
··· 472 472 473 473 static int rockchip_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn, 474 474 enum pci_epc_irq_type type, 475 - u8 interrupt_num) 475 + u16 interrupt_num) 476 476 { 477 477 struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); 478 478
+66 -20
drivers/pci/endpoint/functions/pci-epf-test.c
··· 18 18 #include <linux/pci-epf.h> 19 19 #include <linux/pci_regs.h> 20 20 21 + #define IRQ_TYPE_LEGACY 0 22 + #define IRQ_TYPE_MSI 1 23 + #define IRQ_TYPE_MSIX 2 24 + 21 25 #define COMMAND_RAISE_LEGACY_IRQ BIT(0) 22 26 #define COMMAND_RAISE_MSI_IRQ BIT(1) 23 - #define MSI_NUMBER_SHIFT 2 24 - #define MSI_NUMBER_MASK (0x3f << MSI_NUMBER_SHIFT) 25 - #define COMMAND_READ BIT(8) 26 - #define COMMAND_WRITE BIT(9) 27 - #define COMMAND_COPY BIT(10) 27 + #define COMMAND_RAISE_MSIX_IRQ BIT(2) 28 + #define COMMAND_READ BIT(3) 29 + #define COMMAND_WRITE BIT(4) 30 + #define COMMAND_COPY BIT(5) 28 31 29 32 #define STATUS_READ_SUCCESS BIT(0) 30 33 #define STATUS_READ_FAIL BIT(1) ··· 48 45 struct pci_epf *epf; 49 46 enum pci_barno test_reg_bar; 50 47 bool linkup_notifier; 48 + bool msix_available; 51 49 struct delayed_work cmd_handler; 52 50 }; 53 51 ··· 60 56 u64 dst_addr; 61 57 u32 size; 62 58 u32 checksum; 59 + u32 irq_type; 60 + u32 irq_number; 63 61 } __packed; 64 62 65 63 static struct pci_epf_header test_header = { ··· 250 244 return ret; 251 245 } 252 246 253 - static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq) 247 + static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test, u8 irq_type, 248 + u16 irq) 254 249 { 255 - u8 msi_count; 256 250 struct pci_epf *epf = epf_test->epf; 251 + struct device *dev = &epf->dev; 257 252 struct pci_epc *epc = epf->epc; 258 253 enum pci_barno test_reg_bar = epf_test->test_reg_bar; 259 254 struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; 260 255 261 256 reg->status |= STATUS_IRQ_RAISED; 262 - msi_count = pci_epc_get_msi(epc, epf->func_no); 263 - if (irq > msi_count || msi_count <= 0) 257 + 258 + switch (irq_type) { 259 + case IRQ_TYPE_LEGACY: 264 260 pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_LEGACY, 0); 265 - else 261 + break; 262 + case IRQ_TYPE_MSI: 266 263 pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_MSI, irq); 264 + break; 265 + case IRQ_TYPE_MSIX: 266 + pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_MSIX, irq); 267 + break; 268 + default: 269 + dev_err(dev, "Failed to raise IRQ, unknown type\n"); 270 + break; 271 + } 267 272 } 268 273 269 274 static void pci_epf_test_cmd_handler(struct work_struct *work) 270 275 { 271 276 int ret; 272 - u8 irq; 273 - u8 msi_count; 277 + int count; 274 278 u32 command; 275 279 struct pci_epf_test *epf_test = container_of(work, struct pci_epf_test, 276 280 cmd_handler.work); 277 281 struct pci_epf *epf = epf_test->epf; 282 + struct device *dev = &epf->dev; 278 283 struct pci_epc *epc = epf->epc; 279 284 enum pci_barno test_reg_bar = epf_test->test_reg_bar; 280 285 struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar]; ··· 297 280 reg->command = 0; 298 281 reg->status = 0; 299 282 300 - irq = (command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT; 283 + if (reg->irq_type > IRQ_TYPE_MSIX) { 284 + dev_err(dev, "Failed to detect IRQ type\n"); 285 + goto reset_handler; 286 + } 301 287 302 288 if (command & COMMAND_RAISE_LEGACY_IRQ) { 303 289 reg->status = STATUS_IRQ_RAISED; ··· 314 294 reg->status |= STATUS_WRITE_FAIL; 315 295 else 316 296 reg->status |= STATUS_WRITE_SUCCESS; 317 - pci_epf_test_raise_irq(epf_test, irq); 297 + pci_epf_test_raise_irq(epf_test, reg->irq_type, 298 + reg->irq_number); 318 299 goto reset_handler; 319 300 } 320 301 ··· 325 304 reg->status |= STATUS_READ_SUCCESS; 326 305 else 327 306 reg->status |= STATUS_READ_FAIL; 328 - pci_epf_test_raise_irq(epf_test, irq); 307 + pci_epf_test_raise_irq(epf_test, reg->irq_type, 308 + reg->irq_number); 329 309 goto reset_handler; 330 310 } 331 311 ··· 336 314 reg->status |= STATUS_COPY_SUCCESS; 337 315 else 338 316 reg->status |= STATUS_COPY_FAIL; 339 - pci_epf_test_raise_irq(epf_test, irq); 317 + pci_epf_test_raise_irq(epf_test, reg->irq_type, 318 + reg->irq_number); 340 319 goto reset_handler; 341 320 } 342 321 343 322 if (command & COMMAND_RAISE_MSI_IRQ) { 344 - msi_count = pci_epc_get_msi(epc, epf->func_no); 345 - if (irq > msi_count || msi_count <= 0) 323 + count = pci_epc_get_msi(epc, epf->func_no); 324 + if (reg->irq_number > count || count <= 0) 346 325 goto reset_handler; 347 326 reg->status = STATUS_IRQ_RAISED; 348 - pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_MSI, irq); 327 + pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_MSI, 328 + reg->irq_number); 329 + goto reset_handler; 330 + } 331 + 332 + if (command & COMMAND_RAISE_MSIX_IRQ) { 333 + count = pci_epc_get_msix(epc, epf->func_no); 334 + if (reg->irq_number > count || count <= 0) 335 + goto reset_handler; 336 + reg->status = STATUS_IRQ_RAISED; 337 + pci_epc_raise_irq(epc, epf->func_no, PCI_EPC_IRQ_MSIX, 338 + reg->irq_number); 349 339 goto reset_handler; 350 340 } 351 341 ··· 474 440 else 475 441 epf_test->linkup_notifier = true; 476 442 443 + epf_test->msix_available = epc->features & EPC_FEATURE_MSIX_AVAILABLE; 444 + 477 445 epf_test->test_reg_bar = EPC_FEATURE_GET_BAR(epc->features); 478 446 479 447 ret = pci_epc_write_header(epc, epf->func_no, header); ··· 493 457 return ret; 494 458 495 459 ret = pci_epc_set_msi(epc, epf->func_no, epf->msi_interrupts); 496 - if (ret) 460 + if (ret) { 461 + dev_err(dev, "MSI configuration failed\n"); 497 462 return ret; 463 + } 464 + 465 + if (epf_test->msix_available) { 466 + ret = pci_epc_set_msix(epc, epf->func_no, epf->msix_interrupts); 467 + if (ret) { 468 + dev_err(dev, "MSI-X configuration failed\n"); 469 + return ret; 470 + } 471 + } 498 472 499 473 if (!epf_test->linkup_notifier) 500 474 queue_work(kpcitest_workqueue, &epf_test->cmd_handler.work);
+24
drivers/pci/endpoint/pci-ep-cfs.c
··· 286 286 to_pci_epf_group(item)->epf->msi_interrupts); 287 287 } 288 288 289 + static ssize_t pci_epf_msix_interrupts_store(struct config_item *item, 290 + const char *page, size_t len) 291 + { 292 + u16 val; 293 + int ret; 294 + 295 + ret = kstrtou16(page, 0, &val); 296 + if (ret) 297 + return ret; 298 + 299 + to_pci_epf_group(item)->epf->msix_interrupts = val; 300 + 301 + return len; 302 + } 303 + 304 + static ssize_t pci_epf_msix_interrupts_show(struct config_item *item, 305 + char *page) 306 + { 307 + return sprintf(page, "%d\n", 308 + to_pci_epf_group(item)->epf->msix_interrupts); 309 + } 310 + 289 311 PCI_EPF_HEADER_R(vendorid) 290 312 PCI_EPF_HEADER_W_u16(vendorid) 291 313 ··· 349 327 CONFIGFS_ATTR(pci_epf_, subsys_id); 350 328 CONFIGFS_ATTR(pci_epf_, interrupt_pin); 351 329 CONFIGFS_ATTR(pci_epf_, msi_interrupts); 330 + CONFIGFS_ATTR(pci_epf_, msix_interrupts); 352 331 353 332 static struct configfs_attribute *pci_epf_attrs[] = { 354 333 &pci_epf_attr_vendorid, ··· 363 340 &pci_epf_attr_subsys_id, 364 341 &pci_epf_attr_interrupt_pin, 365 342 &pci_epf_attr_msi_interrupts, 343 + &pci_epf_attr_msix_interrupts, 366 344 NULL, 367 345 }; 368 346
+63 -5
drivers/pci/endpoint/pci-epc-core.c
··· 131 131 * pci_epc_raise_irq() - interrupt the host system 132 132 * @epc: the EPC device which has to interrupt the host 133 133 * @func_no: the endpoint function number in the EPC device 134 - * @type: specify the type of interrupt; legacy or MSI 135 - * @interrupt_num: the MSI interrupt number 134 + * @type: specify the type of interrupt; legacy, MSI or MSI-X 135 + * @interrupt_num: the MSI or MSI-X interrupt number 136 136 * 137 - * Invoke to raise an MSI or legacy interrupt 137 + * Invoke to raise an legacy, MSI or MSI-X interrupt 138 138 */ 139 139 int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no, 140 - enum pci_epc_irq_type type, u8 interrupt_num) 140 + enum pci_epc_irq_type type, u16 interrupt_num) 141 141 { 142 142 int ret; 143 143 unsigned long flags; ··· 201 201 u8 encode_int; 202 202 unsigned long flags; 203 203 204 - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) 204 + if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || 205 + interrupts > 32) 205 206 return -EINVAL; 206 207 207 208 if (!epc->ops->set_msi) ··· 217 216 return ret; 218 217 } 219 218 EXPORT_SYMBOL_GPL(pci_epc_set_msi); 219 + 220 + /** 221 + * pci_epc_get_msix() - get the number of MSI-X interrupt numbers allocated 222 + * @epc: the EPC device to which MSI-X interrupts was requested 223 + * @func_no: the endpoint function number in the EPC device 224 + * 225 + * Invoke to get the number of MSI-X interrupts allocated by the RC 226 + */ 227 + int pci_epc_get_msix(struct pci_epc *epc, u8 func_no) 228 + { 229 + int interrupt; 230 + unsigned long flags; 231 + 232 + if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) 233 + return 0; 234 + 235 + if (!epc->ops->get_msix) 236 + return 0; 237 + 238 + spin_lock_irqsave(&epc->lock, flags); 239 + interrupt = epc->ops->get_msix(epc, func_no); 240 + spin_unlock_irqrestore(&epc->lock, flags); 241 + 242 + if (interrupt < 0) 243 + return 0; 244 + 245 + return interrupt + 1; 246 + } 247 + EXPORT_SYMBOL_GPL(pci_epc_get_msix); 248 + 249 + /** 250 + * pci_epc_set_msix() - set the number of MSI-X interrupt numbers required 251 + * @epc: the EPC device on which MSI-X has to be configured 252 + * @func_no: the endpoint function number in the EPC device 253 + * @interrupts: number of MSI-X interrupts required by the EPF 254 + * 255 + * Invoke to set the required number of MSI-X interrupts. 256 + */ 257 + int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts) 258 + { 259 + int ret; 260 + unsigned long flags; 261 + 262 + if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || 263 + interrupts < 1 || interrupts > 2048) 264 + return -EINVAL; 265 + 266 + if (!epc->ops->set_msix) 267 + return 0; 268 + 269 + spin_lock_irqsave(&epc->lock, flags); 270 + ret = epc->ops->set_msix(epc, func_no, interrupts - 1); 271 + spin_unlock_irqrestore(&epc->lock, flags); 272 + 273 + return ret; 274 + } 275 + EXPORT_SYMBOL_GPL(pci_epc_set_msix); 220 276 221 277 /** 222 278 * pci_epc_unmap_addr() - unmap CPU address from PCI address
+13 -3
include/linux/pci-epc.h
··· 17 17 PCI_EPC_IRQ_UNKNOWN, 18 18 PCI_EPC_IRQ_LEGACY, 19 19 PCI_EPC_IRQ_MSI, 20 + PCI_EPC_IRQ_MSIX, 20 21 }; 21 22 22 23 /** ··· 31 30 * capability register 32 31 * @get_msi: ops to get the number of MSI interrupts allocated by the RC from 33 32 * the MSI capability register 34 - * @raise_irq: ops to raise a legacy or MSI interrupt 33 + * @set_msix: ops to set the requested number of MSI-X interrupts in the 34 + * MSI-X capability register 35 + * @get_msix: ops to get the number of MSI-X interrupts allocated by the RC 36 + * from the MSI-X capability register 37 + * @raise_irq: ops to raise a legacy, MSI or MSI-X interrupt 35 38 * @start: ops to start the PCI link 36 39 * @stop: ops to stop the PCI link 37 40 * @owner: the module owner containing the ops ··· 53 48 phys_addr_t addr); 54 49 int (*set_msi)(struct pci_epc *epc, u8 func_no, u8 interrupts); 55 50 int (*get_msi)(struct pci_epc *epc, u8 func_no); 51 + int (*set_msix)(struct pci_epc *epc, u8 func_no, u16 interrupts); 52 + int (*get_msix)(struct pci_epc *epc, u8 func_no); 56 53 int (*raise_irq)(struct pci_epc *epc, u8 func_no, 57 - enum pci_epc_irq_type type, u8 interrupt_num); 54 + enum pci_epc_irq_type type, u16 interrupt_num); 58 55 int (*start)(struct pci_epc *epc); 59 56 void (*stop)(struct pci_epc *epc); 60 57 struct module *owner; ··· 102 95 103 96 #define EPC_FEATURE_NO_LINKUP_NOTIFIER BIT(0) 104 97 #define EPC_FEATURE_BAR_MASK (BIT(1) | BIT(2) | BIT(3)) 98 + #define EPC_FEATURE_MSIX_AVAILABLE BIT(4) 105 99 #define EPC_FEATURE_SET_BAR(features, bar) \ 106 100 (features |= (EPC_FEATURE_BAR_MASK & (bar << 1))) 107 101 #define EPC_FEATURE_GET_BAR(features) \ ··· 152 144 phys_addr_t phys_addr); 153 145 int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts); 154 146 int pci_epc_get_msi(struct pci_epc *epc, u8 func_no); 147 + int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts); 148 + int pci_epc_get_msix(struct pci_epc *epc, u8 func_no); 155 149 int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no, 156 - enum pci_epc_irq_type type, u8 interrupt_num); 150 + enum pci_epc_irq_type type, u16 interrupt_num); 157 151 int pci_epc_start(struct pci_epc *epc); 158 152 void pci_epc_stop(struct pci_epc *epc); 159 153 struct pci_epc *pci_epc_get(const char *epc_name);
+1
include/linux/pci-epf.h
··· 119 119 struct pci_epf_header *header; 120 120 struct pci_epf_bar bar[6]; 121 121 u8 msi_interrupts; 122 + u16 msix_interrupts; 122 123 u8 func_no; 123 124 124 125 struct pci_epc *epc;
+3
include/uapi/linux/pcitest.h
··· 16 16 #define PCITEST_WRITE _IOW('P', 0x4, unsigned long) 17 17 #define PCITEST_READ _IOW('P', 0x5, unsigned long) 18 18 #define PCITEST_COPY _IOW('P', 0x6, unsigned long) 19 + #define PCITEST_MSIX _IOW('P', 0x7, int) 20 + #define PCITEST_SET_IRQTYPE _IOW('P', 0x8, int) 21 + #define PCITEST_GET_IRQTYPE _IO('P', 0x9) 19 22 20 23 #endif /* __UAPI_LINUX_PCITEST_H */
+50 -1
tools/pci/pcitest.c
··· 31 31 #define BILLION 1E9 32 32 33 33 static char *result[] = { "NOT OKAY", "OKAY" }; 34 + static char *irq[] = { "LEGACY", "MSI", "MSI-X" }; 34 35 35 36 struct pci_test { 36 37 char *device; 37 38 char barnum; 38 39 bool legacyirq; 39 40 unsigned int msinum; 41 + unsigned int msixnum; 42 + int irqtype; 43 + bool set_irqtype; 44 + bool get_irqtype; 40 45 bool read; 41 46 bool write; 42 47 bool copy; ··· 70 65 fprintf(stdout, "%s\n", result[ret]); 71 66 } 72 67 68 + if (test->set_irqtype) { 69 + ret = ioctl(fd, PCITEST_SET_IRQTYPE, test->irqtype); 70 + fprintf(stdout, "SET IRQ TYPE TO %s:\t\t", irq[test->irqtype]); 71 + if (ret < 0) 72 + fprintf(stdout, "FAILED\n"); 73 + else 74 + fprintf(stdout, "%s\n", result[ret]); 75 + } 76 + 77 + if (test->get_irqtype) { 78 + ret = ioctl(fd, PCITEST_GET_IRQTYPE); 79 + fprintf(stdout, "GET IRQ TYPE:\t\t"); 80 + if (ret < 0) 81 + fprintf(stdout, "FAILED\n"); 82 + else 83 + fprintf(stdout, "%s\n", irq[ret]); 84 + } 85 + 73 86 if (test->legacyirq) { 74 87 ret = ioctl(fd, PCITEST_LEGACY_IRQ, 0); 75 88 fprintf(stdout, "LEGACY IRQ:\t"); ··· 100 77 if (test->msinum > 0 && test->msinum <= 32) { 101 78 ret = ioctl(fd, PCITEST_MSI, test->msinum); 102 79 fprintf(stdout, "MSI%d:\t\t", test->msinum); 80 + if (ret < 0) 81 + fprintf(stdout, "TEST FAILED\n"); 82 + else 83 + fprintf(stdout, "%s\n", result[ret]); 84 + } 85 + 86 + if (test->msixnum > 0 && test->msixnum <= 2048) { 87 + ret = ioctl(fd, PCITEST_MSIX, test->msixnum); 88 + fprintf(stdout, "MSI-X%d:\t\t", test->msixnum); 103 89 if (ret < 0) 104 90 fprintf(stdout, "TEST FAILED\n"); 105 91 else ··· 165 133 /* set default endpoint device */ 166 134 test->device = "/dev/pci-endpoint-test.0"; 167 135 168 - while ((c = getopt(argc, argv, "D:b:m:lrwcs:")) != EOF) 136 + while ((c = getopt(argc, argv, "D:b:m:x:i:Ilrwcs:")) != EOF) 169 137 switch (c) { 170 138 case 'D': 171 139 test->device = optarg; ··· 182 150 test->msinum = atoi(optarg); 183 151 if (test->msinum < 1 || test->msinum > 32) 184 152 goto usage; 153 + continue; 154 + case 'x': 155 + test->msixnum = atoi(optarg); 156 + if (test->msixnum < 1 || test->msixnum > 2048) 157 + goto usage; 158 + continue; 159 + case 'i': 160 + test->irqtype = atoi(optarg); 161 + if (test->irqtype < 0 || test->irqtype > 2) 162 + goto usage; 163 + test->set_irqtype = true; 164 + continue; 165 + case 'I': 166 + test->get_irqtype = true; 185 167 continue; 186 168 case 'r': 187 169 test->read = true; ··· 219 173 "\t-D <dev> PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n" 220 174 "\t-b <bar num> BAR test (bar number between 0..5)\n" 221 175 "\t-m <msi num> MSI test (msi number between 1..32)\n" 176 + "\t-x <msix num> \tMSI-X test (msix number between 1..2048)\n" 177 + "\t-i <irq type> \tSet IRQ type (0 - Legacy, 1 - MSI, 2 - MSI-X)\n" 178 + "\t-I Get current IRQ type configured\n" 222 179 "\t-l Legacy IRQ test\n" 223 180 "\t-r Read buffer test\n" 224 181 "\t-w Write buffer test\n"
+15
tools/pci/pcitest.sh
··· 16 16 echo "Interrupt tests" 17 17 echo 18 18 19 + pcitest -i 0 19 20 pcitest -l 21 + 22 + pcitest -i 1 20 23 msi=1 21 24 22 25 while [ $msi -lt 33 ] ··· 29 26 done 30 27 echo 31 28 29 + pcitest -i 2 30 + msix=1 31 + 32 + while [ $msix -lt 2049 ] 33 + do 34 + pcitest -x $msix 35 + msix=`expr $msix + 1` 36 + done 37 + echo 38 + 32 39 echo "Read Tests" 33 40 echo 41 + 42 + pcitest -i 1 34 43 35 44 pcitest -r -s 1 36 45 pcitest -r -s 1024