aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/pci_endpoint_test.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-08 18:47:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-08 18:47:43 -0400
commit0d519f2d1ed1f11e49abc88cfcf6cf13b83ba14c (patch)
treefe2bfed7c6e8448f9661216610ec81f1e0c28515 /drivers/misc/pci_endpoint_test.c
parent0756b7fbb696d2cb18785da9cab13ec164017f64 (diff)
parentcf2d804110d3c20dc6865ade514c44179de34855 (diff)
Merge tag 'pci-v4.14-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas: - add enhanced Downstream Port Containment support, which prints more details about Root Port Programmed I/O errors (Dongdong Liu) - add Layerscape ls1088a and ls2088a support (Hou Zhiqiang) - add MediaTek MT2712 and MT7622 support (Ryder Lee) - add MediaTek MT2712 and MT7622 MSI support (Honghui Zhang) - add Qualcom IPQ8074 support (Varadarajan Narayanan) - add R-Car r8a7743/5 device tree support (Biju Das) - add Rockchip per-lane PHY support for better power management (Shawn Lin) - fix IRQ mapping for hot-added devices by replacing the pci_fixup_irqs() boot-time design with a host bridge hook called at probe-time (Lorenzo Pieralisi, Matthew Minter) - fix race when enabling two devices that results in upstream bridge not being enabled correctly (Srinath Mannam) - fix pciehp power fault infinite loop (Keith Busch) - fix SHPC bridge MSI hotplug events by enabling bus mastering (Aleksandr Bezzubikov) - fix a VFIO issue by correcting PCIe capability sizes (Alex Williamson) - fix an INTD issue on Xilinx and possibly other drivers by unifying INTx IRQ domain support (Paul Burton) - avoid IOMMU stalls by marking AMD Stoney GPU ATS as broken (Joerg Roedel) - allow APM X-Gene device assignment to guests by adding an ACS quirk (Feng Kan) - fix driver crashes by disabling Extended Tags on Broadcom HT2100 (Extended Tags support is required for PCIe Receivers but not Requesters, and we now enable them by default when Requesters support them) (Sinan Kaya) - fix MSIs for devices that use phantom RIDs for DMA by assuming MSIs use the real Requester ID (not a phantom RID) (Robin Murphy) - prevent assignment of Intel VMD children to guests (which may be supported eventually, but isn't yet) by not associating an IOMMU with them (Jon Derrick) - fix Intel VMD suspend/resume by releasing IRQs on suspend (Scott Bauer) - fix a Function-Level Reset issue with Intel 750 NVMe by waiting longer (up to 60sec instead of 1sec) for device to become ready (Sinan Kaya) - fix a Function-Level Reset issue on iProc Stingray by working around hardware defects in the CRS implementation (Oza Pawandeep) - fix an issue with Intel NVMe P3700 after an iProc reset by adding a delay during shutdown (Oza Pawandeep) - fix a Microsoft Hyper-V lockdep issue by polling instead of blocking in compose_msi_msg() (Stephen Hemminger) - fix a wireless LAN driver timeout by clearing DesignWare MSI interrupt status after it is handled, not before (Faiz Abbas) - fix DesignWare ATU enable checking (Jisheng Zhang) - reduce Layerscape dependencies on the bootloader by doing more initialization in the driver (Hou Zhiqiang) - improve Intel VMD performance allowing allocation of more IRQ vectors than present CPUs (Keith Busch) - improve endpoint framework support for initial DMA mask, different BAR sizes, configurable page sizes, MSI, test driver, etc (Kishon Vijay Abraham I, Stan Drozd) - rework CRS support to add periodic messages while we poll during enumeration and after Function-Level Reset and prepare for possible other uses of CRS (Sinan Kaya) - clean up Root Port AER handling by removing unnecessary code and moving error handler methods to struct pcie_port_service_driver (Christoph Hellwig) - clean up error handling paths in various drivers (Bjorn Andersson, Fabio Estevam, Gustavo A. R. Silva, Harunobu Kurokawa, Jeffy Chen, Lorenzo Pieralisi, Sergei Shtylyov) - clean up SR-IOV resource handling by disabling VF decoding before updating the corresponding resource structs (Gavin Shan) - clean up DesignWare-based drivers by unifying quirks to update Class Code and Interrupt Pin and related handling of write-protected registers (Hou Zhiqiang) - clean up by adding empty generic pcibios_align_resource() and pcibios_fixup_bus() and removing empty arch-specific implementations (Palmer Dabbelt) - request exclusive reset control for several drivers to allow cleanup elsewhere (Philipp Zabel) - constify various structures (Arvind Yadav, Bhumika Goyal) - convert from full_name() to %pOF (Rob Herring) - remove unused variables from iProc, HiSi, Altera, Keystone (Shawn Lin) * tag 'pci-v4.14-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (170 commits) PCI: xgene: Clean up whitespace PCI: xgene: Define XGENE_PCI_EXP_CAP and use generic PCI_EXP_RTCTL offset PCI: xgene: Fix platform_get_irq() error handling PCI: xilinx-nwl: Fix platform_get_irq() error handling PCI: rockchip: Fix platform_get_irq() error handling PCI: altera: Fix platform_get_irq() error handling PCI: spear13xx: Fix platform_get_irq() error handling PCI: artpec6: Fix platform_get_irq() error handling PCI: armada8k: Fix platform_get_irq() error handling PCI: dra7xx: Fix platform_get_irq() error handling PCI: exynos: Fix platform_get_irq() error handling PCI: iproc: Clean up whitespace PCI: iproc: Rename PCI_EXP_CAP to IPROC_PCI_EXP_CAP PCI: iproc: Add 500ms delay during device shutdown PCI: Fix typos and whitespace errors PCI: Remove unused "res" variable from pci_resource_io() PCI: Correct kernel-doc of pci_vpd_srdt_size(), pci_vpd_srdt_tag() PCI/AER: Reformat AER register definitions iommu/vt-d: Prevent VMD child devices from being remapping targets x86/PCI: Use is_vmd() rather than relying on the domain number ...
Diffstat (limited to 'drivers/misc/pci_endpoint_test.c')
-rw-r--r--drivers/misc/pci_endpoint_test.c132
1 files changed, 109 insertions, 23 deletions
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index 09c10f426b64..deb203026496 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -72,6 +72,11 @@ static DEFINE_IDA(pci_endpoint_test_ida);
72 72
73#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \ 73#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
74 miscdev) 74 miscdev)
75
76static bool no_msi;
77module_param(no_msi, bool, 0444);
78MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test");
79
75enum pci_barno { 80enum pci_barno {
76 BAR_0, 81 BAR_0,
77 BAR_1, 82 BAR_1,
@@ -90,9 +95,15 @@ struct pci_endpoint_test {
90 /* mutex to protect the ioctls */ 95 /* mutex to protect the ioctls */
91 struct mutex mutex; 96 struct mutex mutex;
92 struct miscdevice miscdev; 97 struct miscdevice miscdev;
98 enum pci_barno test_reg_bar;
99 size_t alignment;
93}; 100};
94 101
95static int bar_size[] = { 4, 512, 1024, 16384, 131072, 1048576 }; 102struct pci_endpoint_test_data {
103 enum pci_barno test_reg_bar;
104 size_t alignment;
105 bool no_msi;
106};
96 107
97static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test, 108static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
98 u32 offset) 109 u32 offset)
@@ -141,11 +152,15 @@ static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
141 int j; 152 int j;
142 u32 val; 153 u32 val;
143 int size; 154 int size;
155 struct pci_dev *pdev = test->pdev;
144 156
145 if (!test->bar[barno]) 157 if (!test->bar[barno])
146 return false; 158 return false;
147 159
148 size = bar_size[barno]; 160 size = pci_resource_len(pdev, barno);
161
162 if (barno == test->test_reg_bar)
163 size = 0x4;
149 164
150 for (j = 0; j < size; j += 4) 165 for (j = 0; j < size; j += 4)
151 pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0); 166 pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0);
@@ -202,16 +217,32 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
202 dma_addr_t dst_phys_addr; 217 dma_addr_t dst_phys_addr;
203 struct pci_dev *pdev = test->pdev; 218 struct pci_dev *pdev = test->pdev;
204 struct device *dev = &pdev->dev; 219 struct device *dev = &pdev->dev;
220 void *orig_src_addr;
221 dma_addr_t orig_src_phys_addr;
222 void *orig_dst_addr;
223 dma_addr_t orig_dst_phys_addr;
224 size_t offset;
225 size_t alignment = test->alignment;
205 u32 src_crc32; 226 u32 src_crc32;
206 u32 dst_crc32; 227 u32 dst_crc32;
207 228
208 src_addr = dma_alloc_coherent(dev, size, &src_phys_addr, GFP_KERNEL); 229 orig_src_addr = dma_alloc_coherent(dev, size + alignment,
209 if (!src_addr) { 230 &orig_src_phys_addr, GFP_KERNEL);
231 if (!orig_src_addr) {
210 dev_err(dev, "failed to allocate source buffer\n"); 232 dev_err(dev, "failed to allocate source buffer\n");
211 ret = false; 233 ret = false;
212 goto err; 234 goto err;
213 } 235 }
214 236
237 if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) {
238 src_phys_addr = PTR_ALIGN(orig_src_phys_addr, alignment);
239 offset = src_phys_addr - orig_src_phys_addr;
240 src_addr = orig_src_addr + offset;
241 } else {
242 src_phys_addr = orig_src_phys_addr;
243 src_addr = orig_src_addr;
244 }
245
215 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR, 246 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
216 lower_32_bits(src_phys_addr)); 247 lower_32_bits(src_phys_addr));
217 248
@@ -221,11 +252,21 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
221 get_random_bytes(src_addr, size); 252 get_random_bytes(src_addr, size);
222 src_crc32 = crc32_le(~0, src_addr, size); 253 src_crc32 = crc32_le(~0, src_addr, size);
223 254
224 dst_addr = dma_alloc_coherent(dev, size, &dst_phys_addr, GFP_KERNEL); 255 orig_dst_addr = dma_alloc_coherent(dev, size + alignment,
225 if (!dst_addr) { 256 &orig_dst_phys_addr, GFP_KERNEL);
257 if (!orig_dst_addr) {
226 dev_err(dev, "failed to allocate destination address\n"); 258 dev_err(dev, "failed to allocate destination address\n");
227 ret = false; 259 ret = false;
228 goto err_src_addr; 260 goto err_orig_src_addr;
261 }
262
263 if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) {
264 dst_phys_addr = PTR_ALIGN(orig_dst_phys_addr, alignment);
265 offset = dst_phys_addr - orig_dst_phys_addr;
266 dst_addr = orig_dst_addr + offset;
267 } else {
268 dst_phys_addr = orig_dst_phys_addr;
269 dst_addr = orig_dst_addr;
229 } 270 }
230 271
231 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR, 272 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
@@ -245,10 +286,12 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
245 if (dst_crc32 == src_crc32) 286 if (dst_crc32 == src_crc32)
246 ret = true; 287 ret = true;
247 288
248 dma_free_coherent(dev, size, dst_addr, dst_phys_addr); 289 dma_free_coherent(dev, size + alignment, orig_dst_addr,
290 orig_dst_phys_addr);
249 291
250err_src_addr: 292err_orig_src_addr:
251 dma_free_coherent(dev, size, src_addr, src_phys_addr); 293 dma_free_coherent(dev, size + alignment, orig_src_addr,
294 orig_src_phys_addr);
252 295
253err: 296err:
254 return ret; 297 return ret;
@@ -262,15 +305,29 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
262 dma_addr_t phys_addr; 305 dma_addr_t phys_addr;
263 struct pci_dev *pdev = test->pdev; 306 struct pci_dev *pdev = test->pdev;
264 struct device *dev = &pdev->dev; 307 struct device *dev = &pdev->dev;
308 void *orig_addr;
309 dma_addr_t orig_phys_addr;
310 size_t offset;
311 size_t alignment = test->alignment;
265 u32 crc32; 312 u32 crc32;
266 313
267 addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL); 314 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
268 if (!addr) { 315 GFP_KERNEL);
316 if (!orig_addr) {
269 dev_err(dev, "failed to allocate address\n"); 317 dev_err(dev, "failed to allocate address\n");
270 ret = false; 318 ret = false;
271 goto err; 319 goto err;
272 } 320 }
273 321
322 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
323 phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
324 offset = phys_addr - orig_phys_addr;
325 addr = orig_addr + offset;
326 } else {
327 phys_addr = orig_phys_addr;
328 addr = orig_addr;
329 }
330
274 get_random_bytes(addr, size); 331 get_random_bytes(addr, size);
275 332
276 crc32 = crc32_le(~0, addr, size); 333 crc32 = crc32_le(~0, addr, size);
@@ -293,7 +350,7 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
293 if (reg & STATUS_READ_SUCCESS) 350 if (reg & STATUS_READ_SUCCESS)
294 ret = true; 351 ret = true;
295 352
296 dma_free_coherent(dev, size, addr, phys_addr); 353 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
297 354
298err: 355err:
299 return ret; 356 return ret;
@@ -306,15 +363,29 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
306 dma_addr_t phys_addr; 363 dma_addr_t phys_addr;
307 struct pci_dev *pdev = test->pdev; 364 struct pci_dev *pdev = test->pdev;
308 struct device *dev = &pdev->dev; 365 struct device *dev = &pdev->dev;
366 void *orig_addr;
367 dma_addr_t orig_phys_addr;
368 size_t offset;
369 size_t alignment = test->alignment;
309 u32 crc32; 370 u32 crc32;
310 371
311 addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL); 372 orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
312 if (!addr) { 373 GFP_KERNEL);
374 if (!orig_addr) {
313 dev_err(dev, "failed to allocate destination address\n"); 375 dev_err(dev, "failed to allocate destination address\n");
314 ret = false; 376 ret = false;
315 goto err; 377 goto err;
316 } 378 }
317 379
380 if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
381 phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
382 offset = phys_addr - orig_phys_addr;
383 addr = orig_addr + offset;
384 } else {
385 phys_addr = orig_phys_addr;
386 addr = orig_addr;
387 }
388
318 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR, 389 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
319 lower_32_bits(phys_addr)); 390 lower_32_bits(phys_addr));
320 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR, 391 pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
@@ -331,7 +402,7 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
331 if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM)) 402 if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
332 ret = true; 403 ret = true;
333 404
334 dma_free_coherent(dev, size, addr, phys_addr); 405 dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
335err: 406err:
336 return ret; 407 return ret;
337} 408}
@@ -383,13 +454,15 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
383{ 454{
384 int i; 455 int i;
385 int err; 456 int err;
386 int irq; 457 int irq = 0;
387 int id; 458 int id;
388 char name[20]; 459 char name[20];
389 enum pci_barno bar; 460 enum pci_barno bar;
390 void __iomem *base; 461 void __iomem *base;
391 struct device *dev = &pdev->dev; 462 struct device *dev = &pdev->dev;
392 struct pci_endpoint_test *test; 463 struct pci_endpoint_test *test;
464 struct pci_endpoint_test_data *data;
465 enum pci_barno test_reg_bar = BAR_0;
393 struct miscdevice *misc_device; 466 struct miscdevice *misc_device;
394 467
395 if (pci_is_bridge(pdev)) 468 if (pci_is_bridge(pdev))
@@ -399,7 +472,17 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
399 if (!test) 472 if (!test)
400 return -ENOMEM; 473 return -ENOMEM;
401 474
475 test->test_reg_bar = 0;
476 test->alignment = 0;
402 test->pdev = pdev; 477 test->pdev = pdev;
478
479 data = (struct pci_endpoint_test_data *)ent->driver_data;
480 if (data) {
481 test_reg_bar = data->test_reg_bar;
482 test->alignment = data->alignment;
483 no_msi = data->no_msi;
484 }
485
403 init_completion(&test->irq_raised); 486 init_completion(&test->irq_raised);
404 mutex_init(&test->mutex); 487 mutex_init(&test->mutex);
405 488
@@ -417,9 +500,11 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
417 500
418 pci_set_master(pdev); 501 pci_set_master(pdev);
419 502
420 irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); 503 if (!no_msi) {
421 if (irq < 0) 504 irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
422 dev_err(dev, "failed to get MSI interrupts\n"); 505 if (irq < 0)
506 dev_err(dev, "failed to get MSI interrupts\n");
507 }
423 508
424 err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, 509 err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler,
425 IRQF_SHARED, DRV_MODULE_NAME, test); 510 IRQF_SHARED, DRV_MODULE_NAME, test);
@@ -441,14 +526,15 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
441 base = pci_ioremap_bar(pdev, bar); 526 base = pci_ioremap_bar(pdev, bar);
442 if (!base) { 527 if (!base) {
443 dev_err(dev, "failed to read BAR%d\n", bar); 528 dev_err(dev, "failed to read BAR%d\n", bar);
444 WARN_ON(bar == BAR_0); 529 WARN_ON(bar == test_reg_bar);
445 } 530 }
446 test->bar[bar] = base; 531 test->bar[bar] = base;
447 } 532 }
448 533
449 test->base = test->bar[0]; 534 test->base = test->bar[test_reg_bar];
450 if (!test->base) { 535 if (!test->base) {
451 dev_err(dev, "Cannot perform PCI test without BAR0\n"); 536 dev_err(dev, "Cannot perform PCI test without BAR%d\n",
537 test_reg_bar);
452 goto err_iounmap; 538 goto err_iounmap;
453 } 539 }
454 540