37
37
38
38
#define DRV_MODULE_NAME "pci-endpoint-test"
39
39
40
+ #define IRQ_TYPE_UNDEFINED -1
40
41
#define IRQ_TYPE_LEGACY 0
41
42
#define IRQ_TYPE_MSI 1
42
43
#define IRQ_TYPE_MSIX 2
@@ -157,6 +158,100 @@ static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id)
157
158
return IRQ_HANDLED ;
158
159
}
159
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
+
160
255
static bool pci_endpoint_test_bar (struct pci_endpoint_test * test ,
161
256
enum pci_barno barno )
162
257
{
@@ -247,6 +342,11 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
247
342
if (size > SIZE_MAX - alignment )
248
343
goto err ;
249
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
+
250
350
orig_src_addr = dma_alloc_coherent (dev , size + alignment ,
251
351
& orig_src_phys_addr , GFP_KERNEL );
252
352
if (!orig_src_addr ) {
@@ -337,6 +437,11 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
337
437
if (size > SIZE_MAX - alignment )
338
438
goto err ;
339
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
+
340
445
orig_addr = dma_alloc_coherent (dev , size + alignment , & orig_phys_addr ,
341
446
GFP_KERNEL );
342
447
if (!orig_addr ) {
@@ -400,6 +505,11 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
400
505
if (size > SIZE_MAX - alignment )
401
506
goto err ;
402
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
+
403
513
orig_addr = dma_alloc_coherent (dev , size + alignment , & orig_phys_addr ,
404
514
GFP_KERNEL );
405
515
if (!orig_addr ) {
@@ -440,6 +550,38 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
440
550
return ret ;
441
551
}
442
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
+
443
585
static long pci_endpoint_test_ioctl (struct file * file , unsigned int cmd ,
444
586
unsigned long arg )
445
587
{
@@ -471,6 +613,12 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
471
613
case PCITEST_COPY :
472
614
ret = pci_endpoint_test_copy (test , arg );
473
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 ;
474
622
}
475
623
476
624
ret :
@@ -486,9 +634,7 @@ static const struct file_operations pci_endpoint_test_fops = {
486
634
static int pci_endpoint_test_probe (struct pci_dev * pdev ,
487
635
const struct pci_device_id * ent )
488
636
{
489
- int i ;
490
637
int err ;
491
- int irq = 0 ;
492
638
int id ;
493
639
char name [20 ];
494
640
enum pci_barno bar ;
@@ -537,41 +683,11 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
537
683
538
684
pci_set_master (pdev );
539
685
540
- switch (irq_type ) {
541
- case IRQ_TYPE_LEGACY :
542
- break ;
543
- case IRQ_TYPE_MSI :
544
- irq = pci_alloc_irq_vectors (pdev , 1 , 32 , PCI_IRQ_MSI );
545
- if (irq < 0 )
546
- dev_err (dev , "Failed to get MSI interrupts\n" );
547
- test -> num_irqs = irq ;
548
- break ;
549
- case IRQ_TYPE_MSIX :
550
- irq = pci_alloc_irq_vectors (pdev , 1 , 2048 , PCI_IRQ_MSIX );
551
- if (irq < 0 )
552
- dev_err (dev , "Failed to get MSI-X interrupts\n" );
553
- test -> num_irqs = irq ;
554
- break ;
555
- default :
556
- dev_err (dev , "Invalid IRQ type selected\n" );
557
- }
686
+ if (!pci_endpoint_test_alloc_irq_vectors (test , irq_type ))
687
+ goto err_disable_irq ;
558
688
559
- err = devm_request_irq (dev , pdev -> irq , pci_endpoint_test_irqhandler ,
560
- IRQF_SHARED , DRV_MODULE_NAME , test );
561
- if (err ) {
562
- dev_err (dev , "Failed to request IRQ %d\n" , pdev -> irq );
563
- goto err_disable_msi ;
564
- }
565
-
566
- for (i = 1 ; i < irq ; i ++ ) {
567
- err = devm_request_irq (dev , pci_irq_vector (pdev , i ),
568
- pci_endpoint_test_irqhandler ,
569
- IRQF_SHARED , DRV_MODULE_NAME , test );
570
- if (err )
571
- dev_err (dev , "Failed to request IRQ %d for MSI%s %d\n" ,
572
- pci_irq_vector (pdev , i ),
573
- irq_type == IRQ_TYPE_MSIX ? "-X" : "" , i + 1 );
574
- }
689
+ if (!pci_endpoint_test_request_irq (test ))
690
+ goto err_disable_irq ;
575
691
576
692
for (bar = BAR_0 ; bar <= BAR_5 ; bar ++ ) {
577
693
if (pci_resource_flags (pdev , bar ) & IORESOURCE_MEM ) {
@@ -630,13 +746,10 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
630
746
if (test -> bar [bar ])
631
747
pci_iounmap (pdev , test -> bar [bar ]);
632
748
}
749
+ pci_endpoint_test_release_irq (test );
633
750
634
- for (i = 0 ; i < irq ; i ++ )
635
- devm_free_irq (& pdev -> dev , pci_irq_vector (pdev , i ), test );
636
-
637
- err_disable_msi :
638
- pci_disable_msi (pdev );
639
- pci_disable_msix (pdev );
751
+ err_disable_irq :
752
+ pci_endpoint_test_free_irq_vectors (test );
640
753
pci_release_regions (pdev );
641
754
642
755
err_disable_pdev :
@@ -648,7 +761,6 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
648
761
static void pci_endpoint_test_remove (struct pci_dev * pdev )
649
762
{
650
763
int id ;
651
- int i ;
652
764
enum pci_barno bar ;
653
765
struct pci_endpoint_test * test = pci_get_drvdata (pdev );
654
766
struct miscdevice * misc_device = & test -> miscdev ;
@@ -665,10 +777,10 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev)
665
777
if (test -> bar [bar ])
666
778
pci_iounmap (pdev , test -> bar [bar ]);
667
779
}
668
- for ( i = 0 ; i < test -> num_irqs ; i ++ )
669
- devm_free_irq ( & pdev -> dev , pci_irq_vector ( pdev , i ), test );
670
- pci_disable_msi ( pdev );
671
- pci_disable_msix ( pdev );
780
+
781
+ pci_endpoint_test_release_irq ( test );
782
+ pci_endpoint_test_free_irq_vectors ( test );
783
+
672
784
pci_release_regions (pdev );
673
785
pci_disable_device (pdev );
674
786
}
0 commit comments