Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Intel I/OAT DMA Linux driver
0004  * Copyright(c) 2004 - 2015 Intel Corporation.
0005  */
0006 
0007 #include <linux/init.h>
0008 #include <linux/module.h>
0009 #include <linux/dmaengine.h>
0010 #include <linux/pci.h>
0011 #include "dma.h"
0012 #include "registers.h"
0013 #include "hw.h"
0014 
0015 #include "../dmaengine.h"
0016 
0017 static ssize_t cap_show(struct dma_chan *c, char *page)
0018 {
0019     struct dma_device *dma = c->device;
0020 
0021     return sprintf(page, "copy%s%s%s%s%s\n",
0022                dma_has_cap(DMA_PQ, dma->cap_mask) ? " pq" : "",
0023                dma_has_cap(DMA_PQ_VAL, dma->cap_mask) ? " pq_val" : "",
0024                dma_has_cap(DMA_XOR, dma->cap_mask) ? " xor" : "",
0025                dma_has_cap(DMA_XOR_VAL, dma->cap_mask) ? " xor_val" : "",
0026                dma_has_cap(DMA_INTERRUPT, dma->cap_mask) ? " intr" : "");
0027 
0028 }
0029 struct ioat_sysfs_entry ioat_cap_attr = __ATTR_RO(cap);
0030 
0031 static ssize_t version_show(struct dma_chan *c, char *page)
0032 {
0033     struct dma_device *dma = c->device;
0034     struct ioatdma_device *ioat_dma = to_ioatdma_device(dma);
0035 
0036     return sprintf(page, "%d.%d\n",
0037                ioat_dma->version >> 4, ioat_dma->version & 0xf);
0038 }
0039 struct ioat_sysfs_entry ioat_version_attr = __ATTR_RO(version);
0040 
0041 static ssize_t
0042 ioat_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
0043 {
0044     struct ioat_sysfs_entry *entry;
0045     struct ioatdma_chan *ioat_chan;
0046 
0047     entry = container_of(attr, struct ioat_sysfs_entry, attr);
0048     ioat_chan = container_of(kobj, struct ioatdma_chan, kobj);
0049 
0050     if (!entry->show)
0051         return -EIO;
0052     return entry->show(&ioat_chan->dma_chan, page);
0053 }
0054 
0055 static ssize_t
0056 ioat_attr_store(struct kobject *kobj, struct attribute *attr,
0057 const char *page, size_t count)
0058 {
0059     struct ioat_sysfs_entry *entry;
0060     struct ioatdma_chan *ioat_chan;
0061 
0062     entry = container_of(attr, struct ioat_sysfs_entry, attr);
0063     ioat_chan = container_of(kobj, struct ioatdma_chan, kobj);
0064 
0065     if (!entry->store)
0066         return -EIO;
0067     return entry->store(&ioat_chan->dma_chan, page, count);
0068 }
0069 
0070 const struct sysfs_ops ioat_sysfs_ops = {
0071     .show   = ioat_attr_show,
0072     .store  = ioat_attr_store,
0073 };
0074 
0075 void ioat_kobject_add(struct ioatdma_device *ioat_dma, struct kobj_type *type)
0076 {
0077     struct dma_device *dma = &ioat_dma->dma_dev;
0078     struct dma_chan *c;
0079 
0080     list_for_each_entry(c, &dma->channels, device_node) {
0081         struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
0082         struct kobject *parent = &c->dev->device.kobj;
0083         int err;
0084 
0085         err = kobject_init_and_add(&ioat_chan->kobj, type,
0086                        parent, "quickdata");
0087         if (err) {
0088             dev_warn(to_dev(ioat_chan),
0089                  "sysfs init error (%d), continuing...\n", err);
0090             kobject_put(&ioat_chan->kobj);
0091             set_bit(IOAT_KOBJ_INIT_FAIL, &ioat_chan->state);
0092         }
0093     }
0094 }
0095 
0096 void ioat_kobject_del(struct ioatdma_device *ioat_dma)
0097 {
0098     struct dma_device *dma = &ioat_dma->dma_dev;
0099     struct dma_chan *c;
0100 
0101     list_for_each_entry(c, &dma->channels, device_node) {
0102         struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
0103 
0104         if (!test_bit(IOAT_KOBJ_INIT_FAIL, &ioat_chan->state)) {
0105             kobject_del(&ioat_chan->kobj);
0106             kobject_put(&ioat_chan->kobj);
0107         }
0108     }
0109 }
0110 
0111 static ssize_t ring_size_show(struct dma_chan *c, char *page)
0112 {
0113     struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
0114 
0115     return sprintf(page, "%d\n", (1 << ioat_chan->alloc_order) & ~1);
0116 }
0117 static struct ioat_sysfs_entry ring_size_attr = __ATTR_RO(ring_size);
0118 
0119 static ssize_t ring_active_show(struct dma_chan *c, char *page)
0120 {
0121     struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
0122 
0123     /* ...taken outside the lock, no need to be precise */
0124     return sprintf(page, "%d\n", ioat_ring_active(ioat_chan));
0125 }
0126 static struct ioat_sysfs_entry ring_active_attr = __ATTR_RO(ring_active);
0127 
0128 static ssize_t intr_coalesce_show(struct dma_chan *c, char *page)
0129 {
0130     struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
0131 
0132     return sprintf(page, "%d\n", ioat_chan->intr_coalesce);
0133 }
0134 
0135 static ssize_t intr_coalesce_store(struct dma_chan *c, const char *page,
0136 size_t count)
0137 {
0138     int intr_coalesce = 0;
0139     struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
0140 
0141     if (sscanf(page, "%du", &intr_coalesce) != -1) {
0142         if ((intr_coalesce < 0) ||
0143             (intr_coalesce > IOAT_INTRDELAY_MASK))
0144             return -EINVAL;
0145         ioat_chan->intr_coalesce = intr_coalesce;
0146     }
0147 
0148     return count;
0149 }
0150 
0151 static struct ioat_sysfs_entry intr_coalesce_attr = __ATTR_RW(intr_coalesce);
0152 
0153 static struct attribute *ioat_attrs[] = {
0154     &ring_size_attr.attr,
0155     &ring_active_attr.attr,
0156     &ioat_cap_attr.attr,
0157     &ioat_version_attr.attr,
0158     &intr_coalesce_attr.attr,
0159     NULL,
0160 };
0161 ATTRIBUTE_GROUPS(ioat);
0162 
0163 struct kobj_type ioat_ktype = {
0164     .sysfs_ops = &ioat_sysfs_ops,
0165     .default_groups = ioat_groups,
0166 };