diff options
Diffstat (limited to 'drivers/net/gianfar_sysfs.c')
-rw-r--r-- | drivers/net/gianfar_sysfs.c | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c new file mode 100644 index 000000000000..10d34cb19192 --- /dev/null +++ b/drivers/net/gianfar_sysfs.c | |||
@@ -0,0 +1,311 @@ | |||
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 | ||
10 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | ||
11 | * | ||
12 | * Copyright (c) 2002-2005 Freescale Semiconductor, Inc. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License as published by the | ||
16 | * Free Software Foundation; either version 2 of the License, or (at your | ||
17 | * option) any later version. | ||
18 | * | ||
19 | * Sysfs file creation and management | ||
20 | */ | ||
21 | |||
22 | #include <linux/config.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/unistd.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/etherdevice.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | #include <linux/mm.h> | ||
34 | #include <linux/device.h> | ||
35 | |||
36 | #include <asm/uaccess.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/version.h> | ||
39 | |||
40 | #include "gianfar.h" | ||
41 | |||
42 | #define GFAR_ATTR(_name) \ | ||
43 | static ssize_t gfar_show_##_name(struct class_device *cdev, char *buf); \ | ||
44 | static ssize_t gfar_set_##_name(struct class_device *cdev, \ | ||
45 | const char *buf, size_t count); \ | ||
46 | static CLASS_DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name) | ||
47 | |||
48 | #define GFAR_CREATE_FILE(_dev, _name) \ | ||
49 | class_device_create_file(&_dev->class_dev, &class_device_attr_##_name) | ||
50 | |||
51 | GFAR_ATTR(bd_stash); | ||
52 | GFAR_ATTR(rx_stash_size); | ||
53 | GFAR_ATTR(rx_stash_index); | ||
54 | GFAR_ATTR(fifo_threshold); | ||
55 | GFAR_ATTR(fifo_starve); | ||
56 | GFAR_ATTR(fifo_starve_off); | ||
57 | |||
58 | #define to_net_dev(cd) container_of(cd, struct net_device, class_dev) | ||
59 | |||
60 | static ssize_t gfar_show_bd_stash(struct class_device *cdev, char *buf) | ||
61 | { | ||
62 | struct net_device *dev = to_net_dev(cdev); | ||
63 | struct gfar_private *priv = netdev_priv(dev); | ||
64 | |||
65 | return sprintf(buf, "%s\n", priv->bd_stash_en? "on" : "off"); | ||
66 | } | ||
67 | |||
68 | static ssize_t gfar_set_bd_stash(struct class_device *cdev, | ||
69 | const char *buf, size_t count) | ||
70 | { | ||
71 | struct net_device *dev = to_net_dev(cdev); | ||
72 | struct gfar_private *priv = netdev_priv(dev); | ||
73 | int new_setting = 0; | ||
74 | u32 temp; | ||
75 | unsigned long flags; | ||
76 | |||
77 | /* Find out the new setting */ | ||
78 | if (!strncmp("on", buf, count-1) || !strncmp("1", buf, count-1)) | ||
79 | new_setting = 1; | ||
80 | else if (!strncmp("off", buf, count-1) || !strncmp("0", buf, count-1)) | ||
81 | new_setting = 0; | ||
82 | else | ||
83 | return count; | ||
84 | |||
85 | spin_lock_irqsave(&priv->lock, flags); | ||
86 | |||
87 | /* Set the new stashing value */ | ||
88 | priv->bd_stash_en = new_setting; | ||
89 | |||
90 | temp = gfar_read(&priv->regs->attr); | ||
91 | |||
92 | if (new_setting) | ||
93 | temp |= ATTR_BDSTASH; | ||
94 | else | ||
95 | temp &= ~(ATTR_BDSTASH); | ||
96 | |||
97 | gfar_write(&priv->regs->attr, temp); | ||
98 | |||
99 | spin_unlock_irqrestore(&priv->lock, flags); | ||
100 | |||
101 | return count; | ||
102 | } | ||
103 | |||
104 | static ssize_t gfar_show_rx_stash_size(struct class_device *cdev, char *buf) | ||
105 | { | ||
106 | struct net_device *dev = to_net_dev(cdev); | ||
107 | struct gfar_private *priv = netdev_priv(dev); | ||
108 | |||
109 | return sprintf(buf, "%d\n", priv->rx_stash_size); | ||
110 | } | ||
111 | |||
112 | static ssize_t gfar_set_rx_stash_size(struct class_device *cdev, | ||
113 | const char *buf, size_t count) | ||
114 | { | ||
115 | struct net_device *dev = to_net_dev(cdev); | ||
116 | struct gfar_private *priv = netdev_priv(dev); | ||
117 | unsigned int length = simple_strtoul(buf, NULL, 0); | ||
118 | u32 temp; | ||
119 | unsigned long flags; | ||
120 | |||
121 | spin_lock_irqsave(&priv->lock, flags); | ||
122 | if (length > priv->rx_buffer_size) | ||
123 | return count; | ||
124 | |||
125 | if (length == priv->rx_stash_size) | ||
126 | return count; | ||
127 | |||
128 | priv->rx_stash_size = length; | ||
129 | |||
130 | temp = gfar_read(&priv->regs->attreli); | ||
131 | temp &= ~ATTRELI_EL_MASK; | ||
132 | temp |= ATTRELI_EL(length); | ||
133 | gfar_write(&priv->regs->attreli, temp); | ||
134 | |||
135 | /* Turn stashing on/off as appropriate */ | ||
136 | temp = gfar_read(&priv->regs->attr); | ||
137 | |||
138 | if (length) | ||
139 | temp |= ATTR_BUFSTASH; | ||
140 | else | ||
141 | temp &= ~(ATTR_BUFSTASH); | ||
142 | |||
143 | gfar_write(&priv->regs->attr, temp); | ||
144 | |||
145 | spin_unlock_irqrestore(&priv->lock, flags); | ||
146 | |||
147 | return count; | ||
148 | } | ||
149 | |||
150 | |||
151 | /* Stashing will only be enabled when rx_stash_size != 0 */ | ||
152 | static ssize_t gfar_show_rx_stash_index(struct class_device *cdev, char *buf) | ||
153 | { | ||
154 | struct net_device *dev = to_net_dev(cdev); | ||
155 | struct gfar_private *priv = netdev_priv(dev); | ||
156 | |||
157 | return sprintf(buf, "%d\n", priv->rx_stash_index); | ||
158 | } | ||
159 | |||
160 | static ssize_t gfar_set_rx_stash_index(struct class_device *cdev, | ||
161 | const char *buf, size_t count) | ||
162 | { | ||
163 | struct net_device *dev = to_net_dev(cdev); | ||
164 | struct gfar_private *priv = netdev_priv(dev); | ||
165 | unsigned short index = simple_strtoul(buf, NULL, 0); | ||
166 | u32 temp; | ||
167 | unsigned long flags; | ||
168 | |||
169 | spin_lock_irqsave(&priv->lock, flags); | ||
170 | if (index > priv->rx_stash_size) | ||
171 | return count; | ||
172 | |||
173 | if (index == priv->rx_stash_index) | ||
174 | return count; | ||
175 | |||
176 | priv->rx_stash_index = index; | ||
177 | |||
178 | temp = gfar_read(&priv->regs->attreli); | ||
179 | temp &= ~ATTRELI_EI_MASK; | ||
180 | temp |= ATTRELI_EI(index); | ||
181 | gfar_write(&priv->regs->attreli, flags); | ||
182 | |||
183 | spin_unlock_irqrestore(&priv->lock, flags); | ||
184 | |||
185 | return count; | ||
186 | } | ||
187 | |||
188 | static ssize_t gfar_show_fifo_threshold(struct class_device *cdev, char *buf) | ||
189 | { | ||
190 | struct net_device *dev = to_net_dev(cdev); | ||
191 | struct gfar_private *priv = netdev_priv(dev); | ||
192 | |||
193 | return sprintf(buf, "%d\n", priv->fifo_threshold); | ||
194 | } | ||
195 | |||
196 | static ssize_t gfar_set_fifo_threshold(struct class_device *cdev, | ||
197 | const char *buf, size_t count) | ||
198 | { | ||
199 | struct net_device *dev = to_net_dev(cdev); | ||
200 | struct gfar_private *priv = netdev_priv(dev); | ||
201 | unsigned int length = simple_strtoul(buf, NULL, 0); | ||
202 | u32 temp; | ||
203 | unsigned long flags; | ||
204 | |||
205 | if (length > GFAR_MAX_FIFO_THRESHOLD) | ||
206 | return count; | ||
207 | |||
208 | spin_lock_irqsave(&priv->lock, flags); | ||
209 | |||
210 | priv->fifo_threshold = length; | ||
211 | |||
212 | temp = gfar_read(&priv->regs->fifo_tx_thr); | ||
213 | temp &= ~FIFO_TX_THR_MASK; | ||
214 | temp |= length; | ||
215 | gfar_write(&priv->regs->fifo_tx_thr, temp); | ||
216 | |||
217 | spin_unlock_irqrestore(&priv->lock, flags); | ||
218 | |||
219 | return count; | ||
220 | } | ||
221 | |||
222 | static ssize_t gfar_show_fifo_starve(struct class_device *cdev, char *buf) | ||
223 | { | ||
224 | struct net_device *dev = to_net_dev(cdev); | ||
225 | struct gfar_private *priv = netdev_priv(dev); | ||
226 | |||
227 | return sprintf(buf, "%d\n", priv->fifo_starve); | ||
228 | } | ||
229 | |||
230 | |||
231 | static ssize_t gfar_set_fifo_starve(struct class_device *cdev, | ||
232 | const char *buf, size_t count) | ||
233 | { | ||
234 | struct net_device *dev = to_net_dev(cdev); | ||
235 | struct gfar_private *priv = netdev_priv(dev); | ||
236 | unsigned int num = simple_strtoul(buf, NULL, 0); | ||
237 | u32 temp; | ||
238 | unsigned long flags; | ||
239 | |||
240 | if (num > GFAR_MAX_FIFO_STARVE) | ||
241 | return count; | ||
242 | |||
243 | spin_lock_irqsave(&priv->lock, flags); | ||
244 | |||
245 | priv->fifo_starve = num; | ||
246 | |||
247 | temp = gfar_read(&priv->regs->fifo_tx_starve); | ||
248 | temp &= ~FIFO_TX_STARVE_MASK; | ||
249 | temp |= num; | ||
250 | gfar_write(&priv->regs->fifo_tx_starve, temp); | ||
251 | |||
252 | spin_unlock_irqrestore(&priv->lock, flags); | ||
253 | |||
254 | return count; | ||
255 | } | ||
256 | |||
257 | static ssize_t gfar_show_fifo_starve_off(struct class_device *cdev, char *buf) | ||
258 | { | ||
259 | struct net_device *dev = to_net_dev(cdev); | ||
260 | struct gfar_private *priv = netdev_priv(dev); | ||
261 | |||
262 | return sprintf(buf, "%d\n", priv->fifo_starve_off); | ||
263 | } | ||
264 | |||
265 | static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev, | ||
266 | const char *buf, size_t count) | ||
267 | { | ||
268 | struct net_device *dev = to_net_dev(cdev); | ||
269 | struct gfar_private *priv = netdev_priv(dev); | ||
270 | unsigned int num = simple_strtoul(buf, NULL, 0); | ||
271 | u32 temp; | ||
272 | unsigned long flags; | ||
273 | |||
274 | if (num > GFAR_MAX_FIFO_STARVE_OFF) | ||
275 | return count; | ||
276 | |||
277 | spin_lock_irqsave(&priv->lock, flags); | ||
278 | |||
279 | priv->fifo_starve_off = num; | ||
280 | |||
281 | temp = gfar_read(&priv->regs->fifo_tx_starve_shutoff); | ||
282 | temp &= ~FIFO_TX_STARVE_OFF_MASK; | ||
283 | temp |= num; | ||
284 | gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); | ||
285 | |||
286 | spin_unlock_irqrestore(&priv->lock, flags); | ||
287 | |||
288 | return count; | ||
289 | } | ||
290 | |||
291 | void gfar_init_sysfs(struct net_device *dev) | ||
292 | { | ||
293 | struct gfar_private *priv = netdev_priv(dev); | ||
294 | |||
295 | /* Initialize the default values */ | ||
296 | priv->rx_stash_size = DEFAULT_STASH_LENGTH; | ||
297 | priv->rx_stash_index = DEFAULT_STASH_INDEX; | ||
298 | priv->fifo_threshold = DEFAULT_FIFO_TX_THR; | ||
299 | priv->fifo_starve = DEFAULT_FIFO_TX_STARVE; | ||
300 | priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF; | ||
301 | priv->bd_stash_en = DEFAULT_BD_STASH; | ||
302 | |||
303 | /* Create our sysfs files */ | ||
304 | GFAR_CREATE_FILE(dev, bd_stash); | ||
305 | GFAR_CREATE_FILE(dev, rx_stash_size); | ||
306 | GFAR_CREATE_FILE(dev, rx_stash_index); | ||
307 | GFAR_CREATE_FILE(dev, fifo_threshold); | ||
308 | GFAR_CREATE_FILE(dev, fifo_starve); | ||
309 | GFAR_CREATE_FILE(dev, fifo_starve_off); | ||
310 | |||
311 | } | ||