On 07/20/2017 11:34 PM, Vinod Koul wrote: > On Wed, Jul 19, 2017 at 07:25:41PM -0400, Ujjal Singh wrote: >> We observed performance increase with DMA copy from memory >> to MMIO by changing the interrupt coalescing value to 0. >> The previous set value was projected on the C5xxx Xeon >> platform and no longer holds true. Removing hard coded >> value and providing a tune-able in sysfs in order to allow >> user to tune this on a per channel basis. By default this >> value will be set to 0. >> Example of sysfs variable importing for interrupt coalescing >> value from command line: >> echo 5> /sys/devices/pci0000:00/0000:00:04.0/dma/dma0chan0/ >> quickdata/intr_coalesce >> >> Reported-by: Nithin Sujir <nsujir@xxxxxxxxxx> >> Signed-off-by: Ujjal Singh <ujjal.singh@xxxxxxxxx> >> --- >> V2: Addressed Dave's comments: >>> Removed definition INTR_DELAY_REG_LIMIT in hw.h and used >>> existing definition IOAT_INTRDELAY_MASK instead to check >>> interrupt delay limit in sysfs.c >> >> Vinod's comment about ABI doc will come in a different patch >> to add ABI doc for ioatdma. > > Sure, but we should send that first and add ABI documentation for this new > file in current patch or part of this series This one can go in now right? > >> >> drivers/dma/ioat/dma.c | 10 +++++++--- >> drivers/dma/ioat/dma.h | 3 +++ >> drivers/dma/ioat/sysfs.c | 42 ++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 52 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c >> index a371b07..f70cc74 100644 >> --- a/drivers/dma/ioat/dma.c >> +++ b/drivers/dma/ioat/dma.c >> @@ -644,9 +644,13 @@ static void __cleanup(struct ioatdma_chan *ioat_chan, dma_addr_t phys_complete) >> mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT); >> } >> >> - /* 5 microsecond delay per pending descriptor */ >> - writew(min((5 * (active - i)), IOAT_INTRDELAY_MASK), >> - ioat_chan->ioat_dma->reg_base + IOAT_INTRDELAY_OFFSET); >> + /* microsecond delay by sysfs variable per pending descriptor */ >> + if (ioat_chan->intr_coalesce != ioat_chan->prev_intr_coalesce) { >> + writew(min((ioat_chan->intr_coalesce * (active - i)), >> + IOAT_INTRDELAY_MASK), >> + ioat_chan->ioat_dma->reg_base + IOAT_INTRDELAY_OFFSET); >> + ioat_chan->prev_intr_coalesce = ioat_chan->intr_coalesce; >> + } >> } >> >> static void ioat_cleanup(struct ioatdma_chan *ioat_chan) >> diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h >> index a9bc1a1..56200ee 100644 >> --- a/drivers/dma/ioat/dma.h >> +++ b/drivers/dma/ioat/dma.h >> @@ -142,11 +142,14 @@ struct ioatdma_chan { >> spinlock_t prep_lock; >> struct ioat_descs descs[2]; >> int desc_chunks; >> + int intr_coalesce; >> + int prev_intr_coalesce; >> }; >> >> struct ioat_sysfs_entry { >> struct attribute attr; >> ssize_t (*show)(struct dma_chan *, char *); >> + ssize_t (*store)(struct dma_chan *, const char *, size_t); >> }; >> >> /** >> diff --git a/drivers/dma/ioat/sysfs.c b/drivers/dma/ioat/sysfs.c >> index cb4a857..3ac677f 100644 >> --- a/drivers/dma/ioat/sysfs.c >> +++ b/drivers/dma/ioat/sysfs.c >> @@ -64,8 +64,24 @@ ioat_attr_show(struct kobject *kobj, struct attribute *attr, char *page) >> return entry->show(&ioat_chan->dma_chan, page); >> } >> >> +static ssize_t >> +ioat_attr_store(struct kobject *kobj, struct attribute *attr, >> +const char *page, size_t count) >> +{ >> + struct ioat_sysfs_entry *entry; >> + struct ioatdma_chan *ioat_chan; >> + >> + entry = container_of(attr, struct ioat_sysfs_entry, attr); >> + ioat_chan = container_of(kobj, struct ioatdma_chan, kobj); >> + >> + if (!entry->store) >> + return -EIO; >> + return entry->store(&ioat_chan->dma_chan, page, count); >> +} >> + >> const struct sysfs_ops ioat_sysfs_ops = { >> .show = ioat_attr_show, >> + .store = ioat_attr_store, >> }; >> >> void ioat_kobject_add(struct ioatdma_device *ioat_dma, struct kobj_type *type) >> @@ -121,11 +137,37 @@ static ssize_t ring_active_show(struct dma_chan *c, char *page) >> } >> static struct ioat_sysfs_entry ring_active_attr = __ATTR_RO(ring_active); >> >> +static ssize_t intr_coalesce_show(struct dma_chan *c, char *page) >> +{ >> + struct ioatdma_chan *ioat_chan = to_ioat_chan(c); >> + >> + return sprintf(page, "%d\n", ioat_chan->intr_coalesce); >> +} >> + >> +static ssize_t intr_coalesce_store(struct dma_chan *c, const char *page, >> +size_t count) >> +{ >> + int intr_coalesce = 0; >> + struct ioatdma_chan *ioat_chan = to_ioat_chan(c); >> + >> + if (sscanf(page, "%du", &intr_coalesce) != -1) { >> + if ((intr_coalesce < 0) || >> + (intr_coalesce > IOAT_INTRDELAY_MASK)) >> + return -EINVAL; >> + ioat_chan->intr_coalesce = intr_coalesce; >> + } >> + >> + return count; >> +} >> + >> +static struct ioat_sysfs_entry intr_coalesce_attr = __ATTR_RW(intr_coalesce); >> + >> static struct attribute *ioat_attrs[] = { >> &ring_size_attr.attr, >> &ring_active_attr.attr, >> &ioat_cap_attr.attr, >> &ioat_version_attr.attr, >> + &intr_coalesce_attr.attr, >> NULL, >> }; >> >> > -- To unsubscribe from this list: send the line "unsubscribe dmaengine" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html