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 };
94 
95 static int bar_size[] = { 4, 512, 1024, 16384, 131072, 1048576 };
96 
97 static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
98 					  u32 offset)
99 {
100 	return readl(test->base + offset);
101 }
102 
103 static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test,
104 					    u32 offset, u32 value)
105 {
106 	writel(value, test->base + offset);
107 }
108 
109 static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test *test,
110 					      int bar, int offset)
111 {
112 	return readl(test->bar[bar] + offset);
113 }
114 
115 static inline void pci_endpoint_test_bar_writel(struct pci_endpoint_test *test,
116 						int bar, u32 offset, u32 value)
117 {
118 	writel(value, test->bar[bar] + offset);
119 }
120 
121 static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id)
122 {
123 	struct pci_endpoint_test *test = dev_id;
124 	u32 reg;
125 
126 	reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
127 	if (reg & STATUS_IRQ_RAISED) {
128 		test->last_irq = irq;
129 		complete(&test->irq_raised);
130 		reg &= ~STATUS_IRQ_RAISED;
131 	}
132 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS,
133 				 reg);
134 
135 	return IRQ_HANDLED;
136 }
137 
138 static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
139 				  enum pci_barno barno)
140 {
141 	int j;
142 	u32 val;
143 	int size;
144 
145 	if (!test->bar[barno])
146 		return false;
147 
148 	size = bar_size[barno];
149 
150 	for (j = 0; j < size; j += 4)
151 		pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0);
152 
153 	for (j = 0; j < size; j += 4) {
154 		val = pci_endpoint_test_bar_readl(test, barno, j);
155 		if (val != 0xA0A0A0A0)
156 			return false;
157 	}
158 
159 	return true;
160 }
161 
162 static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test)
163 {
164 	u32 val;
165 
166 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
167 				 COMMAND_RAISE_LEGACY_IRQ);
168 	val = wait_for_completion_timeout(&test->irq_raised,
169 					  msecs_to_jiffies(1000));
170 	if (!val)
171 		return false;
172 
173 	return true;
174 }
175 
176 static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
177 				      u8 msi_num)
178 {
179 	u32 val;
180 	struct pci_dev *pdev = test->pdev;
181 
182 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
183 				 msi_num << MSI_NUMBER_SHIFT |
184 				 COMMAND_RAISE_MSI_IRQ);
185 	val = wait_for_completion_timeout(&test->irq_raised,
186 					  msecs_to_jiffies(1000));
187 	if (!val)
188 		return false;
189 
190 	if (test->last_irq - pdev->irq == msi_num - 1)
191 		return true;
192 
193 	return false;
194 }
195 
196 static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
197 {
198 	bool ret = false;
199 	void *src_addr;
200 	void *dst_addr;
201 	dma_addr_t src_phys_addr;
202 	dma_addr_t dst_phys_addr;
203 	struct pci_dev *pdev = test->pdev;
204 	struct device *dev = &pdev->dev;
205 	u32 src_crc32;
206 	u32 dst_crc32;
207 
208 	src_addr = dma_alloc_coherent(dev, size, &src_phys_addr, GFP_KERNEL);
209 	if (!src_addr) {
210 		dev_err(dev, "failed to allocate source buffer\n");
211 		ret = false;
212 		goto err;
213 	}
214 
215 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
216 				 lower_32_bits(src_phys_addr));
217 
218 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
219 				 upper_32_bits(src_phys_addr));
220 
221 	get_random_bytes(src_addr, size);
222 	src_crc32 = crc32_le(~0, src_addr, size);
223 
224 	dst_addr = dma_alloc_coherent(dev, size, &dst_phys_addr, GFP_KERNEL);
225 	if (!dst_addr) {
226 		dev_err(dev, "failed to allocate destination address\n");
227 		ret = false;
228 		goto err_src_addr;
229 	}
230 
231 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
232 				 lower_32_bits(dst_phys_addr));
233 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
234 				 upper_32_bits(dst_phys_addr));
235 
236 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE,
237 				 size);
238 
239 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
240 				 1 << MSI_NUMBER_SHIFT | COMMAND_COPY);
241 
242 	wait_for_completion(&test->irq_raised);
243 
244 	dst_crc32 = crc32_le(~0, dst_addr, size);
245 	if (dst_crc32 == src_crc32)
246 		ret = true;
247 
248 	dma_free_coherent(dev, size, dst_addr, dst_phys_addr);
249 
250 err_src_addr:
251 	dma_free_coherent(dev, size, src_addr, src_phys_addr);
252 
253 err:
254 	return ret;
255 }
256 
257 static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
258 {
259 	bool ret = false;
260 	u32 reg;
261 	void *addr;
262 	dma_addr_t phys_addr;
263 	struct pci_dev *pdev = test->pdev;
264 	struct device *dev = &pdev->dev;
265 	u32 crc32;
266 
267 	addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
268 	if (!addr) {
269 		dev_err(dev, "failed to allocate address\n");
270 		ret = false;
271 		goto err;
272 	}
273 
274 	get_random_bytes(addr, size);
275 
276 	crc32 = crc32_le(~0, addr, size);
277 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_CHECKSUM,
278 				 crc32);
279 
280 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
281 				 lower_32_bits(phys_addr));
282 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
283 				 upper_32_bits(phys_addr));
284 
285 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
286 
287 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
288 				 1 << MSI_NUMBER_SHIFT | COMMAND_READ);
289 
290 	wait_for_completion(&test->irq_raised);
291 
292 	reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
293 	if (reg & STATUS_READ_SUCCESS)
294 		ret = true;
295 
296 	dma_free_coherent(dev, size, addr, phys_addr);
297 
298 err:
299 	return ret;
300 }
301 
302 static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
303 {
304 	bool ret = false;
305 	void *addr;
306 	dma_addr_t phys_addr;
307 	struct pci_dev *pdev = test->pdev;
308 	struct device *dev = &pdev->dev;
309 	u32 crc32;
310 
311 	addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
312 	if (!addr) {
313 		dev_err(dev, "failed to allocate destination address\n");
314 		ret = false;
315 		goto err;
316 	}
317 
318 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
319 				 lower_32_bits(phys_addr));
320 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
321 				 upper_32_bits(phys_addr));
322 
323 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
324 
325 	pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
326 				 1 << MSI_NUMBER_SHIFT | COMMAND_WRITE);
327 
328 	wait_for_completion(&test->irq_raised);
329 
330 	crc32 = crc32_le(~0, addr, size);
331 	if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
332 		ret = true;
333 
334 	dma_free_coherent(dev, size, addr, phys_addr);
335 err:
336 	return ret;
337 }
338 
339 static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
340 				    unsigned long arg)
341 {
342 	int ret = -EINVAL;
343 	enum pci_barno bar;
344 	struct pci_endpoint_test *test = to_endpoint_test(file->private_data);
345 
346 	mutex_lock(&test->mutex);
347 	switch (cmd) {
348 	case PCITEST_BAR:
349 		bar = arg;
350 		if (bar < 0 || bar > 5)
351 			goto ret;
352 		ret = pci_endpoint_test_bar(test, bar);
353 		break;
354 	case PCITEST_LEGACY_IRQ:
355 		ret = pci_endpoint_test_legacy_irq(test);
356 		break;
357 	case PCITEST_MSI:
358 		ret = pci_endpoint_test_msi_irq(test, arg);
359 		break;
360 	case PCITEST_WRITE:
361 		ret = pci_endpoint_test_write(test, arg);
362 		break;
363 	case PCITEST_READ:
364 		ret = pci_endpoint_test_read(test, arg);
365 		break;
366 	case PCITEST_COPY:
367 		ret = pci_endpoint_test_copy(test, arg);
368 		break;
369 	}
370 
371 ret:
372 	mutex_unlock(&test->mutex);
373 	return ret;
374 }
375 
376 static const struct file_operations pci_endpoint_test_fops = {
377 	.owner = THIS_MODULE,
378 	.unlocked_ioctl = pci_endpoint_test_ioctl,
379 };
380 
381 static int pci_endpoint_test_probe(struct pci_dev *pdev,
382 				   const struct pci_device_id *ent)
383 {
384 	int i;
385 	int err;
386 	int irq;
387 	int id;
388 	char name[20];
389 	enum pci_barno bar;
390 	void __iomem *base;
391 	struct device *dev = &pdev->dev;
392 	struct pci_endpoint_test *test;
393 	struct miscdevice *misc_device;
394 
395 	if (pci_is_bridge(pdev))
396 		return -ENODEV;
397 
398 	test = devm_kzalloc(dev, sizeof(*test), GFP_KERNEL);
399 	if (!test)
400 		return -ENOMEM;
401 
402 	test->pdev = pdev;
403 	init_completion(&test->irq_raised);
404 	mutex_init(&test->mutex);
405 
406 	err = pci_enable_device(pdev);
407 	if (err) {
408 		dev_err(dev, "Cannot enable PCI device\n");
409 		return err;
410 	}
411 
412 	err = pci_request_regions(pdev, DRV_MODULE_NAME);
413 	if (err) {
414 		dev_err(dev, "Cannot obtain PCI resources\n");
415 		goto err_disable_pdev;
416 	}
417 
418 	pci_set_master(pdev);
419 
420 	irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
421 	if (irq < 0)
422 		dev_err(dev, "failed to get MSI interrupts\n");
423 
424 	err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler,
425 			       IRQF_SHARED, DRV_MODULE_NAME, test);
426 	if (err) {
427 		dev_err(dev, "failed to request IRQ %d\n", pdev->irq);
428 		goto err_disable_msi;
429 	}
430 
431 	for (i = 1; i < irq; i++) {
432 		err = devm_request_irq(dev, pdev->irq + i,
433 				       pci_endpoint_test_irqhandler,
434 				       IRQF_SHARED, DRV_MODULE_NAME, test);
435 		if (err)
436 			dev_err(dev, "failed to request IRQ %d for MSI %d\n",
437 				pdev->irq + i, i + 1);
438 	}
439 
440 	for (bar = BAR_0; bar <= BAR_5; bar++) {
441 		base = pci_ioremap_bar(pdev, bar);
442 		if (!base) {
443 			dev_err(dev, "failed to read BAR%d\n", bar);
444 			WARN_ON(bar == BAR_0);
445 		}
446 		test->bar[bar] = base;
447 	}
448 
449 	test->base = test->bar[0];
450 	if (!test->base) {
451 		dev_err(dev, "Cannot perform PCI test without BAR0\n");
452 		goto err_iounmap;
453 	}
454 
455 	pci_set_drvdata(pdev, test);
456 
457 	id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL);
458 	if (id < 0) {
459 		dev_err(dev, "unable to get id\n");
460 		goto err_iounmap;
461 	}
462 
463 	snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id);
464 	misc_device = &test->miscdev;
465 	misc_device->minor = MISC_DYNAMIC_MINOR;
466 	misc_device->name = name;
467 	misc_device->fops = &pci_endpoint_test_fops,
468 
469 	err = misc_register(misc_device);
470 	if (err) {
471 		dev_err(dev, "failed to register device\n");
472 		goto err_ida_remove;
473 	}
474 
475 	return 0;
476 
477 err_ida_remove:
478 	ida_simple_remove(&pci_endpoint_test_ida, id);
479 
480 err_iounmap:
481 	for (bar = BAR_0; bar <= BAR_5; bar++) {
482 		if (test->bar[bar])
483 			pci_iounmap(pdev, test->bar[bar]);
484 	}
485 
486 err_disable_msi:
487 	pci_disable_msi(pdev);
488 	pci_release_regions(pdev);
489 
490 err_disable_pdev:
491 	pci_disable_device(pdev);
492 
493 	return err;
494 }
495 
496 static void pci_endpoint_test_remove(struct pci_dev *pdev)
497 {
498 	int id;
499 	enum pci_barno bar;
500 	struct pci_endpoint_test *test = pci_get_drvdata(pdev);
501 	struct miscdevice *misc_device = &test->miscdev;
502 
503 	if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1)
504 		return;
505 
506 	misc_deregister(&test->miscdev);
507 	ida_simple_remove(&pci_endpoint_test_ida, id);
508 	for (bar = BAR_0; bar <= BAR_5; bar++) {
509 		if (test->bar[bar])
510 			pci_iounmap(pdev, test->bar[bar]);
511 	}
512 	pci_disable_msi(pdev);
513 	pci_release_regions(pdev);
514 	pci_disable_device(pdev);
515 }
516 
517 static const struct pci_device_id pci_endpoint_test_tbl[] = {
518 	{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x) },
519 	{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x) },
520 	{ }
521 };
522 MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
523 
524 static struct pci_driver pci_endpoint_test_driver = {
525 	.name		= DRV_MODULE_NAME,
526 	.id_table	= pci_endpoint_test_tbl,
527 	.probe		= pci_endpoint_test_probe,
528 	.remove		= pci_endpoint_test_remove,
529 };
530 module_pci_driver(pci_endpoint_test_driver);
531 
532 MODULE_DESCRIPTION("PCI ENDPOINT TEST HOST DRIVER");
533 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
534 MODULE_LICENSE("GPL v2");
535