diff options
Diffstat (limited to 'drivers/misc/pci_endpoint_test.c')
-rw-r--r-- | drivers/misc/pci_endpoint_test.c | 290 |
1 files changed, 222 insertions, 68 deletions
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 7b370466a227..896e2df9400f 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c | |||
@@ -35,38 +35,45 @@ | |||
35 | 35 | ||
36 | #include <uapi/linux/pcitest.h> | 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 | 41 | #define IRQ_TYPE_LEGACY 0 | |
42 | #define PCI_ENDPOINT_TEST_COMMAND 0x4 | 42 | #define IRQ_TYPE_MSI 1 |
43 | #define COMMAND_RAISE_LEGACY_IRQ BIT(0) | 43 | #define IRQ_TYPE_MSIX 2 |
44 | #define COMMAND_RAISE_MSI_IRQ BIT(1) | 44 | |
45 | #define MSI_NUMBER_SHIFT 2 | 45 | #define PCI_ENDPOINT_TEST_MAGIC 0x0 |
46 | /* 6 bits for MSI number */ | 46 | |
47 | #define COMMAND_READ BIT(8) | 47 | #define PCI_ENDPOINT_TEST_COMMAND 0x4 |
48 | #define COMMAND_WRITE BIT(9) | 48 | #define COMMAND_RAISE_LEGACY_IRQ BIT(0) |
49 | #define COMMAND_COPY BIT(10) | 49 | #define COMMAND_RAISE_MSI_IRQ BIT(1) |
50 | 50 | #define COMMAND_RAISE_MSIX_IRQ BIT(2) | |
51 | #define PCI_ENDPOINT_TEST_STATUS 0x8 | 51 | #define COMMAND_READ BIT(3) |
52 | #define STATUS_READ_SUCCESS BIT(0) | 52 | #define COMMAND_WRITE BIT(4) |
53 | #define STATUS_READ_FAIL BIT(1) | 53 | #define COMMAND_COPY BIT(5) |
54 | #define STATUS_WRITE_SUCCESS BIT(2) | 54 | |
55 | #define STATUS_WRITE_FAIL BIT(3) | 55 | #define PCI_ENDPOINT_TEST_STATUS 0x8 |
56 | #define STATUS_COPY_SUCCESS BIT(4) | 56 | #define STATUS_READ_SUCCESS BIT(0) |
57 | #define STATUS_COPY_FAIL BIT(5) | 57 | #define STATUS_READ_FAIL BIT(1) |
58 | #define STATUS_IRQ_RAISED BIT(6) | 58 | #define STATUS_WRITE_SUCCESS BIT(2) |
59 | #define STATUS_SRC_ADDR_INVALID BIT(7) | 59 | #define STATUS_WRITE_FAIL BIT(3) |
60 | #define STATUS_DST_ADDR_INVALID BIT(8) | 60 | #define STATUS_COPY_SUCCESS BIT(4) |
61 | 61 | #define STATUS_COPY_FAIL BIT(5) | |
62 | #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0xc | 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 | #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10 | 67 | #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10 |
64 | 68 | ||
65 | #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14 | 69 | #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14 |
66 | #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18 | 70 | #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18 |
67 | 71 | ||
68 | #define PCI_ENDPOINT_TEST_SIZE 0x1c | 72 | #define PCI_ENDPOINT_TEST_SIZE 0x1c |
69 | #define PCI_ENDPOINT_TEST_CHECKSUM 0x20 | 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 | static DEFINE_IDA(pci_endpoint_test_ida); | 78 | static DEFINE_IDA(pci_endpoint_test_ida); |
72 | 79 | ||
@@ -77,6 +84,10 @@ static bool no_msi; | |||
77 | module_param(no_msi, bool, 0444); | 84 | module_param(no_msi, bool, 0444); |
78 | MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test"); | 85 | MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test"); |
79 | 86 | ||
87 | static int irq_type = IRQ_TYPE_MSI; | ||
88 | module_param(irq_type, int, 0444); | ||
89 | MODULE_PARM_DESC(irq_type, "IRQ mode selection in pci_endpoint_test (0 - Legacy, 1 - MSI, 2 - MSI-X)"); | ||
90 | |||
80 | enum pci_barno { | 91 | enum pci_barno { |
81 | BAR_0, | 92 | BAR_0, |
82 | BAR_1, | 93 | BAR_1, |
@@ -103,7 +114,7 @@ struct pci_endpoint_test { | |||
103 | struct pci_endpoint_test_data { | 114 | struct pci_endpoint_test_data { |
104 | enum pci_barno test_reg_bar; | 115 | enum pci_barno test_reg_bar; |
105 | size_t alignment; | 116 | size_t alignment; |
106 | bool no_msi; | 117 | int irq_type; |
107 | }; | 118 | }; |
108 | 119 | ||
109 | static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test, | 120 | static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test, |
@@ -147,6 +158,100 @@ static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id) | |||
147 | return IRQ_HANDLED; | 158 | return IRQ_HANDLED; |
148 | } | 159 | } |
149 | 160 | ||
161 | static void pci_endpoint_test_free_irq_vectors(struct pci_endpoint_test *test) | ||
162 | { | ||
163 | struct pci_dev *pdev = test->pdev; | ||
164 | |||
165 | pci_free_irq_vectors(pdev); | ||
166 | } | ||
167 | |||
168 | static bool pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test, | ||
169 | int type) | ||
170 | { | ||
171 | int irq = -1; | ||
172 | struct pci_dev *pdev = test->pdev; | ||
173 | struct device *dev = &pdev->dev; | ||
174 | bool res = true; | ||
175 | |||
176 | switch (type) { | ||
177 | case IRQ_TYPE_LEGACY: | ||
178 | irq = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_LEGACY); | ||
179 | if (irq < 0) | ||
180 | dev_err(dev, "Failed to get Legacy interrupt\n"); | ||
181 | break; | ||
182 | case IRQ_TYPE_MSI: | ||
183 | irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); | ||
184 | if (irq < 0) | ||
185 | dev_err(dev, "Failed to get MSI interrupts\n"); | ||
186 | break; | ||
187 | case IRQ_TYPE_MSIX: | ||
188 | irq = pci_alloc_irq_vectors(pdev, 1, 2048, PCI_IRQ_MSIX); | ||
189 | if (irq < 0) | ||
190 | dev_err(dev, "Failed to get MSI-X interrupts\n"); | ||
191 | break; | ||
192 | default: | ||
193 | dev_err(dev, "Invalid IRQ type selected\n"); | ||
194 | } | ||
195 | |||
196 | if (irq < 0) { | ||
197 | irq = 0; | ||
198 | res = false; | ||
199 | } | ||
200 | test->num_irqs = irq; | ||
201 | |||
202 | return res; | ||
203 | } | ||
204 | |||
205 | static void pci_endpoint_test_release_irq(struct pci_endpoint_test *test) | ||
206 | { | ||
207 | int i; | ||
208 | struct pci_dev *pdev = test->pdev; | ||
209 | struct device *dev = &pdev->dev; | ||
210 | |||
211 | for (i = 0; i < test->num_irqs; i++) | ||
212 | devm_free_irq(dev, pci_irq_vector(pdev, i), test); | ||
213 | |||
214 | test->num_irqs = 0; | ||
215 | } | ||
216 | |||
217 | static bool pci_endpoint_test_request_irq(struct pci_endpoint_test *test) | ||
218 | { | ||
219 | int i; | ||
220 | int err; | ||
221 | struct pci_dev *pdev = test->pdev; | ||
222 | struct device *dev = &pdev->dev; | ||
223 | |||
224 | for (i = 0; i < test->num_irqs; i++) { | ||
225 | err = devm_request_irq(dev, pci_irq_vector(pdev, i), | ||
226 | pci_endpoint_test_irqhandler, | ||
227 | IRQF_SHARED, DRV_MODULE_NAME, test); | ||
228 | if (err) | ||
229 | goto fail; | ||
230 | } | ||
231 | |||
232 | return true; | ||
233 | |||
234 | fail: | ||
235 | switch (irq_type) { | ||
236 | case IRQ_TYPE_LEGACY: | ||
237 | dev_err(dev, "Failed to request IRQ %d for Legacy\n", | ||
238 | pci_irq_vector(pdev, i)); | ||
239 | break; | ||
240 | case IRQ_TYPE_MSI: | ||
241 | dev_err(dev, "Failed to request IRQ %d for MSI %d\n", | ||
242 | pci_irq_vector(pdev, i), | ||
243 | i + 1); | ||
244 | break; | ||
245 | case IRQ_TYPE_MSIX: | ||
246 | dev_err(dev, "Failed to request IRQ %d for MSI-X %d\n", | ||
247 | pci_irq_vector(pdev, i), | ||
248 | i + 1); | ||
249 | break; | ||
250 | } | ||
251 | |||
252 | return false; | ||
253 | } | ||
254 | |||
150 | static bool pci_endpoint_test_bar(struct pci_endpoint_test *test, | 255 | static bool pci_endpoint_test_bar(struct pci_endpoint_test *test, |
151 | enum pci_barno barno) | 256 | enum pci_barno barno) |
152 | { | 257 | { |
@@ -179,6 +284,9 @@ static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test) | |||
179 | { | 284 | { |
180 | u32 val; | 285 | u32 val; |
181 | 286 | ||
287 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, | ||
288 | IRQ_TYPE_LEGACY); | ||
289 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 0); | ||
182 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, | 290 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, |
183 | COMMAND_RAISE_LEGACY_IRQ); | 291 | COMMAND_RAISE_LEGACY_IRQ); |
184 | val = wait_for_completion_timeout(&test->irq_raised, | 292 | val = wait_for_completion_timeout(&test->irq_raised, |
@@ -190,14 +298,18 @@ static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test) | |||
190 | } | 298 | } |
191 | 299 | ||
192 | static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, | 300 | static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, |
193 | u8 msi_num) | 301 | u16 msi_num, bool msix) |
194 | { | 302 | { |
195 | u32 val; | 303 | u32 val; |
196 | struct pci_dev *pdev = test->pdev; | 304 | struct pci_dev *pdev = test->pdev; |
197 | 305 | ||
306 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, | ||
307 | msix == false ? IRQ_TYPE_MSI : | ||
308 | IRQ_TYPE_MSIX); | ||
309 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, msi_num); | ||
198 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, | 310 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, |
199 | msi_num << MSI_NUMBER_SHIFT | | 311 | msix == false ? COMMAND_RAISE_MSI_IRQ : |
200 | COMMAND_RAISE_MSI_IRQ); | 312 | COMMAND_RAISE_MSIX_IRQ); |
201 | val = wait_for_completion_timeout(&test->irq_raised, | 313 | val = wait_for_completion_timeout(&test->irq_raised, |
202 | msecs_to_jiffies(1000)); | 314 | msecs_to_jiffies(1000)); |
203 | if (!val) | 315 | if (!val) |
@@ -230,6 +342,11 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) | |||
230 | if (size > SIZE_MAX - alignment) | 342 | if (size > SIZE_MAX - alignment) |
231 | goto err; | 343 | goto err; |
232 | 344 | ||
345 | if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { | ||
346 | dev_err(dev, "Invalid IRQ type option\n"); | ||
347 | goto err; | ||
348 | } | ||
349 | |||
233 | orig_src_addr = dma_alloc_coherent(dev, size + alignment, | 350 | orig_src_addr = dma_alloc_coherent(dev, size + alignment, |
234 | &orig_src_phys_addr, GFP_KERNEL); | 351 | &orig_src_phys_addr, GFP_KERNEL); |
235 | if (!orig_src_addr) { | 352 | if (!orig_src_addr) { |
@@ -281,8 +398,10 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) | |||
281 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, | 398 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, |
282 | size); | 399 | size); |
283 | 400 | ||
401 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); | ||
402 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); | ||
284 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, | 403 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, |
285 | 1 << MSI_NUMBER_SHIFT | COMMAND_COPY); | 404 | COMMAND_COPY); |
286 | 405 | ||
287 | wait_for_completion(&test->irq_raised); | 406 | wait_for_completion(&test->irq_raised); |
288 | 407 | ||
@@ -318,6 +437,11 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size) | |||
318 | if (size > SIZE_MAX - alignment) | 437 | if (size > SIZE_MAX - alignment) |
319 | goto err; | 438 | goto err; |
320 | 439 | ||
440 | if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { | ||
441 | dev_err(dev, "Invalid IRQ type option\n"); | ||
442 | goto err; | ||
443 | } | ||
444 | |||
321 | orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, | 445 | orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, |
322 | GFP_KERNEL); | 446 | GFP_KERNEL); |
323 | if (!orig_addr) { | 447 | if (!orig_addr) { |
@@ -348,8 +472,10 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size) | |||
348 | 472 | ||
349 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); | 473 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); |
350 | 474 | ||
475 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); | ||
476 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); | ||
351 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, | 477 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, |
352 | 1 << MSI_NUMBER_SHIFT | COMMAND_READ); | 478 | COMMAND_READ); |
353 | 479 | ||
354 | wait_for_completion(&test->irq_raised); | 480 | wait_for_completion(&test->irq_raised); |
355 | 481 | ||
@@ -379,6 +505,11 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size) | |||
379 | if (size > SIZE_MAX - alignment) | 505 | if (size > SIZE_MAX - alignment) |
380 | goto err; | 506 | goto err; |
381 | 507 | ||
508 | if (irq_type < IRQ_TYPE_LEGACY || irq_type > IRQ_TYPE_MSIX) { | ||
509 | dev_err(dev, "Invalid IRQ type option\n"); | ||
510 | goto err; | ||
511 | } | ||
512 | |||
382 | orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, | 513 | orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, |
383 | GFP_KERNEL); | 514 | GFP_KERNEL); |
384 | if (!orig_addr) { | 515 | if (!orig_addr) { |
@@ -403,8 +534,10 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size) | |||
403 | 534 | ||
404 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); | 535 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size); |
405 | 536 | ||
537 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type); | ||
538 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1); | ||
406 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, | 539 | pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND, |
407 | 1 << MSI_NUMBER_SHIFT | COMMAND_WRITE); | 540 | COMMAND_WRITE); |
408 | 541 | ||
409 | wait_for_completion(&test->irq_raised); | 542 | wait_for_completion(&test->irq_raised); |
410 | 543 | ||
@@ -417,6 +550,38 @@ err: | |||
417 | return ret; | 550 | return ret; |
418 | } | 551 | } |
419 | 552 | ||
553 | static bool pci_endpoint_test_set_irq(struct pci_endpoint_test *test, | ||
554 | int req_irq_type) | ||
555 | { | ||
556 | struct pci_dev *pdev = test->pdev; | ||
557 | struct device *dev = &pdev->dev; | ||
558 | |||
559 | if (req_irq_type < IRQ_TYPE_LEGACY || req_irq_type > IRQ_TYPE_MSIX) { | ||
560 | dev_err(dev, "Invalid IRQ type option\n"); | ||
561 | return false; | ||
562 | } | ||
563 | |||
564 | if (irq_type == req_irq_type) | ||
565 | return true; | ||
566 | |||
567 | pci_endpoint_test_release_irq(test); | ||
568 | pci_endpoint_test_free_irq_vectors(test); | ||
569 | |||
570 | if (!pci_endpoint_test_alloc_irq_vectors(test, req_irq_type)) | ||
571 | goto err; | ||
572 | |||
573 | if (!pci_endpoint_test_request_irq(test)) | ||
574 | goto err; | ||
575 | |||
576 | irq_type = req_irq_type; | ||
577 | return true; | ||
578 | |||
579 | err: | ||
580 | pci_endpoint_test_free_irq_vectors(test); | ||
581 | irq_type = IRQ_TYPE_UNDEFINED; | ||
582 | return false; | ||
583 | } | ||
584 | |||
420 | static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, | 585 | static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, |
421 | unsigned long arg) | 586 | unsigned long arg) |
422 | { | 587 | { |
@@ -436,7 +601,8 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, | |||
436 | ret = pci_endpoint_test_legacy_irq(test); | 601 | ret = pci_endpoint_test_legacy_irq(test); |
437 | break; | 602 | break; |
438 | case PCITEST_MSI: | 603 | case PCITEST_MSI: |
439 | ret = pci_endpoint_test_msi_irq(test, arg); | 604 | case PCITEST_MSIX: |
605 | ret = pci_endpoint_test_msi_irq(test, arg, cmd == PCITEST_MSIX); | ||
440 | break; | 606 | break; |
441 | case PCITEST_WRITE: | 607 | case PCITEST_WRITE: |
442 | ret = pci_endpoint_test_write(test, arg); | 608 | ret = pci_endpoint_test_write(test, arg); |
@@ -447,6 +613,12 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, | |||
447 | case PCITEST_COPY: | 613 | case PCITEST_COPY: |
448 | ret = pci_endpoint_test_copy(test, arg); | 614 | ret = pci_endpoint_test_copy(test, arg); |
449 | break; | 615 | break; |
616 | case PCITEST_SET_IRQTYPE: | ||
617 | ret = pci_endpoint_test_set_irq(test, arg); | ||
618 | break; | ||
619 | case PCITEST_GET_IRQTYPE: | ||
620 | ret = irq_type; | ||
621 | break; | ||
450 | } | 622 | } |
451 | 623 | ||
452 | ret: | 624 | ret: |
@@ -462,9 +634,7 @@ static const struct file_operations pci_endpoint_test_fops = { | |||
462 | static int pci_endpoint_test_probe(struct pci_dev *pdev, | 634 | static int pci_endpoint_test_probe(struct pci_dev *pdev, |
463 | const struct pci_device_id *ent) | 635 | const struct pci_device_id *ent) |
464 | { | 636 | { |
465 | int i; | ||
466 | int err; | 637 | int err; |
467 | int irq = 0; | ||
468 | int id; | 638 | int id; |
469 | char name[20]; | 639 | char name[20]; |
470 | enum pci_barno bar; | 640 | enum pci_barno bar; |
@@ -486,11 +656,14 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, | |||
486 | test->alignment = 0; | 656 | test->alignment = 0; |
487 | test->pdev = pdev; | 657 | test->pdev = pdev; |
488 | 658 | ||
659 | if (no_msi) | ||
660 | irq_type = IRQ_TYPE_LEGACY; | ||
661 | |||
489 | data = (struct pci_endpoint_test_data *)ent->driver_data; | 662 | data = (struct pci_endpoint_test_data *)ent->driver_data; |
490 | if (data) { | 663 | if (data) { |
491 | test_reg_bar = data->test_reg_bar; | 664 | test_reg_bar = data->test_reg_bar; |
492 | test->alignment = data->alignment; | 665 | test->alignment = data->alignment; |
493 | no_msi = data->no_msi; | 666 | irq_type = data->irq_type; |
494 | } | 667 | } |
495 | 668 | ||
496 | init_completion(&test->irq_raised); | 669 | init_completion(&test->irq_raised); |
@@ -510,28 +683,11 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, | |||
510 | 683 | ||
511 | pci_set_master(pdev); | 684 | pci_set_master(pdev); |
512 | 685 | ||
513 | if (!no_msi) { | 686 | if (!pci_endpoint_test_alloc_irq_vectors(test, irq_type)) |
514 | irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); | 687 | goto err_disable_irq; |
515 | if (irq < 0) | ||
516 | dev_err(dev, "Failed to get MSI interrupts\n"); | ||
517 | test->num_irqs = irq; | ||
518 | } | ||
519 | |||
520 | err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, | ||
521 | IRQF_SHARED, DRV_MODULE_NAME, test); | ||
522 | if (err) { | ||
523 | dev_err(dev, "Failed to request IRQ %d\n", pdev->irq); | ||
524 | goto err_disable_msi; | ||
525 | } | ||
526 | 688 | ||
527 | for (i = 1; i < irq; i++) { | 689 | if (!pci_endpoint_test_request_irq(test)) |
528 | err = devm_request_irq(dev, pci_irq_vector(pdev, i), | 690 | goto err_disable_irq; |
529 | pci_endpoint_test_irqhandler, | ||
530 | IRQF_SHARED, DRV_MODULE_NAME, test); | ||
531 | if (err) | ||
532 | dev_err(dev, "failed to request IRQ %d for MSI %d\n", | ||
533 | pci_irq_vector(pdev, i), i + 1); | ||
534 | } | ||
535 | 691 | ||
536 | for (bar = BAR_0; bar <= BAR_5; bar++) { | 692 | for (bar = BAR_0; bar <= BAR_5; bar++) { |
537 | if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { | 693 | if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { |
@@ -590,12 +746,10 @@ err_iounmap: | |||
590 | if (test->bar[bar]) | 746 | if (test->bar[bar]) |
591 | pci_iounmap(pdev, test->bar[bar]); | 747 | pci_iounmap(pdev, test->bar[bar]); |
592 | } | 748 | } |
749 | pci_endpoint_test_release_irq(test); | ||
593 | 750 | ||
594 | for (i = 0; i < irq; i++) | 751 | err_disable_irq: |
595 | devm_free_irq(&pdev->dev, pci_irq_vector(pdev, i), test); | 752 | pci_endpoint_test_free_irq_vectors(test); |
596 | |||
597 | err_disable_msi: | ||
598 | pci_disable_msi(pdev); | ||
599 | pci_release_regions(pdev); | 753 | pci_release_regions(pdev); |
600 | 754 | ||
601 | err_disable_pdev: | 755 | err_disable_pdev: |
@@ -607,7 +761,6 @@ err_disable_pdev: | |||
607 | static void pci_endpoint_test_remove(struct pci_dev *pdev) | 761 | static void pci_endpoint_test_remove(struct pci_dev *pdev) |
608 | { | 762 | { |
609 | int id; | 763 | int id; |
610 | int i; | ||
611 | enum pci_barno bar; | 764 | enum pci_barno bar; |
612 | struct pci_endpoint_test *test = pci_get_drvdata(pdev); | 765 | struct pci_endpoint_test *test = pci_get_drvdata(pdev); |
613 | struct miscdevice *misc_device = &test->miscdev; | 766 | struct miscdevice *misc_device = &test->miscdev; |
@@ -624,9 +777,10 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) | |||
624 | if (test->bar[bar]) | 777 | if (test->bar[bar]) |
625 | pci_iounmap(pdev, test->bar[bar]); | 778 | pci_iounmap(pdev, test->bar[bar]); |
626 | } | 779 | } |
627 | for (i = 0; i < test->num_irqs; i++) | 780 | |
628 | devm_free_irq(&pdev->dev, pci_irq_vector(pdev, i), test); | 781 | pci_endpoint_test_release_irq(test); |
629 | pci_disable_msi(pdev); | 782 | pci_endpoint_test_free_irq_vectors(test); |
783 | |||
630 | pci_release_regions(pdev); | 784 | pci_release_regions(pdev); |
631 | pci_disable_device(pdev); | 785 | pci_disable_device(pdev); |
632 | } | 786 | } |