]>
Commit | Line | Data |
---|---|---|
80b19736 DJ |
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 | ||
268e2519 US |
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 | ||
80b19736 DJ |
82 | const struct sysfs_ops ioat_sysfs_ops = { |
83 | .show = ioat_attr_show, | |
268e2519 | 84 | .store = ioat_attr_store, |
80b19736 DJ |
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 | ||
268e2519 US |
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 | ||
80b19736 DJ |
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, | |
268e2519 | 170 | &intr_coalesce_attr.attr, |
80b19736 DJ |
171 | NULL, |
172 | }; | |
173 | ||
174 | struct kobj_type ioat_ktype = { | |
175 | .sysfs_ops = &ioat_sysfs_ops, | |
176 | .default_attrs = ioat_attrs, | |
177 | }; |