misc: pci_endpoint_test: Add support to not enable MSI interrupts
[linux-2.6-microblaze.git] / drivers / misc / pci_endpoint_test.c
1 /**
2  * Host side test driver to test endpoint functionality
3  *
4  * Copyright (C) 2017 Texas Instruments
5  * Author: Kishon Vijay Abraham I <kishon@ti.com>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 of
9  * the License as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <linux/crc32.h>
21 #include <linux/delay.h>
22 #include <linux/fs.h>
23 #include <linux/io.h>
24 #include <linux/interrupt.h>
25 #include <linux/irq.h>
26 #include <linux/miscdevice.h>
27 #include <linux/module.h>
28 #include <linux/mutex.h>
29 #include <linux/random.h>
30 #include <linux/slab.h>
31 #include <linux/pci.h>
32 #include <linux/pci_ids.h>
33
34 #include <linux/pci_regs.h>
35
36 #include <uapi/linux/pcitest.h>
37
38 #define DRV_MODULE_NAME                 "pci-endpoint-test"
39
40 #define PCI_ENDPOINT_TEST_MAGIC         0x0
41
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)
50
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)
61
62 #define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR        0xc
63 #define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR        0x10
64
65 #define PCI_ENDPOINT_TEST_LOWER_DST_ADDR        0x14
66 #define PCI_ENDPOINT_TEST_UPPER_DST_ADDR        0x18
67
68 #define PCI_ENDPOINT_TEST_SIZE          0x1c
69 #define PCI_ENDPOINT_TEST_CHECKSUM      0x20
70
71 static DEFINE_IDA(pci_endpoint_test_ida);
72
73 #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
74                                             miscdev)
75 enum pci_barno {
76         BAR_0,
77         BAR_1,
78         BAR_2,
79         BAR_3,
80         BAR_4,
81         BAR_5,
82 };
83
84 struct pci_endpoint_test {
85         struct pci_dev  *pdev;
86         void __iomem    *base;
87         void __iomem    *bar[6];
88         struct completion irq_raised;
89         int             last_irq;
90         /* mutex to protect the ioctls */
91         struct mutex    mutex;
92         struct miscdevice miscdev;
93         enum pci_barno test_reg_bar;
94         size_t alignment;
95 };
96
97 struct pci_endpoint_test_data {
98         enum pci_barno test_reg_bar;
99         size_t alignment;
100         bool no_msi;
101 };
102
103 static int bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
104
105 static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
106                                           u32 offset)
107 {
108         return readl(test->base + offset);
109 }
110
111 static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test,
112                                             u32 offset, u32 value)
113 {
114         writel(value, test->base + offset);
115 }
116
117 static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test *test,
118                                               int bar, int offset)
119 {
120         return readl(test->bar[bar] + offset);
121 }
122
123 static inline void pci_endpoint_test_bar_writel(struct pci_endpoint_test *test,
124                                                 int bar, u32 offset, u32 value)
125 {
126         writel(value, test->bar[bar] + offset);
127 }
128
129 static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id)
130 {
131         struct pci_endpoint_test *test = dev_id;
132         u32 reg;
133
134         reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
135         if (reg & STATUS_IRQ_RAISED) {
136                 test->last_irq = irq;
137                 complete(&test->irq_raised);
138                 reg &= ~STATUS_IRQ_RAISED;
139         }
140         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS,
141                                  reg);
142
143         return IRQ_HANDLED;
144 }
145
146 static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
147                                   enum pci_barno barno)
148 {
149         int j;
150         u32 val;
151         int size;
152
153         if (!test->bar[barno])
154                 return false;
155
156         size = bar_size[barno];
157
158         if (barno == test->test_reg_bar)
159                 size = 0x4;
160
161         for (j = 0; j < size; j += 4)
162                 pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0);
163
164         for (j = 0; j < size; j += 4) {
165                 val = pci_endpoint_test_bar_readl(test, barno, j);
166                 if (val != 0xA0A0A0A0)
167                         return false;
168         }
169
170         return true;
171 }
172
173 static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test)
174 {
175         u32 val;
176
177         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
178                                  COMMAND_RAISE_LEGACY_IRQ);
179         val = wait_for_completion_timeout(&test->irq_raised,
180                                           msecs_to_jiffies(1000));
181         if (!val)
182                 return false;
183
184         return true;
185 }
186
187 static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
188                                       u8 msi_num)
189 {
190         u32 val;
191         struct pci_dev *pdev = test->pdev;
192
193         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
194                                  msi_num << MSI_NUMBER_SHIFT |
195                                  COMMAND_RAISE_MSI_IRQ);
196         val = wait_for_completion_timeout(&test->irq_raised,
197                                           msecs_to_jiffies(1000));
198         if (!val)
199                 return false;
200
201         if (test->last_irq - pdev->irq == msi_num - 1)
202                 return true;
203
204         return false;
205 }
206
207 static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
208 {
209         bool ret = false;
210         void *src_addr;
211         void *dst_addr;
212         dma_addr_t src_phys_addr;
213         dma_addr_t dst_phys_addr;
214         struct pci_dev *pdev = test->pdev;
215         struct device *dev = &pdev->dev;
216         void *orig_src_addr;
217         dma_addr_t orig_src_phys_addr;
218         void *orig_dst_addr;
219         dma_addr_t orig_dst_phys_addr;
220         size_t offset;
221         size_t alignment = test->alignment;
222         u32 src_crc32;
223         u32 dst_crc32;
224
225         orig_src_addr = dma_alloc_coherent(dev, size + alignment,
226                                            &orig_src_phys_addr, GFP_KERNEL);
227         if (!orig_src_addr) {
228                 dev_err(dev, "failed to allocate source buffer\n");
229                 ret = false;
230                 goto err;
231         }
232
233         if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) {
234                 src_phys_addr = PTR_ALIGN(orig_src_phys_addr, alignment);
235                 offset = src_phys_addr - orig_src_phys_addr;
236                 src_addr = orig_src_addr + offset;
237         } else {
238                 src_phys_addr = orig_src_phys_addr;
239                 src_addr = orig_src_addr;
240         }
241
242         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
243                                  lower_32_bits(src_phys_addr));
244
245         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
246                                  upper_32_bits(src_phys_addr));
247
248         get_random_bytes(src_addr, size);
249         src_crc32 = crc32_le(~0, src_addr, size);
250
251         orig_dst_addr = dma_alloc_coherent(dev, size + alignment,
252                                            &orig_dst_phys_addr, GFP_KERNEL);
253         if (!orig_dst_addr) {
254                 dev_err(dev, "failed to allocate destination address\n");
255                 ret = false;
256                 goto err_orig_src_addr;
257         }
258
259         if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) {
260                 dst_phys_addr = PTR_ALIGN(orig_dst_phys_addr, alignment);
261                 offset = dst_phys_addr - orig_dst_phys_addr;
262                 dst_addr = orig_dst_addr + offset;
263         } else {
264                 dst_phys_addr = orig_dst_phys_addr;
265                 dst_addr = orig_dst_addr;
266         }
267
268         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
269                                  lower_32_bits(dst_phys_addr));
270         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
271                                  upper_32_bits(dst_phys_addr));
272
273         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE,
274                                  size);
275
276         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
277                                  1 << MSI_NUMBER_SHIFT | COMMAND_COPY);
278
279         wait_for_completion(&test->irq_raised);
280
281         dst_crc32 = crc32_le(~0, dst_addr, size);
282         if (dst_crc32 == src_crc32)
283                 ret = true;
284
285         dma_free_coherent(dev, size + alignment, orig_dst_addr,
286                           orig_dst_phys_addr);
287
288 err_orig_src_addr:
289         dma_free_coherent(dev, size + alignment, orig_src_addr,
290                           orig_src_phys_addr);
291
292 err:
293         return ret;
294 }
295
296 static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
297 {
298         bool ret = false;
299         u32 reg;
300         void *addr;
301         dma_addr_t phys_addr;
302         struct pci_dev *pdev = test->pdev;
303         struct device *dev = &pdev->dev;
304         void *orig_addr;
305         dma_addr_t orig_phys_addr;
306         size_t offset;
307         size_t alignment = test->alignment;
308         u32 crc32;
309
310         orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
311                                        GFP_KERNEL);
312         if (!orig_addr) {
313                 dev_err(dev, "failed to allocate address\n");
314                 ret = false;
315                 goto err;
316         }
317
318         if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
319                 phys_addr =  PTR_ALIGN(orig_phys_addr, alignment);
320                 offset = phys_addr - orig_phys_addr;
321                 addr = orig_addr + offset;
322         } else {
323                 phys_addr = orig_phys_addr;
324                 addr = orig_addr;
325         }
326
327         get_random_bytes(addr, size);
328
329         crc32 = crc32_le(~0, addr, size);
330         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_CHECKSUM,
331                                  crc32);
332
333         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
334                                  lower_32_bits(phys_addr));
335         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
336                                  upper_32_bits(phys_addr));
337
338         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
339
340         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
341                                  1 << MSI_NUMBER_SHIFT | COMMAND_READ);
342
343         wait_for_completion(&test->irq_raised);
344
345         reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
346         if (reg & STATUS_READ_SUCCESS)
347                 ret = true;
348
349         dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
350
351 err:
352         return ret;
353 }
354
355 static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
356 {
357         bool ret = false;
358         void *addr;
359         dma_addr_t phys_addr;
360         struct pci_dev *pdev = test->pdev;
361         struct device *dev = &pdev->dev;
362         void *orig_addr;
363         dma_addr_t orig_phys_addr;
364         size_t offset;
365         size_t alignment = test->alignment;
366         u32 crc32;
367
368         orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
369                                        GFP_KERNEL);
370         if (!orig_addr) {
371                 dev_err(dev, "failed to allocate destination address\n");
372                 ret = false;
373                 goto err;
374         }
375
376         if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
377                 phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
378                 offset = phys_addr - orig_phys_addr;
379                 addr = orig_addr + offset;
380         } else {
381                 phys_addr = orig_phys_addr;
382                 addr = orig_addr;
383         }
384
385         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
386                                  lower_32_bits(phys_addr));
387         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
388                                  upper_32_bits(phys_addr));
389
390         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
391
392         pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
393                                  1 << MSI_NUMBER_SHIFT | COMMAND_WRITE);
394
395         wait_for_completion(&test->irq_raised);
396
397         crc32 = crc32_le(~0, addr, size);
398         if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
399                 ret = true;
400
401         dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
402 err:
403         return ret;
404 }
405
406 static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
407                                     unsigned long arg)
408 {
409         int ret = -EINVAL;
410         enum pci_barno bar;
411         struct pci_endpoint_test *test = to_endpoint_test(file->private_data);
412
413         mutex_lock(&test->mutex);
414         switch (cmd) {
415         case PCITEST_BAR:
416                 bar = arg;
417                 if (bar < 0 || bar > 5)
418                         goto ret;
419                 ret = pci_endpoint_test_bar(test, bar);
420                 break;
421         case PCITEST_LEGACY_IRQ:
422                 ret = pci_endpoint_test_legacy_irq(test);
423                 break;
424         case PCITEST_MSI:
425                 ret = pci_endpoint_test_msi_irq(test, arg);
426                 break;
427         case PCITEST_WRITE:
428                 ret = pci_endpoint_test_write(test, arg);
429                 break;
430         case PCITEST_READ:
431                 ret = pci_endpoint_test_read(test, arg);
432                 break;
433         case PCITEST_COPY:
434                 ret = pci_endpoint_test_copy(test, arg);
435                 break;
436         }
437
438 ret:
439         mutex_unlock(&test->mutex);
440         return ret;
441 }
442
443 static const struct file_operations pci_endpoint_test_fops = {
444         .owner = THIS_MODULE,
445         .unlocked_ioctl = pci_endpoint_test_ioctl,
446 };
447
448 static int pci_endpoint_test_probe(struct pci_dev *pdev,
449                                    const struct pci_device_id *ent)
450 {
451         int i;
452         int err;
453         int irq = 0;
454         int id;
455         bool no_msi = false;
456         char name[20];
457         enum pci_barno bar;
458         void __iomem *base;
459         struct device *dev = &pdev->dev;
460         struct pci_endpoint_test *test;
461         struct pci_endpoint_test_data *data;
462         enum pci_barno test_reg_bar = BAR_0;
463         struct miscdevice *misc_device;
464
465         if (pci_is_bridge(pdev))
466                 return -ENODEV;
467
468         test = devm_kzalloc(dev, sizeof(*test), GFP_KERNEL);
469         if (!test)
470                 return -ENOMEM;
471
472         test->test_reg_bar = 0;
473         test->alignment = 0;
474         test->pdev = pdev;
475
476         data = (struct pci_endpoint_test_data *)ent->driver_data;
477         if (data) {
478                 test_reg_bar = data->test_reg_bar;
479                 test->alignment = data->alignment;
480                 no_msi = data->no_msi;
481         }
482
483         init_completion(&test->irq_raised);
484         mutex_init(&test->mutex);
485
486         err = pci_enable_device(pdev);
487         if (err) {
488                 dev_err(dev, "Cannot enable PCI device\n");
489                 return err;
490         }
491
492         err = pci_request_regions(pdev, DRV_MODULE_NAME);
493         if (err) {
494                 dev_err(dev, "Cannot obtain PCI resources\n");
495                 goto err_disable_pdev;
496         }
497
498         pci_set_master(pdev);
499
500         if (!no_msi) {
501                 irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
502                 if (irq < 0)
503                         dev_err(dev, "failed to get MSI interrupts\n");
504         }
505
506         err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler,
507                                IRQF_SHARED, DRV_MODULE_NAME, test);
508         if (err) {
509                 dev_err(dev, "failed to request IRQ %d\n", pdev->irq);
510                 goto err_disable_msi;
511         }
512
513         for (i = 1; i < irq; i++) {
514                 err = devm_request_irq(dev, pdev->irq + i,
515                                        pci_endpoint_test_irqhandler,
516                                        IRQF_SHARED, DRV_MODULE_NAME, test);
517                 if (err)
518                         dev_err(dev, "failed to request IRQ %d for MSI %d\n",
519                                 pdev->irq + i, i + 1);
520         }
521
522         for (bar = BAR_0; bar <= BAR_5; bar++) {
523                 base = pci_ioremap_bar(pdev, bar);
524                 if (!base) {
525                         dev_err(dev, "failed to read BAR%d\n", bar);
526                         WARN_ON(bar == test_reg_bar);
527                 }
528                 test->bar[bar] = base;
529         }
530
531         test->base = test->bar[test_reg_bar];
532         if (!test->base) {
533                 dev_err(dev, "Cannot perform PCI test without BAR%d\n",
534                         test_reg_bar);
535                 goto err_iounmap;
536         }
537
538         pci_set_drvdata(pdev, test);
539
540         id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL);
541         if (id < 0) {
542                 dev_err(dev, "unable to get id\n");
543                 goto err_iounmap;
544         }
545
546         snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id);
547         misc_device = &test->miscdev;
548         misc_device->minor = MISC_DYNAMIC_MINOR;
549         misc_device->name = name;
550         misc_device->fops = &pci_endpoint_test_fops,
551
552         err = misc_register(misc_device);
553         if (err) {
554                 dev_err(dev, "failed to register device\n");
555                 goto err_ida_remove;
556         }
557
558         return 0;
559
560 err_ida_remove:
561         ida_simple_remove(&pci_endpoint_test_ida, id);
562
563 err_iounmap:
564         for (bar = BAR_0; bar <= BAR_5; bar++) {
565                 if (test->bar[bar])
566                         pci_iounmap(pdev, test->bar[bar]);
567         }
568
569 err_disable_msi:
570         pci_disable_msi(pdev);
571         pci_release_regions(pdev);
572
573 err_disable_pdev:
574         pci_disable_device(pdev);
575
576         return err;
577 }
578
579 static void pci_endpoint_test_remove(struct pci_dev *pdev)
580 {
581         int id;
582         enum pci_barno bar;
583         struct pci_endpoint_test *test = pci_get_drvdata(pdev);
584         struct miscdevice *misc_device = &test->miscdev;
585
586         if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1)
587                 return;
588
589         misc_deregister(&test->miscdev);
590         ida_simple_remove(&pci_endpoint_test_ida, id);
591         for (bar = BAR_0; bar <= BAR_5; bar++) {
592                 if (test->bar[bar])
593                         pci_iounmap(pdev, test->bar[bar]);
594         }
595         pci_disable_msi(pdev);
596         pci_release_regions(pdev);
597         pci_disable_device(pdev);
598 }
599
600 static const struct pci_device_id pci_endpoint_test_tbl[] = {
601         { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x) },
602         { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x) },
603         { }
604 };
605 MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
606
607 static struct pci_driver pci_endpoint_test_driver = {
608         .name           = DRV_MODULE_NAME,
609         .id_table       = pci_endpoint_test_tbl,
610         .probe          = pci_endpoint_test_probe,
611         .remove         = pci_endpoint_test_remove,
612 };
613 module_pci_driver(pci_endpoint_test_driver);
614
615 MODULE_DESCRIPTION("PCI ENDPOINT TEST HOST DRIVER");
616 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
617 MODULE_LICENSE("GPL v2");