2828
2929#define DRV_MODULE_NAME "pci-endpoint-test"
3030
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-
3631#define PCI_ENDPOINT_TEST_MAGIC 0x0
3732
3833#define PCI_ENDPOINT_TEST_COMMAND 0x4
7166
7267#define PCI_ENDPOINT_TEST_CAPS 0x30
7368#define CAP_UNALIGNED_ACCESS BIT(0)
69+ #define CAP_MSI BIT(1)
70+ #define CAP_MSIX BIT(2)
71+ #define CAP_INTX BIT(3)
7472
7573#define PCI_DEVICE_ID_TI_AM654 0xb00c
7674#define PCI_DEVICE_ID_TI_J7200 0xb00f
@@ -96,14 +94,6 @@ static DEFINE_IDA(pci_endpoint_test_ida);
9694#define to_endpoint_test (priv ) container_of((priv), struct pci_endpoint_test, \
9795 miscdev)
9896
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-
10797enum pci_barno {
10898 BAR_0 ,
10999 BAR_1 ,
@@ -126,6 +116,7 @@ struct pci_endpoint_test {
126116 struct miscdevice miscdev ;
127117 enum pci_barno test_reg_bar ;
128118 size_t alignment ;
119+ u32 ep_caps ;
129120 const char * name ;
130121};
131122
@@ -166,7 +157,7 @@ static void pci_endpoint_test_free_irq_vectors(struct pci_endpoint_test *test)
166157 struct pci_dev * pdev = test -> pdev ;
167158
168159 pci_free_irq_vectors (pdev );
169- test -> irq_type = IRQ_TYPE_UNDEFINED ;
160+ test -> irq_type = PCITEST_IRQ_TYPE_UNDEFINED ;
170161}
171162
172163static 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,
177168 struct device * dev = & pdev -> dev ;
178169
179170 switch (type ) {
180- case IRQ_TYPE_INTX :
171+ case PCITEST_IRQ_TYPE_INTX :
181172 irq = pci_alloc_irq_vectors (pdev , 1 , 1 , PCI_IRQ_INTX );
182173 if (irq < 0 ) {
183174 dev_err (dev , "Failed to get Legacy interrupt\n" );
184175 return irq ;
185176 }
186177
187178 break ;
188- case IRQ_TYPE_MSI :
179+ case PCITEST_IRQ_TYPE_MSI :
189180 irq = pci_alloc_irq_vectors (pdev , 1 , 32 , PCI_IRQ_MSI );
190181 if (irq < 0 ) {
191182 dev_err (dev , "Failed to get MSI interrupts\n" );
192183 return irq ;
193184 }
194185
195186 break ;
196- case IRQ_TYPE_MSIX :
187+ case PCITEST_IRQ_TYPE_MSIX :
197188 irq = pci_alloc_irq_vectors (pdev , 1 , 2048 , PCI_IRQ_MSIX );
198189 if (irq < 0 ) {
199190 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)
216207{
217208 int i ;
218209 struct pci_dev * pdev = test -> pdev ;
219- struct device * dev = & pdev -> dev ;
220210
221211 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 );
223213
224214 test -> num_irqs = 0 ;
225215}
@@ -232,33 +222,36 @@ static int pci_endpoint_test_request_irq(struct pci_endpoint_test *test)
232222 struct device * dev = & pdev -> dev ;
233223
234224 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 );
238228 if (ret )
239229 goto fail ;
240230 }
241231
242232 return 0 ;
243233
244234fail :
245- switch (irq_type ) {
246- case IRQ_TYPE_INTX :
235+ switch (test -> irq_type ) {
236+ case PCITEST_IRQ_TYPE_INTX :
247237 dev_err (dev , "Failed to request IRQ %d for Legacy\n" ,
248238 pci_irq_vector (pdev , i ));
249239 break ;
250- case IRQ_TYPE_MSI :
240+ case PCITEST_IRQ_TYPE_MSI :
251241 dev_err (dev , "Failed to request IRQ %d for MSI %d\n" ,
252242 pci_irq_vector (pdev , i ),
253243 i + 1 );
254244 break ;
255- case IRQ_TYPE_MSIX :
245+ case PCITEST_IRQ_TYPE_MSIX :
256246 dev_err (dev , "Failed to request IRQ %d for MSI-X %d\n" ,
257247 pci_irq_vector (pdev , i ),
258248 i + 1 );
259249 break ;
260250 }
261251
252+ test -> num_irqs = i ;
253+ pci_endpoint_test_release_irq (test );
254+
262255 return ret ;
263256}
264257
@@ -272,9 +265,9 @@ static const u32 bar_test_pattern[] = {
272265};
273266
274267static 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 )
278271{
279272 memset (write_buf , bar_test_pattern [barno ], size );
280273 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,
287280static int pci_endpoint_test_bar (struct pci_endpoint_test * test ,
288281 enum pci_barno barno )
289282{
290- int j , bar_size , buf_size , iters ;
283+ resource_size_t bar_size , offset = 0 ;
291284 void * write_buf __free (kfree ) = NULL ;
292285 void * read_buf __free (kfree ) = NULL ;
293286 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 ;
294292
295293 if (!test -> bar [barno ])
296294 return - ENOMEM ;
297295
298- bar_size = pci_resource_len (pdev , barno );
299-
300296 if (barno == test -> test_reg_bar )
301297 bar_size = 0x4 ;
302298
@@ -314,11 +310,12 @@ static int pci_endpoint_test_bar(struct pci_endpoint_test *test,
314310 if (!read_buf )
315311 return - ENOMEM ;
316312
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 ))
321316 return - EIO ;
317+ offset += buf_size ;
318+ }
322319
323320 return 0 ;
324321}
@@ -382,7 +379,7 @@ static int pci_endpoint_test_bars_read_bar(struct pci_endpoint_test *test,
382379static int pci_endpoint_test_bars (struct pci_endpoint_test * test )
383380{
384381 enum pci_barno bar ;
385- bool ret ;
382+ int ret ;
386383
387384 /* Write all BARs in order (without reading). */
388385 for (bar = 0 ; bar < PCI_STD_NUM_BARS ; bar ++ )
@@ -398,7 +395,7 @@ static int pci_endpoint_test_bars(struct pci_endpoint_test *test)
398395 for (bar = 0 ; bar < PCI_STD_NUM_BARS ; bar ++ ) {
399396 if (test -> bar [bar ]) {
400397 ret = pci_endpoint_test_bars_read_bar (test , bar );
401- if (! ret )
398+ if (ret )
402399 return ret ;
403400 }
404401 }
@@ -411,7 +408,7 @@ static int pci_endpoint_test_intx_irq(struct pci_endpoint_test *test)
411408 u32 val ;
412409
413410 pci_endpoint_test_writel (test , PCI_ENDPOINT_TEST_IRQ_TYPE ,
414- IRQ_TYPE_INTX );
411+ PCITEST_IRQ_TYPE_INTX );
415412 pci_endpoint_test_writel (test , PCI_ENDPOINT_TEST_IRQ_NUMBER , 0 );
416413 pci_endpoint_test_writel (test , PCI_ENDPOINT_TEST_COMMAND ,
417414 COMMAND_RAISE_INTX_IRQ );
@@ -431,7 +428,8 @@ static int pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
431428 int ret ;
432429
433430 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 );
435433 pci_endpoint_test_writel (test , PCI_ENDPOINT_TEST_IRQ_NUMBER , msi_num );
436434 pci_endpoint_test_writel (test , PCI_ENDPOINT_TEST_COMMAND ,
437435 msix ? COMMAND_RAISE_MSIX_IRQ :
@@ -507,7 +505,8 @@ static int pci_endpoint_test_copy(struct pci_endpoint_test *test,
507505 if (use_dma )
508506 flags |= FLAG_USE_DMA ;
509507
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 ) {
511510 dev_err (dev , "Invalid IRQ type option\n" );
512511 return - EINVAL ;
513512 }
@@ -639,7 +638,8 @@ static int pci_endpoint_test_write(struct pci_endpoint_test *test,
639638 if (use_dma )
640639 flags |= FLAG_USE_DMA ;
641640
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 ) {
643643 dev_err (dev , "Invalid IRQ type option\n" );
644644 return - EINVAL ;
645645 }
@@ -735,7 +735,8 @@ static int pci_endpoint_test_read(struct pci_endpoint_test *test,
735735 if (use_dma )
736736 flags |= FLAG_USE_DMA ;
737737
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 ) {
739740 dev_err (dev , "Invalid IRQ type option\n" );
740741 return - EINVAL ;
741742 }
@@ -805,11 +806,24 @@ static int pci_endpoint_test_set_irq(struct pci_endpoint_test *test,
805806 struct device * dev = & pdev -> dev ;
806807 int ret ;
807808
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 ) {
809811 dev_err (dev , "Invalid IRQ type option\n" );
810812 return - EINVAL ;
811813 }
812814
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+
813827 if (test -> irq_type == req_irq_type )
814828 return 0 ;
815829
@@ -874,7 +888,7 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
874888 ret = pci_endpoint_test_set_irq (test , arg );
875889 break ;
876890 case PCITEST_GET_IRQTYPE :
877- ret = irq_type ;
891+ ret = test -> irq_type ;
878892 break ;
879893 case PCITEST_CLEAR_IRQ :
880894 ret = pci_endpoint_test_clear_irq (test );
@@ -895,13 +909,12 @@ static void pci_endpoint_test_get_capabilities(struct pci_endpoint_test *test)
895909{
896910 struct pci_dev * pdev = test -> pdev ;
897911 struct device * dev = & pdev -> dev ;
898- u32 caps ;
899912
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 );
902915
903916 /* 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 )
905918 test -> alignment = 0 ;
906919}
907920
@@ -910,7 +923,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
910923{
911924 int ret ;
912925 int id ;
913- char name [24 ];
926+ char name [29 ];
914927 enum pci_barno bar ;
915928 void __iomem * base ;
916929 struct device * dev = & pdev -> dev ;
@@ -929,17 +942,14 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
929942 test -> test_reg_bar = 0 ;
930943 test -> alignment = 0 ;
931944 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 ;
936946
937947 data = (struct pci_endpoint_test_data * )ent -> driver_data ;
938948 if (data ) {
939949 test_reg_bar = data -> test_reg_bar ;
940950 test -> test_reg_bar = test_reg_bar ;
941951 test -> alignment = data -> alignment ;
942- irq_type = data -> irq_type ;
952+ test -> irq_type = data -> irq_type ;
943953 }
944954
945955 init_completion (& test -> irq_raised );
@@ -961,7 +971,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
961971
962972 pci_set_master (pdev );
963973
964- ret = pci_endpoint_test_alloc_irq_vectors (test , irq_type );
974+ ret = pci_endpoint_test_alloc_irq_vectors (test , test -> irq_type );
965975 if (ret )
966976 goto err_disable_irq ;
967977
@@ -1083,23 +1093,23 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev)
10831093static const struct pci_endpoint_test_data default_data = {
10841094 .test_reg_bar = BAR_0 ,
10851095 .alignment = SZ_4K ,
1086- .irq_type = IRQ_TYPE_MSI ,
1096+ .irq_type = PCITEST_IRQ_TYPE_MSI ,
10871097};
10881098
10891099static const struct pci_endpoint_test_data am654_data = {
10901100 .test_reg_bar = BAR_2 ,
10911101 .alignment = SZ_64K ,
1092- .irq_type = IRQ_TYPE_MSI ,
1102+ .irq_type = PCITEST_IRQ_TYPE_MSI ,
10931103};
10941104
10951105static const struct pci_endpoint_test_data j721e_data = {
10961106 .alignment = 256 ,
1097- .irq_type = IRQ_TYPE_MSI ,
1107+ .irq_type = PCITEST_IRQ_TYPE_MSI ,
10981108};
10991109
11001110static const struct pci_endpoint_test_data rk3588_data = {
11011111 .alignment = SZ_64K ,
1102- .irq_type = IRQ_TYPE_MSI ,
1112+ .irq_type = PCITEST_IRQ_TYPE_MSI ,
11031113};
11041114
11051115/*
0 commit comments