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