Commit | Line | Data |
---|---|---|
7f7f5316 AF |
1 | /* |
2 | * drivers/net/gianfar_sysfs.c | |
3 | * | |
4 | * Gianfar Ethernet Driver | |
5 | * This driver is designed for the non-CPM ethernet controllers | |
6 | * on the 85xx and 83xx family of integrated processors | |
7 | * Based on 8260_io/fcc_enet.c | |
8 | * | |
9 | * Author: Andy Fleming | |
b56d55b6 | 10 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) |
a12f801d | 11 | * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com> |
7f7f5316 | 12 | * |
a12f801d | 13 | * Copyright 2002-2009 Freescale Semiconductor, Inc. |
7f7f5316 AF |
14 | * |
15 | * This program is free software; you can redistribute it and/or modify it | |
16 | * under the terms of the GNU General Public License as published by the | |
17 | * Free Software Foundation; either version 2 of the License, or (at your | |
18 | * option) any later version. | |
19 | * | |
20 | * Sysfs file creation and management | |
21 | */ | |
22 | ||
7f7f5316 | 23 | #include <linux/kernel.h> |
7f7f5316 AF |
24 | #include <linux/string.h> |
25 | #include <linux/errno.h> | |
26 | #include <linux/unistd.h> | |
27 | #include <linux/slab.h> | |
28 | #include <linux/init.h> | |
29 | #include <linux/delay.h> | |
30 | #include <linux/etherdevice.h> | |
31 | #include <linux/spinlock.h> | |
32 | #include <linux/mm.h> | |
33 | #include <linux/device.h> | |
34 | ||
35 | #include <asm/uaccess.h> | |
36 | #include <linux/module.h> | |
7f7f5316 AF |
37 | |
38 | #include "gianfar.h" | |
39 | ||
4409d281 KG |
40 | static ssize_t gfar_show_bd_stash(struct device *dev, |
41 | struct device_attribute *attr, char *buf) | |
7f7f5316 | 42 | { |
4409d281 | 43 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
7f7f5316 | 44 | |
4409d281 | 45 | return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off"); |
7f7f5316 AF |
46 | } |
47 | ||
4409d281 KG |
48 | static ssize_t gfar_set_bd_stash(struct device *dev, |
49 | struct device_attribute *attr, | |
50 | const char *buf, size_t count) | |
7f7f5316 | 51 | { |
4409d281 | 52 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
46ceb60c | 53 | struct gfar __iomem *regs = priv->gfargrp[0].regs; |
7f7f5316 AF |
54 | int new_setting = 0; |
55 | u32 temp; | |
56 | unsigned long flags; | |
57 | ||
4d7902f2 AF |
58 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING)) |
59 | return count; | |
60 | ||
a12f801d | 61 | |
7f7f5316 | 62 | /* Find out the new setting */ |
4409d281 | 63 | if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1)) |
7f7f5316 | 64 | new_setting = 1; |
8e95a202 JP |
65 | else if (!strncmp("off", buf, count - 1) || |
66 | !strncmp("0", buf, count - 1)) | |
7f7f5316 AF |
67 | new_setting = 0; |
68 | else | |
69 | return count; | |
70 | ||
fba4ed03 SG |
71 | |
72 | local_irq_save(flags); | |
73 | lock_rx_qs(priv); | |
7f7f5316 AF |
74 | |
75 | /* Set the new stashing value */ | |
76 | priv->bd_stash_en = new_setting; | |
77 | ||
f4983704 | 78 | temp = gfar_read(®s->attr); |
6aa20a22 | 79 | |
7f7f5316 AF |
80 | if (new_setting) |
81 | temp |= ATTR_BDSTASH; | |
82 | else | |
83 | temp &= ~(ATTR_BDSTASH); | |
84 | ||
f4983704 | 85 | gfar_write(®s->attr, temp); |
7f7f5316 | 86 | |
fba4ed03 SG |
87 | unlock_rx_qs(priv); |
88 | local_irq_restore(flags); | |
7f7f5316 AF |
89 | |
90 | return count; | |
91 | } | |
92 | ||
b2f66d18 | 93 | static DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash); |
35a84fdc | 94 | |
4409d281 KG |
95 | static ssize_t gfar_show_rx_stash_size(struct device *dev, |
96 | struct device_attribute *attr, char *buf) | |
7f7f5316 | 97 | { |
4409d281 | 98 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
7f7f5316 AF |
99 | |
100 | return sprintf(buf, "%d\n", priv->rx_stash_size); | |
101 | } | |
102 | ||
4409d281 KG |
103 | static ssize_t gfar_set_rx_stash_size(struct device *dev, |
104 | struct device_attribute *attr, | |
105 | const char *buf, size_t count) | |
7f7f5316 | 106 | { |
4409d281 | 107 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
46ceb60c | 108 | struct gfar __iomem *regs = priv->gfargrp[0].regs; |
7f7f5316 AF |
109 | unsigned int length = simple_strtoul(buf, NULL, 0); |
110 | u32 temp; | |
111 | unsigned long flags; | |
112 | ||
4d7902f2 AF |
113 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) |
114 | return count; | |
115 | ||
fba4ed03 SG |
116 | local_irq_save(flags); |
117 | lock_rx_qs(priv); | |
a12f801d | 118 | |
7f7f5316 | 119 | if (length > priv->rx_buffer_size) |
f162b9d5 | 120 | goto out; |
7f7f5316 AF |
121 | |
122 | if (length == priv->rx_stash_size) | |
f162b9d5 | 123 | goto out; |
7f7f5316 AF |
124 | |
125 | priv->rx_stash_size = length; | |
126 | ||
f4983704 | 127 | temp = gfar_read(®s->attreli); |
7f7f5316 AF |
128 | temp &= ~ATTRELI_EL_MASK; |
129 | temp |= ATTRELI_EL(length); | |
f4983704 | 130 | gfar_write(®s->attreli, temp); |
7f7f5316 AF |
131 | |
132 | /* Turn stashing on/off as appropriate */ | |
f4983704 | 133 | temp = gfar_read(®s->attr); |
7f7f5316 AF |
134 | |
135 | if (length) | |
136 | temp |= ATTR_BUFSTASH; | |
137 | else | |
138 | temp &= ~(ATTR_BUFSTASH); | |
139 | ||
f4983704 | 140 | gfar_write(®s->attr, temp); |
7f7f5316 | 141 | |
f162b9d5 | 142 | out: |
fba4ed03 SG |
143 | unlock_rx_qs(priv); |
144 | local_irq_restore(flags); | |
7f7f5316 AF |
145 | |
146 | return count; | |
147 | } | |
148 | ||
b2f66d18 AV |
149 | static DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size, |
150 | gfar_set_rx_stash_size); | |
35a84fdc | 151 | |
7f7f5316 | 152 | /* Stashing will only be enabled when rx_stash_size != 0 */ |
4409d281 KG |
153 | static ssize_t gfar_show_rx_stash_index(struct device *dev, |
154 | struct device_attribute *attr, | |
155 | char *buf) | |
7f7f5316 | 156 | { |
4409d281 | 157 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
7f7f5316 AF |
158 | |
159 | return sprintf(buf, "%d\n", priv->rx_stash_index); | |
160 | } | |
161 | ||
4409d281 KG |
162 | static ssize_t gfar_set_rx_stash_index(struct device *dev, |
163 | struct device_attribute *attr, | |
164 | const char *buf, size_t count) | |
7f7f5316 | 165 | { |
4409d281 | 166 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
46ceb60c | 167 | struct gfar __iomem *regs = priv->gfargrp[0].regs; |
7f7f5316 AF |
168 | unsigned short index = simple_strtoul(buf, NULL, 0); |
169 | u32 temp; | |
170 | unsigned long flags; | |
171 | ||
4d7902f2 AF |
172 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) |
173 | return count; | |
174 | ||
fba4ed03 SG |
175 | local_irq_save(flags); |
176 | lock_rx_qs(priv); | |
a12f801d | 177 | |
7f7f5316 | 178 | if (index > priv->rx_stash_size) |
f162b9d5 | 179 | goto out; |
7f7f5316 AF |
180 | |
181 | if (index == priv->rx_stash_index) | |
f162b9d5 | 182 | goto out; |
7f7f5316 AF |
183 | |
184 | priv->rx_stash_index = index; | |
185 | ||
f4983704 | 186 | temp = gfar_read(®s->attreli); |
7f7f5316 AF |
187 | temp &= ~ATTRELI_EI_MASK; |
188 | temp |= ATTRELI_EI(index); | |
499428ed | 189 | gfar_write(®s->attreli, temp); |
7f7f5316 | 190 | |
f162b9d5 | 191 | out: |
fba4ed03 SG |
192 | unlock_rx_qs(priv); |
193 | local_irq_restore(flags); | |
7f7f5316 AF |
194 | |
195 | return count; | |
196 | } | |
197 | ||
b2f66d18 AV |
198 | static DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index, |
199 | gfar_set_rx_stash_index); | |
35a84fdc | 200 | |
4409d281 KG |
201 | static ssize_t gfar_show_fifo_threshold(struct device *dev, |
202 | struct device_attribute *attr, | |
203 | char *buf) | |
7f7f5316 | 204 | { |
4409d281 | 205 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
7f7f5316 AF |
206 | |
207 | return sprintf(buf, "%d\n", priv->fifo_threshold); | |
208 | } | |
209 | ||
4409d281 KG |
210 | static ssize_t gfar_set_fifo_threshold(struct device *dev, |
211 | struct device_attribute *attr, | |
212 | const char *buf, size_t count) | |
7f7f5316 | 213 | { |
4409d281 | 214 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
46ceb60c | 215 | struct gfar __iomem *regs = priv->gfargrp[0].regs; |
7f7f5316 AF |
216 | unsigned int length = simple_strtoul(buf, NULL, 0); |
217 | u32 temp; | |
218 | unsigned long flags; | |
219 | ||
220 | if (length > GFAR_MAX_FIFO_THRESHOLD) | |
221 | return count; | |
222 | ||
fba4ed03 SG |
223 | local_irq_save(flags); |
224 | lock_tx_qs(priv); | |
7f7f5316 AF |
225 | |
226 | priv->fifo_threshold = length; | |
227 | ||
f4983704 | 228 | temp = gfar_read(®s->fifo_tx_thr); |
7f7f5316 AF |
229 | temp &= ~FIFO_TX_THR_MASK; |
230 | temp |= length; | |
f4983704 | 231 | gfar_write(®s->fifo_tx_thr, temp); |
7f7f5316 | 232 | |
fba4ed03 SG |
233 | unlock_tx_qs(priv); |
234 | local_irq_restore(flags); | |
7f7f5316 AF |
235 | |
236 | return count; | |
237 | } | |
238 | ||
b2f66d18 AV |
239 | static DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold, |
240 | gfar_set_fifo_threshold); | |
35a84fdc | 241 | |
4409d281 KG |
242 | static ssize_t gfar_show_fifo_starve(struct device *dev, |
243 | struct device_attribute *attr, char *buf) | |
7f7f5316 | 244 | { |
4409d281 | 245 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
7f7f5316 AF |
246 | |
247 | return sprintf(buf, "%d\n", priv->fifo_starve); | |
248 | } | |
249 | ||
4409d281 KG |
250 | static ssize_t gfar_set_fifo_starve(struct device *dev, |
251 | struct device_attribute *attr, | |
252 | const char *buf, size_t count) | |
7f7f5316 | 253 | { |
4409d281 | 254 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
46ceb60c | 255 | struct gfar __iomem *regs = priv->gfargrp[0].regs; |
7f7f5316 AF |
256 | unsigned int num = simple_strtoul(buf, NULL, 0); |
257 | u32 temp; | |
258 | unsigned long flags; | |
259 | ||
260 | if (num > GFAR_MAX_FIFO_STARVE) | |
261 | return count; | |
262 | ||
fba4ed03 SG |
263 | local_irq_save(flags); |
264 | lock_tx_qs(priv); | |
7f7f5316 AF |
265 | |
266 | priv->fifo_starve = num; | |
267 | ||
f4983704 | 268 | temp = gfar_read(®s->fifo_tx_starve); |
7f7f5316 AF |
269 | temp &= ~FIFO_TX_STARVE_MASK; |
270 | temp |= num; | |
f4983704 | 271 | gfar_write(®s->fifo_tx_starve, temp); |
7f7f5316 | 272 | |
fba4ed03 SG |
273 | unlock_tx_qs(priv); |
274 | local_irq_restore(flags); | |
7f7f5316 AF |
275 | |
276 | return count; | |
277 | } | |
278 | ||
b2f66d18 AV |
279 | static DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve, |
280 | gfar_set_fifo_starve); | |
35a84fdc | 281 | |
4409d281 KG |
282 | static ssize_t gfar_show_fifo_starve_off(struct device *dev, |
283 | struct device_attribute *attr, | |
284 | char *buf) | |
7f7f5316 | 285 | { |
4409d281 | 286 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
7f7f5316 AF |
287 | |
288 | return sprintf(buf, "%d\n", priv->fifo_starve_off); | |
289 | } | |
290 | ||
4409d281 KG |
291 | static ssize_t gfar_set_fifo_starve_off(struct device *dev, |
292 | struct device_attribute *attr, | |
293 | const char *buf, size_t count) | |
7f7f5316 | 294 | { |
4409d281 | 295 | struct gfar_private *priv = netdev_priv(to_net_dev(dev)); |
46ceb60c | 296 | struct gfar __iomem *regs = priv->gfargrp[0].regs; |
7f7f5316 AF |
297 | unsigned int num = simple_strtoul(buf, NULL, 0); |
298 | u32 temp; | |
299 | unsigned long flags; | |
300 | ||
301 | if (num > GFAR_MAX_FIFO_STARVE_OFF) | |
302 | return count; | |
303 | ||
fba4ed03 SG |
304 | local_irq_save(flags); |
305 | lock_tx_qs(priv); | |
7f7f5316 AF |
306 | |
307 | priv->fifo_starve_off = num; | |
308 | ||
f4983704 | 309 | temp = gfar_read(®s->fifo_tx_starve_shutoff); |
7f7f5316 AF |
310 | temp &= ~FIFO_TX_STARVE_OFF_MASK; |
311 | temp |= num; | |
f4983704 | 312 | gfar_write(®s->fifo_tx_starve_shutoff, temp); |
7f7f5316 | 313 | |
fba4ed03 SG |
314 | unlock_tx_qs(priv); |
315 | local_irq_restore(flags); | |
7f7f5316 AF |
316 | |
317 | return count; | |
318 | } | |
319 | ||
b2f66d18 AV |
320 | static DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off, |
321 | gfar_set_fifo_starve_off); | |
35a84fdc | 322 | |
7f7f5316 AF |
323 | void gfar_init_sysfs(struct net_device *dev) |
324 | { | |
325 | struct gfar_private *priv = netdev_priv(dev); | |
35a84fdc | 326 | int rc; |
7f7f5316 AF |
327 | |
328 | /* Initialize the default values */ | |
7f7f5316 AF |
329 | priv->fifo_threshold = DEFAULT_FIFO_TX_THR; |
330 | priv->fifo_starve = DEFAULT_FIFO_TX_STARVE; | |
331 | priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF; | |
7f7f5316 AF |
332 | |
333 | /* Create our sysfs files */ | |
35a84fdc GL |
334 | rc = device_create_file(&dev->dev, &dev_attr_bd_stash); |
335 | rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_size); | |
336 | rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_index); | |
337 | rc |= device_create_file(&dev->dev, &dev_attr_fifo_threshold); | |
338 | rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve); | |
339 | rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve_off); | |
340 | if (rc) | |
341 | dev_err(&dev->dev, "Error creating gianfar sysfs files.\n"); | |
7f7f5316 | 342 | } |