1 /* 2 * Intel I/OAT DMA Linux driver 3 * Copyright(c) 2004 - 2015 Intel Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * The full GNU General Public License is included in this distribution in 15 * the file called "COPYING". 16 * 17 */ 18 19 #include <linux/init.h> 20 #include <linux/module.h> 21 #include <linux/dmaengine.h> 22 #include <linux/pci.h> 23 #include "dma.h" 24 #include "registers.h" 25 #include "hw.h" 26 27 #include "../dmaengine.h" 28 29 static ssize_t cap_show(struct dma_chan *c, char *page) 30 { 31 struct dma_device *dma = c->device; 32 33 return sprintf(page, "copy%s%s%s%s%s\n", 34 dma_has_cap(DMA_PQ, dma->cap_mask) ? " pq" : "", 35 dma_has_cap(DMA_PQ_VAL, dma->cap_mask) ? " pq_val" : "", 36 dma_has_cap(DMA_XOR, dma->cap_mask) ? " xor" : "", 37 dma_has_cap(DMA_XOR_VAL, dma->cap_mask) ? " xor_val" : "", 38 dma_has_cap(DMA_INTERRUPT, dma->cap_mask) ? " intr" : ""); 39 40 } 41 struct ioat_sysfs_entry ioat_cap_attr = __ATTR_RO(cap); 42 43 static ssize_t version_show(struct dma_chan *c, char *page) 44 { 45 struct dma_device *dma = c->device; 46 struct ioatdma_device *ioat_dma = to_ioatdma_device(dma); 47 48 return sprintf(page, "%d.%d\n", 49 ioat_dma->version >> 4, ioat_dma->version & 0xf); 50 } 51 struct ioat_sysfs_entry ioat_version_attr = __ATTR_RO(version); 52 53 static ssize_t 54 ioat_attr_show(struct kobject *kobj, struct attribute *attr, char *page) 55 { 56 struct ioat_sysfs_entry *entry; 57 struct ioatdma_chan *ioat_chan; 58 59 entry = container_of(attr, struct ioat_sysfs_entry, attr); 60 ioat_chan = container_of(kobj, struct ioatdma_chan, kobj); 61 62 if (!entry->show) 63 return -EIO; 64 return entry->show(&ioat_chan->dma_chan, page); 65 } 66 67 static ssize_t 68 ioat_attr_store(struct kobject *kobj, struct attribute *attr, 69 const char *page, size_t count) 70 { 71 struct ioat_sysfs_entry *entry; 72 struct ioatdma_chan *ioat_chan; 73 74 entry = container_of(attr, struct ioat_sysfs_entry, attr); 75 ioat_chan = container_of(kobj, struct ioatdma_chan, kobj); 76 77 if (!entry->store) 78 return -EIO; 79 return entry->store(&ioat_chan->dma_chan, page, count); 80 } 81 82 const struct sysfs_ops ioat_sysfs_ops = { 83 .show = ioat_attr_show, 84 .store = ioat_attr_store, 85 }; 86 87 void ioat_kobject_add(struct ioatdma_device *ioat_dma, struct kobj_type *type) 88 { 89 struct dma_device *dma = &ioat_dma->dma_dev; 90 struct dma_chan *c; 91 92 list_for_each_entry(c, &dma->channels, device_node) { 93 struct ioatdma_chan *ioat_chan = to_ioat_chan(c); 94 struct kobject *parent = &c->dev->device.kobj; 95 int err; 96 97 err = kobject_init_and_add(&ioat_chan->kobj, type, 98 parent, "quickdata"); 99 if (err) { 100 dev_warn(to_dev(ioat_chan), 101 "sysfs init error (%d), continuing...\n", err); 102 kobject_put(&ioat_chan->kobj); 103 set_bit(IOAT_KOBJ_INIT_FAIL, &ioat_chan->state); 104 } 105 } 106 } 107 108 void ioat_kobject_del(struct ioatdma_device *ioat_dma) 109 { 110 struct dma_device *dma = &ioat_dma->dma_dev; 111 struct dma_chan *c; 112 113 list_for_each_entry(c, &dma->channels, device_node) { 114 struct ioatdma_chan *ioat_chan = to_ioat_chan(c); 115 116 if (!test_bit(IOAT_KOBJ_INIT_FAIL, &ioat_chan->state)) { 117 kobject_del(&ioat_chan->kobj); 118 kobject_put(&ioat_chan->kobj); 119 } 120 } 121 } 122 123 static ssize_t ring_size_show(struct dma_chan *c, char *page) 124 { 125 struct ioatdma_chan *ioat_chan = to_ioat_chan(c); 126 127 return sprintf(page, "%d\n", (1 << ioat_chan->alloc_order) & ~1); 128 } 129 static struct ioat_sysfs_entry ring_size_attr = __ATTR_RO(ring_size); 130 131 static ssize_t ring_active_show(struct dma_chan *c, char *page) 132 { 133 struct ioatdma_chan *ioat_chan = to_ioat_chan(c); 134 135 /* ...taken outside the lock, no need to be precise */ 136 return sprintf(page, "%d\n", ioat_ring_active(ioat_chan)); 137 } 138 static struct ioat_sysfs_entry ring_active_attr = __ATTR_RO(ring_active); 139 140 static ssize_t intr_coalesce_show(struct dma_chan *c, char *page) 141 { 142 struct ioatdma_chan *ioat_chan = to_ioat_chan(c); 143 144 return sprintf(page, "%d\n", ioat_chan->intr_coalesce); 145 } 146 147 static ssize_t intr_coalesce_store(struct dma_chan *c, const char *page, 148 size_t count) 149 { 150 int intr_coalesce = 0; 151 struct ioatdma_chan *ioat_chan = to_ioat_chan(c); 152 153 if (sscanf(page, "%du", &intr_coalesce) != -1) { 154 if ((intr_coalesce < 0) || 155 (intr_coalesce > IOAT_INTRDELAY_MASK)) 156 return -EINVAL; 157 ioat_chan->intr_coalesce = intr_coalesce; 158 } 159 160 return count; 161 } 162 163 static struct ioat_sysfs_entry intr_coalesce_attr = __ATTR_RW(intr_coalesce); 164 165 static struct attribute *ioat_attrs[] = { 166 &ring_size_attr.attr, 167 &ring_active_attr.attr, 168 &ioat_cap_attr.attr, 169 &ioat_version_attr.attr, 170 &intr_coalesce_attr.attr, 171 NULL, 172 }; 173 174 struct kobj_type ioat_ktype = { 175 .sysfs_ops = &ioat_sysfs_ops, 176 .default_attrs = ioat_attrs, 177 }; 178