On 06/23/2017 05:00 PM, 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> Acked-by: Dave Jiang <dave.jiang@xxxxxxxxx> > --- > drivers/dma/ioat/dma.c | 10 +++++++--- > drivers/dma/ioat/dma.h | 3 +++ > drivers/dma/ioat/hw.h | 1 + > drivers/dma/ioat/sysfs.c | 42 ++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 53 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/hw.h b/drivers/dma/ioat/hw.h > index abcc51b..6cd540c 100644 > --- a/drivers/dma/ioat/hw.h > +++ b/drivers/dma/ioat/hw.h > @@ -72,6 +72,7 @@ > #define IOAT_VER_3_2 0x32 /* Version 3.2 */ > #define IOAT_VER_3_3 0x33 /* Version 3.3 */ > > +#define INTR_DELAY_REG_LIMIT 0x3fff > > int system_has_dca_enabled(struct pci_dev *pdev); > > diff --git a/drivers/dma/ioat/sysfs.c b/drivers/dma/ioat/sysfs.c > index cb4a857..d7df044 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 > INTR_DELAY_REG_LIMIT)) > + 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 > -- 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