28
28
29
29
#define DRV_MODULE_NAME "pci-endpoint-test"
30
30
31
- #define IRQ_TYPE_UNDEFINED -1
32
- #define IRQ_TYPE_INTX 0
33
- #define IRQ_TYPE_MSI 1
34
- #define IRQ_TYPE_MSIX 2
35
-
36
31
#define PCI_ENDPOINT_TEST_MAGIC 0x0
37
32
38
33
#define PCI_ENDPOINT_TEST_COMMAND 0x4
71
66
72
67
#define PCI_ENDPOINT_TEST_CAPS 0x30
73
68
#define CAP_UNALIGNED_ACCESS BIT(0)
69
+ #define CAP_MSI BIT(1)
70
+ #define CAP_MSIX BIT(2)
71
+ #define CAP_INTX BIT(3)
74
72
75
73
#define PCI_DEVICE_ID_TI_AM654 0xb00c
76
74
#define PCI_DEVICE_ID_TI_J7200 0xb00f
@@ -96,14 +94,6 @@ static DEFINE_IDA(pci_endpoint_test_ida);
96
94
#define to_endpoint_test (priv ) container_of((priv), struct pci_endpoint_test, \
97
95
miscdev)
98
96
99
- static bool no_msi ;
100
- module_param (no_msi , bool , 0444 );
101
- MODULE_PARM_DESC (no_msi , "Disable MSI interrupt in pci_endpoint_test" );
102
-
103
- static int irq_type = IRQ_TYPE_MSI ;
104
- module_param (irq_type , int , 0444 );
105
- MODULE_PARM_DESC (irq_type , "IRQ mode selection in pci_endpoint_test (0 - Legacy, 1 - MSI, 2 - MSI-X)" );
106
-
107
97
enum pci_barno {
108
98
BAR_0 ,
109
99
BAR_1 ,
@@ -126,6 +116,7 @@ struct pci_endpoint_test {
126
116
struct miscdevice miscdev ;
127
117
enum pci_barno test_reg_bar ;
128
118
size_t alignment ;
119
+ u32 ep_caps ;
129
120
const char * name ;
130
121
};
131
122
@@ -166,7 +157,7 @@ static void pci_endpoint_test_free_irq_vectors(struct pci_endpoint_test *test)
166
157
struct pci_dev * pdev = test -> pdev ;
167
158
168
159
pci_free_irq_vectors (pdev );
169
- test -> irq_type = IRQ_TYPE_UNDEFINED ;
160
+ test -> irq_type = PCITEST_IRQ_TYPE_UNDEFINED ;
170
161
}
171
162
172
163
static int pci_endpoint_test_alloc_irq_vectors (struct pci_endpoint_test * test ,
@@ -177,23 +168,23 @@ static int pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test,
177
168
struct device * dev = & pdev -> dev ;
178
169
179
170
switch (type ) {
180
- case IRQ_TYPE_INTX :
171
+ case PCITEST_IRQ_TYPE_INTX :
181
172
irq = pci_alloc_irq_vectors (pdev , 1 , 1 , PCI_IRQ_INTX );
182
173
if (irq < 0 ) {
183
174
dev_err (dev , "Failed to get Legacy interrupt\n" );
184
175
return irq ;
185
176
}
186
177
187
178
break ;
188
- case IRQ_TYPE_MSI :
179
+ case PCITEST_IRQ_TYPE_MSI :
189
180
irq = pci_alloc_irq_vectors (pdev , 1 , 32 , PCI_IRQ_MSI );
190
181
if (irq < 0 ) {
191
182
dev_err (dev , "Failed to get MSI interrupts\n" );
192
183
return irq ;
193
184
}
194
185
195
186
break ;
196
- case IRQ_TYPE_MSIX :
187
+ case PCITEST_IRQ_TYPE_MSIX :
197
188
irq = pci_alloc_irq_vectors (pdev , 1 , 2048 , PCI_IRQ_MSIX );
198
189
if (irq < 0 ) {
199
190
dev_err (dev , "Failed to get MSI-X interrupts\n" );
@@ -216,10 +207,9 @@ static void pci_endpoint_test_release_irq(struct pci_endpoint_test *test)
216
207
{
217
208
int i ;
218
209
struct pci_dev * pdev = test -> pdev ;
219
- struct device * dev = & pdev -> dev ;
220
210
221
211
for (i = 0 ; i < test -> num_irqs ; i ++ )
222
- devm_free_irq ( dev , pci_irq_vector (pdev , i ), test );
212
+ free_irq ( pci_irq_vector (pdev , i ), test );
223
213
224
214
test -> num_irqs = 0 ;
225
215
}
@@ -232,33 +222,36 @@ static int pci_endpoint_test_request_irq(struct pci_endpoint_test *test)
232
222
struct device * dev = & pdev -> dev ;
233
223
234
224
for (i = 0 ; i < test -> num_irqs ; i ++ ) {
235
- ret = devm_request_irq ( dev , pci_irq_vector (pdev , i ),
236
- pci_endpoint_test_irqhandler ,
237
- IRQF_SHARED , test -> name , test );
225
+ ret = request_irq ( pci_irq_vector (pdev , i ),
226
+ pci_endpoint_test_irqhandler , IRQF_SHARED ,
227
+ test -> name , test );
238
228
if (ret )
239
229
goto fail ;
240
230
}
241
231
242
232
return 0 ;
243
233
244
234
fail :
245
- switch (irq_type ) {
246
- case IRQ_TYPE_INTX :
235
+ switch (test -> irq_type ) {
236
+ case PCITEST_IRQ_TYPE_INTX :
247
237
dev_err (dev , "Failed to request IRQ %d for Legacy\n" ,
248
238
pci_irq_vector (pdev , i ));
249
239
break ;
250
- case IRQ_TYPE_MSI :
240
+ case PCITEST_IRQ_TYPE_MSI :
251
241
dev_err (dev , "Failed to request IRQ %d for MSI %d\n" ,
252
242
pci_irq_vector (pdev , i ),
253
243
i + 1 );
254
244
break ;
255
- case IRQ_TYPE_MSIX :
245
+ case PCITEST_IRQ_TYPE_MSIX :
256
246
dev_err (dev , "Failed to request IRQ %d for MSI-X %d\n" ,
257
247
pci_irq_vector (pdev , i ),
258
248
i + 1 );
259
249
break ;
260
250
}
261
251
252
+ test -> num_irqs = i ;
253
+ pci_endpoint_test_release_irq (test );
254
+
262
255
return ret ;
263
256
}
264
257
@@ -272,9 +265,9 @@ static const u32 bar_test_pattern[] = {
272
265
};
273
266
274
267
static int pci_endpoint_test_bar_memcmp (struct pci_endpoint_test * test ,
275
- enum pci_barno barno , int offset ,
276
- void * write_buf , void * read_buf ,
277
- int size )
268
+ enum pci_barno barno ,
269
+ resource_size_t offset , void * write_buf ,
270
+ void * read_buf , int size )
278
271
{
279
272
memset (write_buf , bar_test_pattern [barno ], size );
280
273
memcpy_toio (test -> bar [barno ] + offset , write_buf , size );
@@ -287,16 +280,19 @@ static int pci_endpoint_test_bar_memcmp(struct pci_endpoint_test *test,
287
280
static int pci_endpoint_test_bar (struct pci_endpoint_test * test ,
288
281
enum pci_barno barno )
289
282
{
290
- int j , bar_size , buf_size , iters ;
283
+ resource_size_t bar_size , offset = 0 ;
291
284
void * write_buf __free (kfree ) = NULL ;
292
285
void * read_buf __free (kfree ) = NULL ;
293
286
struct pci_dev * pdev = test -> pdev ;
287
+ int buf_size ;
288
+
289
+ bar_size = pci_resource_len (pdev , barno );
290
+ if (!bar_size )
291
+ return - ENODATA ;
294
292
295
293
if (!test -> bar [barno ])
296
294
return - ENOMEM ;
297
295
298
- bar_size = pci_resource_len (pdev , barno );
299
-
300
296
if (barno == test -> test_reg_bar )
301
297
bar_size = 0x4 ;
302
298
@@ -314,11 +310,12 @@ static int pci_endpoint_test_bar(struct pci_endpoint_test *test,
314
310
if (!read_buf )
315
311
return - ENOMEM ;
316
312
317
- iters = bar_size / buf_size ;
318
- for (j = 0 ; j < iters ; j ++ )
319
- if (pci_endpoint_test_bar_memcmp (test , barno , buf_size * j ,
320
- write_buf , read_buf , buf_size ))
313
+ while (offset < bar_size ) {
314
+ if (pci_endpoint_test_bar_memcmp (test , barno , offset , write_buf ,
315
+ read_buf , buf_size ))
321
316
return - EIO ;
317
+ offset += buf_size ;
318
+ }
322
319
323
320
return 0 ;
324
321
}
@@ -382,7 +379,7 @@ static int pci_endpoint_test_bars_read_bar(struct pci_endpoint_test *test,
382
379
static int pci_endpoint_test_bars (struct pci_endpoint_test * test )
383
380
{
384
381
enum pci_barno bar ;
385
- bool ret ;
382
+ int ret ;
386
383
387
384
/* Write all BARs in order (without reading). */
388
385
for (bar = 0 ; bar < PCI_STD_NUM_BARS ; bar ++ )
@@ -398,7 +395,7 @@ static int pci_endpoint_test_bars(struct pci_endpoint_test *test)
398
395
for (bar = 0 ; bar < PCI_STD_NUM_BARS ; bar ++ ) {
399
396
if (test -> bar [bar ]) {
400
397
ret = pci_endpoint_test_bars_read_bar (test , bar );
401
- if (! ret )
398
+ if (ret )
402
399
return ret ;
403
400
}
404
401
}
@@ -411,7 +408,7 @@ static int pci_endpoint_test_intx_irq(struct pci_endpoint_test *test)
411
408
u32 val ;
412
409
413
410
pci_endpoint_test_writel (test , PCI_ENDPOINT_TEST_IRQ_TYPE ,
414
- IRQ_TYPE_INTX );
411
+ PCITEST_IRQ_TYPE_INTX );
415
412
pci_endpoint_test_writel (test , PCI_ENDPOINT_TEST_IRQ_NUMBER , 0 );
416
413
pci_endpoint_test_writel (test , PCI_ENDPOINT_TEST_COMMAND ,
417
414
COMMAND_RAISE_INTX_IRQ );
@@ -431,7 +428,8 @@ static int pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
431
428
int ret ;
432
429
433
430
pci_endpoint_test_writel (test , PCI_ENDPOINT_TEST_IRQ_TYPE ,
434
- msix ? IRQ_TYPE_MSIX : IRQ_TYPE_MSI );
431
+ msix ? PCITEST_IRQ_TYPE_MSIX :
432
+ PCITEST_IRQ_TYPE_MSI );
435
433
pci_endpoint_test_writel (test , PCI_ENDPOINT_TEST_IRQ_NUMBER , msi_num );
436
434
pci_endpoint_test_writel (test , PCI_ENDPOINT_TEST_COMMAND ,
437
435
msix ? COMMAND_RAISE_MSIX_IRQ :
@@ -507,7 +505,8 @@ static int pci_endpoint_test_copy(struct pci_endpoint_test *test,
507
505
if (use_dma )
508
506
flags |= FLAG_USE_DMA ;
509
507
510
- if (irq_type < IRQ_TYPE_INTX || irq_type > IRQ_TYPE_MSIX ) {
508
+ if (irq_type < PCITEST_IRQ_TYPE_INTX ||
509
+ irq_type > PCITEST_IRQ_TYPE_MSIX ) {
511
510
dev_err (dev , "Invalid IRQ type option\n" );
512
511
return - EINVAL ;
513
512
}
@@ -639,7 +638,8 @@ static int pci_endpoint_test_write(struct pci_endpoint_test *test,
639
638
if (use_dma )
640
639
flags |= FLAG_USE_DMA ;
641
640
642
- if (irq_type < IRQ_TYPE_INTX || irq_type > IRQ_TYPE_MSIX ) {
641
+ if (irq_type < PCITEST_IRQ_TYPE_INTX ||
642
+ irq_type > PCITEST_IRQ_TYPE_MSIX ) {
643
643
dev_err (dev , "Invalid IRQ type option\n" );
644
644
return - EINVAL ;
645
645
}
@@ -735,7 +735,8 @@ static int pci_endpoint_test_read(struct pci_endpoint_test *test,
735
735
if (use_dma )
736
736
flags |= FLAG_USE_DMA ;
737
737
738
- if (irq_type < IRQ_TYPE_INTX || irq_type > IRQ_TYPE_MSIX ) {
738
+ if (irq_type < PCITEST_IRQ_TYPE_INTX ||
739
+ irq_type > PCITEST_IRQ_TYPE_MSIX ) {
739
740
dev_err (dev , "Invalid IRQ type option\n" );
740
741
return - EINVAL ;
741
742
}
@@ -805,11 +806,24 @@ static int pci_endpoint_test_set_irq(struct pci_endpoint_test *test,
805
806
struct device * dev = & pdev -> dev ;
806
807
int ret ;
807
808
808
- if (req_irq_type < IRQ_TYPE_INTX || req_irq_type > IRQ_TYPE_MSIX ) {
809
+ if (req_irq_type < PCITEST_IRQ_TYPE_INTX ||
810
+ req_irq_type > PCITEST_IRQ_TYPE_AUTO ) {
809
811
dev_err (dev , "Invalid IRQ type option\n" );
810
812
return - EINVAL ;
811
813
}
812
814
815
+ if (req_irq_type == PCITEST_IRQ_TYPE_AUTO ) {
816
+ if (test -> ep_caps & CAP_MSI )
817
+ req_irq_type = PCITEST_IRQ_TYPE_MSI ;
818
+ else if (test -> ep_caps & CAP_MSIX )
819
+ req_irq_type = PCITEST_IRQ_TYPE_MSIX ;
820
+ else if (test -> ep_caps & CAP_INTX )
821
+ req_irq_type = PCITEST_IRQ_TYPE_INTX ;
822
+ else
823
+ /* fallback to MSI if no caps defined */
824
+ req_irq_type = PCITEST_IRQ_TYPE_MSI ;
825
+ }
826
+
813
827
if (test -> irq_type == req_irq_type )
814
828
return 0 ;
815
829
@@ -874,7 +888,7 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
874
888
ret = pci_endpoint_test_set_irq (test , arg );
875
889
break ;
876
890
case PCITEST_GET_IRQTYPE :
877
- ret = irq_type ;
891
+ ret = test -> irq_type ;
878
892
break ;
879
893
case PCITEST_CLEAR_IRQ :
880
894
ret = pci_endpoint_test_clear_irq (test );
@@ -895,13 +909,12 @@ static void pci_endpoint_test_get_capabilities(struct pci_endpoint_test *test)
895
909
{
896
910
struct pci_dev * pdev = test -> pdev ;
897
911
struct device * dev = & pdev -> dev ;
898
- u32 caps ;
899
912
900
- caps = pci_endpoint_test_readl (test , PCI_ENDPOINT_TEST_CAPS );
901
- dev_dbg (dev , "PCI_ENDPOINT_TEST_CAPS: %#x\n" , caps );
913
+ test -> ep_caps = pci_endpoint_test_readl (test , PCI_ENDPOINT_TEST_CAPS );
914
+ dev_dbg (dev , "PCI_ENDPOINT_TEST_CAPS: %#x\n" , test -> ep_caps );
902
915
903
916
/* CAP_UNALIGNED_ACCESS is set if the EP can do unaligned access */
904
- if (caps & CAP_UNALIGNED_ACCESS )
917
+ if (test -> ep_caps & CAP_UNALIGNED_ACCESS )
905
918
test -> alignment = 0 ;
906
919
}
907
920
@@ -910,7 +923,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
910
923
{
911
924
int ret ;
912
925
int id ;
913
- char name [24 ];
926
+ char name [29 ];
914
927
enum pci_barno bar ;
915
928
void __iomem * base ;
916
929
struct device * dev = & pdev -> dev ;
@@ -929,17 +942,14 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
929
942
test -> test_reg_bar = 0 ;
930
943
test -> alignment = 0 ;
931
944
test -> pdev = pdev ;
932
- test -> irq_type = IRQ_TYPE_UNDEFINED ;
933
-
934
- if (no_msi )
935
- irq_type = IRQ_TYPE_INTX ;
945
+ test -> irq_type = PCITEST_IRQ_TYPE_UNDEFINED ;
936
946
937
947
data = (struct pci_endpoint_test_data * )ent -> driver_data ;
938
948
if (data ) {
939
949
test_reg_bar = data -> test_reg_bar ;
940
950
test -> test_reg_bar = test_reg_bar ;
941
951
test -> alignment = data -> alignment ;
942
- irq_type = data -> irq_type ;
952
+ test -> irq_type = data -> irq_type ;
943
953
}
944
954
945
955
init_completion (& test -> irq_raised );
@@ -961,7 +971,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
961
971
962
972
pci_set_master (pdev );
963
973
964
- ret = pci_endpoint_test_alloc_irq_vectors (test , irq_type );
974
+ ret = pci_endpoint_test_alloc_irq_vectors (test , test -> irq_type );
965
975
if (ret )
966
976
goto err_disable_irq ;
967
977
@@ -1083,23 +1093,23 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev)
1083
1093
static const struct pci_endpoint_test_data default_data = {
1084
1094
.test_reg_bar = BAR_0 ,
1085
1095
.alignment = SZ_4K ,
1086
- .irq_type = IRQ_TYPE_MSI ,
1096
+ .irq_type = PCITEST_IRQ_TYPE_MSI ,
1087
1097
};
1088
1098
1089
1099
static const struct pci_endpoint_test_data am654_data = {
1090
1100
.test_reg_bar = BAR_2 ,
1091
1101
.alignment = SZ_64K ,
1092
- .irq_type = IRQ_TYPE_MSI ,
1102
+ .irq_type = PCITEST_IRQ_TYPE_MSI ,
1093
1103
};
1094
1104
1095
1105
static const struct pci_endpoint_test_data j721e_data = {
1096
1106
.alignment = 256 ,
1097
- .irq_type = IRQ_TYPE_MSI ,
1107
+ .irq_type = PCITEST_IRQ_TYPE_MSI ,
1098
1108
};
1099
1109
1100
1110
static const struct pci_endpoint_test_data rk3588_data = {
1101
1111
.alignment = SZ_64K ,
1102
- .irq_type = IRQ_TYPE_MSI ,
1112
+ .irq_type = PCITEST_IRQ_TYPE_MSI ,
1103
1113
};
1104
1114
1105
1115
/*
0 commit comments