PCI: endpoint: functions/pci-epf-test: Print throughput information
authorKishon Vijay Abraham I <kishon@ti.com>
Mon, 16 Mar 2020 11:24:21 +0000 (16:54 +0530)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Thu, 2 Apr 2020 16:57:10 +0000 (17:57 +0100)
Print throughput information in KB/s after every completed transfer,
including information on whether DMA is used or not.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Tested-by: Alan Mikhak <alan.mikhak@sifive.com>
drivers/pci/endpoint/functions/pci-epf-test.c

index 737e15d..0a5019c 100644 (file)
@@ -190,6 +190,36 @@ static void pci_epf_test_clean_dma_chan(struct pci_epf_test *epf_test)
        epf_test->dma_chan = NULL;
 }
 
+static void pci_epf_test_print_rate(const char *ops, u64 size,
+                                   struct timespec64 *start,
+                                   struct timespec64 *end, bool dma)
+{
+       struct timespec64 ts;
+       u64 rate, ns;
+
+       ts = timespec64_sub(*end, *start);
+
+       /* convert both size (stored in 'rate') and time in terms of 'ns' */
+       ns = timespec64_to_ns(&ts);
+       rate = size * NSEC_PER_SEC;
+
+       /* Divide both size (stored in 'rate') and ns by a common factor */
+       while (ns > UINT_MAX) {
+               rate >>= 1;
+               ns >>= 1;
+       }
+
+       if (!ns)
+               return;
+
+       /* calculate the rate */
+       do_div(rate, (uint32_t)ns);
+
+       pr_info("\n%s => Size: %llu bytes\t DMA: %s\t Time: %llu.%09u seconds\t"
+               "Rate: %llu KB/s\n", ops, size, dma ? "YES" : "NO",
+               (u64)ts.tv_sec, (u32)ts.tv_nsec, rate / 1024);
+}
+
 static int pci_epf_test_copy(struct pci_epf_test *epf_test)
 {
        int ret;
@@ -198,6 +228,7 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
        void __iomem *dst_addr;
        phys_addr_t src_phys_addr;
        phys_addr_t dst_phys_addr;
+       struct timespec64 start, end;
        struct pci_epf *epf = epf_test->epf;
        struct device *dev = &epf->dev;
        struct pci_epc *epc = epf->epc;
@@ -236,6 +267,7 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
                goto err_dst_addr;
        }
 
+       ktime_get_ts64(&start);
        use_dma = !!(reg->flags & FLAG_USE_DMA);
        if (use_dma) {
                if (!epf_test->dma_supported) {
@@ -251,6 +283,8 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
        } else {
                memcpy(dst_addr, src_addr, reg->size);
        }
+       ktime_get_ts64(&end);
+       pci_epf_test_print_rate("COPY", reg->size, &start, &end, use_dma);
 
 err_map_addr:
        pci_epc_unmap_addr(epc, epf->func_no, dst_phys_addr);
@@ -277,6 +311,7 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test)
        bool use_dma;
        phys_addr_t phys_addr;
        phys_addr_t dst_phys_addr;
+       struct timespec64 start, end;
        struct pci_epf *epf = epf_test->epf;
        struct device *dev = &epf->dev;
        struct pci_epc *epc = epf->epc;
@@ -322,17 +357,23 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test)
                        goto err_dma_map;
                }
 
+               ktime_get_ts64(&start);
                ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr,
                                                 phys_addr, reg->size);
                if (ret)
                        dev_err(dev, "Data transfer failed\n");
+               ktime_get_ts64(&end);
 
                dma_unmap_single(dma_dev, dst_phys_addr, reg->size,
                                 DMA_FROM_DEVICE);
        } else {
+               ktime_get_ts64(&start);
                memcpy_fromio(buf, src_addr, reg->size);
+               ktime_get_ts64(&end);
        }
 
+       pci_epf_test_print_rate("READ", reg->size, &start, &end, use_dma);
+
        crc32 = crc32_le(~0, buf, reg->size);
        if (crc32 != reg->checksum)
                ret = -EIO;
@@ -358,6 +399,7 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test)
        bool use_dma;
        phys_addr_t phys_addr;
        phys_addr_t src_phys_addr;
+       struct timespec64 start, end;
        struct pci_epf *epf = epf_test->epf;
        struct device *dev = &epf->dev;
        struct pci_epc *epc = epf->epc;
@@ -406,17 +448,23 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test)
                        goto err_dma_map;
                }
 
+               ktime_get_ts64(&start);
                ret = pci_epf_test_data_transfer(epf_test, phys_addr,
                                                 src_phys_addr, reg->size);
                if (ret)
                        dev_err(dev, "Data transfer failed\n");
+               ktime_get_ts64(&end);
 
                dma_unmap_single(dma_dev, src_phys_addr, reg->size,
                                 DMA_TO_DEVICE);
        } else {
+               ktime_get_ts64(&start);
                memcpy_toio(dst_addr, buf, reg->size);
+               ktime_get_ts64(&end);
        }
 
+       pci_epf_test_print_rate("WRITE", reg->size, &start, &end, use_dma);
+
        /*
         * wait 1ms inorder for the write to complete. Without this delay L3
         * error in observed in the host system.