pci-epf-test/pci_endpoint_test: Add MSI-X support
[linux-2.6-block.git] / drivers / misc / pci_endpoint_test.c
CommitLineData
2c156ac7
KVA
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
e8817de7
GP
38#define DRV_MODULE_NAME "pci-endpoint-test"
39
40#define IRQ_TYPE_LEGACY 0
41#define IRQ_TYPE_MSI 1
c2e00e31 42#define IRQ_TYPE_MSIX 2
e8817de7
GP
43
44#define PCI_ENDPOINT_TEST_MAGIC 0x0
45
46#define PCI_ENDPOINT_TEST_COMMAND 0x4
47#define COMMAND_RAISE_LEGACY_IRQ BIT(0)
48#define COMMAND_RAISE_MSI_IRQ BIT(1)
c2e00e31 49#define COMMAND_RAISE_MSIX_IRQ BIT(2)
e8817de7
GP
50#define COMMAND_READ BIT(3)
51#define COMMAND_WRITE BIT(4)
52#define COMMAND_COPY BIT(5)
53
54#define PCI_ENDPOINT_TEST_STATUS 0x8
55#define STATUS_READ_SUCCESS BIT(0)
56#define STATUS_READ_FAIL BIT(1)
57#define STATUS_WRITE_SUCCESS BIT(2)
58#define STATUS_WRITE_FAIL BIT(3)
59#define STATUS_COPY_SUCCESS BIT(4)
60#define STATUS_COPY_FAIL BIT(5)
61#define STATUS_IRQ_RAISED BIT(6)
62#define STATUS_SRC_ADDR_INVALID BIT(7)
63#define STATUS_DST_ADDR_INVALID BIT(8)
64
65#define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR 0x0c
2c156ac7
KVA
66#define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR 0x10
67
68#define PCI_ENDPOINT_TEST_LOWER_DST_ADDR 0x14
69#define PCI_ENDPOINT_TEST_UPPER_DST_ADDR 0x18
70
e8817de7
GP
71#define PCI_ENDPOINT_TEST_SIZE 0x1c
72#define PCI_ENDPOINT_TEST_CHECKSUM 0x20
73
74#define PCI_ENDPOINT_TEST_IRQ_TYPE 0x24
75#define PCI_ENDPOINT_TEST_IRQ_NUMBER 0x28
2c156ac7
KVA
76
77static DEFINE_IDA(pci_endpoint_test_ida);
78
79#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
80 miscdev)
0c8a5f9d
KVA
81
82static bool no_msi;
83module_param(no_msi, bool, 0444);
84MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test");
85
9133e394
GP
86static int irq_type = IRQ_TYPE_MSI;
87module_param(irq_type, int, 0444);
c2e00e31 88MODULE_PARM_DESC(irq_type, "IRQ mode selection in pci_endpoint_test (0 - Legacy, 1 - MSI, 2 - MSI-X)");
9133e394 89
2c156ac7
KVA
90enum pci_barno {
91 BAR_0,
92 BAR_1,
93 BAR_2,
94 BAR_3,
95 BAR_4,
96 BAR_5,
97};
98
99struct pci_endpoint_test {
100 struct pci_dev *pdev;
101 void __iomem *base;
102 void __iomem *bar[6];
103 struct completion irq_raised;
104 int last_irq;
b7636e81 105 int num_irqs;
2c156ac7
KVA
106 /* mutex to protect the ioctls */
107 struct mutex mutex;
108 struct miscdevice miscdev;
834b9051 109 enum pci_barno test_reg_bar;
13107c60 110 size_t alignment;
2c156ac7
KVA
111};
112
834b9051
KVA
113struct pci_endpoint_test_data {
114 enum pci_barno test_reg_bar;
13107c60 115 size_t alignment;
9133e394 116 int irq_type;
834b9051
KVA
117};
118
2c156ac7
KVA
119static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
120 u32 offset)
121{
122 return readl(test->base + offset);
123}
124
125static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test,
126 u32 offset, u32 value)
127{
128 writel(value, test->base + offset);
129}
130
131static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test *test,
132 int bar, int offset)
133{
134 return readl(test->bar[bar] + offset);
135}
136
137static inline void pci_endpoint_test_bar_writel(struct pci_endpoint_test *test,
138 int bar, u32 offset, u32 value)
139{
140 writel(value, test->bar[bar] + offset);
141}
142
143static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id)
144{
145 struct pci_endpoint_test *test = dev_id;
146 u32 reg;
147
148 reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
149 if (reg & STATUS_IRQ_RAISED) {
150 test->last_irq = irq;
151 complete(&test->irq_raised);
152 reg &= ~STATUS_IRQ_RAISED;
153 }
154 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS,
155 reg);
156
157 return IRQ_HANDLED;
158}
159
160static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
161 enum pci_barno barno)
162{
163 int j;
164 u32 val;
165 int size;
cda370ec 166 struct pci_dev *pdev = test->pdev;
2c156ac7
KVA
167
168 if (!test->bar[barno])
169 return false;
170
cda370ec 171 size = pci_resource_len(pdev, barno);
2c156ac7 172
834b9051
KVA
173 if (barno == test->test_reg_bar)
174 size = 0x4;
175
2c156ac7
KVA
176 for (j = 0; j < size; j += 4)
177 pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0);
178
179 for (j = 0; j < size; j += 4) {
180 val = pci_endpoint_test_bar_readl(test, barno, j);
181 if (val != 0xA0A0A0A0)
182 return false;
183 }
184
185 return true;
186}
187
188static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test)
189{
190 u32 val;
191
e8817de7
GP
192 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE,
193 IRQ_TYPE_LEGACY);
194 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 0);
2c156ac7
KVA
195 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
196 COMMAND_RAISE_LEGACY_IRQ);
197 val = wait_for_completion_timeout(&test->irq_raised,
198 msecs_to_jiffies(1000));
199 if (!val)
200 return false;
201
202 return true;
203}
204
205static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
c2e00e31 206 u16 msi_num, bool msix)
2c156ac7
KVA
207{
208 u32 val;
209 struct pci_dev *pdev = test->pdev;
210
e8817de7 211 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE,
c2e00e31
GP
212 msix == false ? IRQ_TYPE_MSI :
213 IRQ_TYPE_MSIX);
e8817de7 214 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, msi_num);
2c156ac7 215 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
c2e00e31
GP
216 msix == false ? COMMAND_RAISE_MSI_IRQ :
217 COMMAND_RAISE_MSIX_IRQ);
2c156ac7
KVA
218 val = wait_for_completion_timeout(&test->irq_raised,
219 msecs_to_jiffies(1000));
220 if (!val)
221 return false;
222
ecc57efe 223 if (pci_irq_vector(pdev, msi_num - 1) == test->last_irq)
2c156ac7
KVA
224 return true;
225
226 return false;
227}
228
229static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
230{
231 bool ret = false;
232 void *src_addr;
233 void *dst_addr;
234 dma_addr_t src_phys_addr;
235 dma_addr_t dst_phys_addr;
236 struct pci_dev *pdev = test->pdev;
237 struct device *dev = &pdev->dev;
13107c60
KVA
238 void *orig_src_addr;
239 dma_addr_t orig_src_phys_addr;
240 void *orig_dst_addr;
241 dma_addr_t orig_dst_phys_addr;
242 size_t offset;
243 size_t alignment = test->alignment;
2c156ac7
KVA
244 u32 src_crc32;
245 u32 dst_crc32;
246
343dc693
DC
247 if (size > SIZE_MAX - alignment)
248 goto err;
249
13107c60
KVA
250 orig_src_addr = dma_alloc_coherent(dev, size + alignment,
251 &orig_src_phys_addr, GFP_KERNEL);
252 if (!orig_src_addr) {
0e52ea61 253 dev_err(dev, "Failed to allocate source buffer\n");
2c156ac7
KVA
254 ret = false;
255 goto err;
256 }
257
13107c60
KVA
258 if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) {
259 src_phys_addr = PTR_ALIGN(orig_src_phys_addr, alignment);
260 offset = src_phys_addr - orig_src_phys_addr;
261 src_addr = orig_src_addr + offset;
262 } else {
263 src_phys_addr = orig_src_phys_addr;
264 src_addr = orig_src_addr;
265 }
266
2c156ac7
KVA
267 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
268 lower_32_bits(src_phys_addr));
269
270 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
271 upper_32_bits(src_phys_addr));
272
273 get_random_bytes(src_addr, size);
274 src_crc32 = crc32_le(~0, src_addr, size);
275
13107c60
KVA
276 orig_dst_addr = dma_alloc_coherent(dev, size + alignment,
277 &orig_dst_phys_addr, GFP_KERNEL);
278 if (!orig_dst_addr) {
0e52ea61 279 dev_err(dev, "Failed to allocate destination address\n");
2c156ac7 280 ret = false;
13107c60
KVA
281 goto err_orig_src_addr;
282 }
283
284 if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) {
285 dst_phys_addr = PTR_ALIGN(orig_dst_phys_addr, alignment);
286 offset = dst_phys_addr - orig_dst_phys_addr;
287 dst_addr = orig_dst_addr + offset;
288 } else {
289 dst_phys_addr = orig_dst_phys_addr;
290 dst_addr = orig_dst_addr;
2c156ac7
KVA
291 }
292
293 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
294 lower_32_bits(dst_phys_addr));
295 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
296 upper_32_bits(dst_phys_addr));
297
298 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE,
299 size);
300
9133e394 301 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type);
e8817de7 302 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1);
2c156ac7 303 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
e8817de7 304 COMMAND_COPY);
2c156ac7
KVA
305
306 wait_for_completion(&test->irq_raised);
307
308 dst_crc32 = crc32_le(~0, dst_addr, size);
309 if (dst_crc32 == src_crc32)
310 ret = true;
311
13107c60
KVA
312 dma_free_coherent(dev, size + alignment, orig_dst_addr,
313 orig_dst_phys_addr);
2c156ac7 314
13107c60
KVA
315err_orig_src_addr:
316 dma_free_coherent(dev, size + alignment, orig_src_addr,
317 orig_src_phys_addr);
2c156ac7
KVA
318
319err:
320 return ret;
321}
322
323static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
324{
325 bool ret = false;
326 u32 reg;
327 void *addr;
328 dma_addr_t phys_addr;
329 struct pci_dev *pdev = test->pdev;
330 struct device *dev = &pdev->dev;
13107c60
KVA
331 void *orig_addr;
332 dma_addr_t orig_phys_addr;
333 size_t offset;
334 size_t alignment = test->alignment;
2c156ac7
KVA
335 u32 crc32;
336
343dc693
DC
337 if (size > SIZE_MAX - alignment)
338 goto err;
339
13107c60
KVA
340 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
341 GFP_KERNEL);
342 if (!orig_addr) {
0e52ea61 343 dev_err(dev, "Failed to allocate address\n");
2c156ac7
KVA
344 ret = false;
345 goto err;
346 }
347
13107c60
KVA
348 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
349 phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
350 offset = phys_addr - orig_phys_addr;
351 addr = orig_addr + offset;
352 } else {
353 phys_addr = orig_phys_addr;
354 addr = orig_addr;
355 }
356
2c156ac7
KVA
357 get_random_bytes(addr, size);
358
359 crc32 = crc32_le(~0, addr, size);
360 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_CHECKSUM,
361 crc32);
362
363 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
364 lower_32_bits(phys_addr));
365 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
366 upper_32_bits(phys_addr));
367
368 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
369
9133e394 370 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type);
e8817de7 371 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1);
2c156ac7 372 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
e8817de7 373 COMMAND_READ);
2c156ac7
KVA
374
375 wait_for_completion(&test->irq_raised);
376
377 reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
378 if (reg & STATUS_READ_SUCCESS)
379 ret = true;
380
13107c60 381 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
2c156ac7
KVA
382
383err:
384 return ret;
385}
386
387static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
388{
389 bool ret = false;
390 void *addr;
391 dma_addr_t phys_addr;
392 struct pci_dev *pdev = test->pdev;
393 struct device *dev = &pdev->dev;
13107c60
KVA
394 void *orig_addr;
395 dma_addr_t orig_phys_addr;
396 size_t offset;
397 size_t alignment = test->alignment;
2c156ac7
KVA
398 u32 crc32;
399
343dc693
DC
400 if (size > SIZE_MAX - alignment)
401 goto err;
402
13107c60
KVA
403 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
404 GFP_KERNEL);
405 if (!orig_addr) {
0e52ea61 406 dev_err(dev, "Failed to allocate destination address\n");
2c156ac7
KVA
407 ret = false;
408 goto err;
409 }
410
13107c60
KVA
411 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
412 phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
413 offset = phys_addr - orig_phys_addr;
414 addr = orig_addr + offset;
415 } else {
416 phys_addr = orig_phys_addr;
417 addr = orig_addr;
418 }
419
2c156ac7
KVA
420 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
421 lower_32_bits(phys_addr));
422 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
423 upper_32_bits(phys_addr));
424
425 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
426
9133e394 427 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE, irq_type);
e8817de7 428 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 1);
2c156ac7 429 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
e8817de7 430 COMMAND_WRITE);
2c156ac7
KVA
431
432 wait_for_completion(&test->irq_raised);
433
434 crc32 = crc32_le(~0, addr, size);
435 if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
436 ret = true;
437
13107c60 438 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
2c156ac7
KVA
439err:
440 return ret;
441}
442
443static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
444 unsigned long arg)
445{
446 int ret = -EINVAL;
447 enum pci_barno bar;
448 struct pci_endpoint_test *test = to_endpoint_test(file->private_data);
449
450 mutex_lock(&test->mutex);
451 switch (cmd) {
452 case PCITEST_BAR:
453 bar = arg;
454 if (bar < 0 || bar > 5)
455 goto ret;
456 ret = pci_endpoint_test_bar(test, bar);
457 break;
458 case PCITEST_LEGACY_IRQ:
459 ret = pci_endpoint_test_legacy_irq(test);
460 break;
461 case PCITEST_MSI:
c2e00e31
GP
462 case PCITEST_MSIX:
463 ret = pci_endpoint_test_msi_irq(test, arg, cmd == PCITEST_MSIX);
2c156ac7
KVA
464 break;
465 case PCITEST_WRITE:
466 ret = pci_endpoint_test_write(test, arg);
467 break;
468 case PCITEST_READ:
469 ret = pci_endpoint_test_read(test, arg);
470 break;
471 case PCITEST_COPY:
472 ret = pci_endpoint_test_copy(test, arg);
473 break;
474 }
475
476ret:
477 mutex_unlock(&test->mutex);
478 return ret;
479}
480
481static const struct file_operations pci_endpoint_test_fops = {
482 .owner = THIS_MODULE,
483 .unlocked_ioctl = pci_endpoint_test_ioctl,
484};
485
486static int pci_endpoint_test_probe(struct pci_dev *pdev,
487 const struct pci_device_id *ent)
488{
489 int i;
490 int err;
0b91516a 491 int irq = 0;
2c156ac7
KVA
492 int id;
493 char name[20];
494 enum pci_barno bar;
495 void __iomem *base;
496 struct device *dev = &pdev->dev;
497 struct pci_endpoint_test *test;
834b9051
KVA
498 struct pci_endpoint_test_data *data;
499 enum pci_barno test_reg_bar = BAR_0;
2c156ac7
KVA
500 struct miscdevice *misc_device;
501
502 if (pci_is_bridge(pdev))
503 return -ENODEV;
504
505 test = devm_kzalloc(dev, sizeof(*test), GFP_KERNEL);
506 if (!test)
507 return -ENOMEM;
508
834b9051 509 test->test_reg_bar = 0;
13107c60 510 test->alignment = 0;
2c156ac7 511 test->pdev = pdev;
834b9051 512
9133e394
GP
513 if (no_msi)
514 irq_type = IRQ_TYPE_LEGACY;
515
834b9051 516 data = (struct pci_endpoint_test_data *)ent->driver_data;
13107c60 517 if (data) {
834b9051 518 test_reg_bar = data->test_reg_bar;
13107c60 519 test->alignment = data->alignment;
9133e394 520 irq_type = data->irq_type;
13107c60 521 }
834b9051 522
2c156ac7
KVA
523 init_completion(&test->irq_raised);
524 mutex_init(&test->mutex);
525
526 err = pci_enable_device(pdev);
527 if (err) {
528 dev_err(dev, "Cannot enable PCI device\n");
529 return err;
530 }
531
532 err = pci_request_regions(pdev, DRV_MODULE_NAME);
533 if (err) {
534 dev_err(dev, "Cannot obtain PCI resources\n");
535 goto err_disable_pdev;
536 }
537
538 pci_set_master(pdev);
539
9133e394
GP
540 switch (irq_type) {
541 case IRQ_TYPE_LEGACY:
542 break;
543 case IRQ_TYPE_MSI:
0b91516a
KVA
544 irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
545 if (irq < 0)
0e52ea61 546 dev_err(dev, "Failed to get MSI interrupts\n");
b7636e81 547 test->num_irqs = irq;
9133e394 548 break;
c2e00e31
GP
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;
9133e394
GP
555 default:
556 dev_err(dev, "Invalid IRQ type selected\n");
0b91516a 557 }
2c156ac7
KVA
558
559 err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler,
560 IRQF_SHARED, DRV_MODULE_NAME, test);
561 if (err) {
0e52ea61 562 dev_err(dev, "Failed to request IRQ %d\n", pdev->irq);
2c156ac7
KVA
563 goto err_disable_msi;
564 }
565
566 for (i = 1; i < irq; i++) {
ecc57efe 567 err = devm_request_irq(dev, pci_irq_vector(pdev, i),
2c156ac7
KVA
568 pci_endpoint_test_irqhandler,
569 IRQF_SHARED, DRV_MODULE_NAME, test);
570 if (err)
c2e00e31
GP
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);
2c156ac7
KVA
574 }
575
576 for (bar = BAR_0; bar <= BAR_5; bar++) {
16b17cad
NC
577 if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) {
578 base = pci_ioremap_bar(pdev, bar);
579 if (!base) {
0e52ea61 580 dev_err(dev, "Failed to read BAR%d\n", bar);
16b17cad
NC
581 WARN_ON(bar == test_reg_bar);
582 }
583 test->bar[bar] = base;
2c156ac7 584 }
2c156ac7
KVA
585 }
586
834b9051 587 test->base = test->bar[test_reg_bar];
2c156ac7 588 if (!test->base) {
80068c93 589 err = -ENOMEM;
834b9051
KVA
590 dev_err(dev, "Cannot perform PCI test without BAR%d\n",
591 test_reg_bar);
2c156ac7
KVA
592 goto err_iounmap;
593 }
594
595 pci_set_drvdata(pdev, test);
596
597 id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL);
598 if (id < 0) {
80068c93 599 err = id;
0e52ea61 600 dev_err(dev, "Unable to get id\n");
2c156ac7
KVA
601 goto err_iounmap;
602 }
603
604 snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id);
605 misc_device = &test->miscdev;
606 misc_device->minor = MISC_DYNAMIC_MINOR;
139838ff
KVA
607 misc_device->name = kstrdup(name, GFP_KERNEL);
608 if (!misc_device->name) {
609 err = -ENOMEM;
610 goto err_ida_remove;
611 }
2c156ac7
KVA
612 misc_device->fops = &pci_endpoint_test_fops,
613
614 err = misc_register(misc_device);
615 if (err) {
0e52ea61 616 dev_err(dev, "Failed to register device\n");
139838ff 617 goto err_kfree_name;
2c156ac7
KVA
618 }
619
620 return 0;
621
139838ff
KVA
622err_kfree_name:
623 kfree(misc_device->name);
624
2c156ac7
KVA
625err_ida_remove:
626 ida_simple_remove(&pci_endpoint_test_ida, id);
627
628err_iounmap:
629 for (bar = BAR_0; bar <= BAR_5; bar++) {
630 if (test->bar[bar])
631 pci_iounmap(pdev, test->bar[bar]);
632 }
633
b7636e81 634 for (i = 0; i < irq; i++)
ecc57efe 635 devm_free_irq(&pdev->dev, pci_irq_vector(pdev, i), test);
b7636e81 636
2c156ac7
KVA
637err_disable_msi:
638 pci_disable_msi(pdev);
c2e00e31 639 pci_disable_msix(pdev);
2c156ac7
KVA
640 pci_release_regions(pdev);
641
642err_disable_pdev:
643 pci_disable_device(pdev);
644
645 return err;
646}
647
648static void pci_endpoint_test_remove(struct pci_dev *pdev)
649{
650 int id;
b7636e81 651 int i;
2c156ac7
KVA
652 enum pci_barno bar;
653 struct pci_endpoint_test *test = pci_get_drvdata(pdev);
654 struct miscdevice *misc_device = &test->miscdev;
655
656 if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1)
657 return;
a2db2663
DC
658 if (id < 0)
659 return;
2c156ac7
KVA
660
661 misc_deregister(&test->miscdev);
139838ff 662 kfree(misc_device->name);
2c156ac7
KVA
663 ida_simple_remove(&pci_endpoint_test_ida, id);
664 for (bar = BAR_0; bar <= BAR_5; bar++) {
665 if (test->bar[bar])
666 pci_iounmap(pdev, test->bar[bar]);
667 }
b7636e81 668 for (i = 0; i < test->num_irqs; i++)
ecc57efe 669 devm_free_irq(&pdev->dev, pci_irq_vector(pdev, i), test);
2c156ac7 670 pci_disable_msi(pdev);
c2e00e31 671 pci_disable_msix(pdev);
2c156ac7
KVA
672 pci_release_regions(pdev);
673 pci_disable_device(pdev);
674}
675
676static const struct pci_device_id pci_endpoint_test_tbl[] = {
677 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x) },
678 { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x) },
14b06ddd 679 { PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, 0xedda) },
2c156ac7
KVA
680 { }
681};
682MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
683
684static struct pci_driver pci_endpoint_test_driver = {
685 .name = DRV_MODULE_NAME,
686 .id_table = pci_endpoint_test_tbl,
687 .probe = pci_endpoint_test_probe,
688 .remove = pci_endpoint_test_remove,
689};
690module_pci_driver(pci_endpoint_test_driver);
691
692MODULE_DESCRIPTION("PCI ENDPOINT TEST HOST DRIVER");
693MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
694MODULE_LICENSE("GPL v2");