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) |
7f7f5316 AF |
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 | ||
7f7f5316 AF |
22 | #include <linux/kernel.h> |
23 | #include <linux/sched.h> | |
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> | |
37 | #include <linux/version.h> | |
38 | ||
39 | #include "gianfar.h" | |
40 | ||
41 | #define GFAR_ATTR(_name) \ | |
42 | static ssize_t gfar_show_##_name(struct class_device *cdev, char *buf); \ | |
43 | static ssize_t gfar_set_##_name(struct class_device *cdev, \ | |
44 | const char *buf, size_t count); \ | |
45 | static CLASS_DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name) | |
46 | ||
47 | #define GFAR_CREATE_FILE(_dev, _name) \ | |
48 | class_device_create_file(&_dev->class_dev, &class_device_attr_##_name) | |
49 | ||
50 | GFAR_ATTR(bd_stash); | |
51 | GFAR_ATTR(rx_stash_size); | |
52 | GFAR_ATTR(rx_stash_index); | |
53 | GFAR_ATTR(fifo_threshold); | |
54 | GFAR_ATTR(fifo_starve); | |
55 | GFAR_ATTR(fifo_starve_off); | |
56 | ||
57 | #define to_net_dev(cd) container_of(cd, struct net_device, class_dev) | |
58 | ||
59 | static ssize_t gfar_show_bd_stash(struct class_device *cdev, char *buf) | |
60 | { | |
61 | struct net_device *dev = to_net_dev(cdev); | |
62 | struct gfar_private *priv = netdev_priv(dev); | |
63 | ||
64 | return sprintf(buf, "%s\n", priv->bd_stash_en? "on" : "off"); | |
65 | } | |
66 | ||
67 | static ssize_t gfar_set_bd_stash(struct class_device *cdev, | |
68 | const char *buf, size_t count) | |
69 | { | |
70 | struct net_device *dev = to_net_dev(cdev); | |
71 | struct gfar_private *priv = netdev_priv(dev); | |
72 | int new_setting = 0; | |
73 | u32 temp; | |
74 | unsigned long flags; | |
75 | ||
76 | /* Find out the new setting */ | |
77 | if (!strncmp("on", buf, count-1) || !strncmp("1", buf, count-1)) | |
78 | new_setting = 1; | |
79 | else if (!strncmp("off", buf, count-1) || !strncmp("0", buf, count-1)) | |
80 | new_setting = 0; | |
81 | else | |
82 | return count; | |
83 | ||
fef6108d | 84 | spin_lock_irqsave(&priv->rxlock, flags); |
7f7f5316 AF |
85 | |
86 | /* Set the new stashing value */ | |
87 | priv->bd_stash_en = new_setting; | |
88 | ||
89 | temp = gfar_read(&priv->regs->attr); | |
6aa20a22 | 90 | |
7f7f5316 AF |
91 | if (new_setting) |
92 | temp |= ATTR_BDSTASH; | |
93 | else | |
94 | temp &= ~(ATTR_BDSTASH); | |
95 | ||
96 | gfar_write(&priv->regs->attr, temp); | |
97 | ||
fef6108d | 98 | spin_unlock_irqrestore(&priv->rxlock, flags); |
7f7f5316 AF |
99 | |
100 | return count; | |
101 | } | |
102 | ||
103 | static ssize_t gfar_show_rx_stash_size(struct class_device *cdev, char *buf) | |
104 | { | |
105 | struct net_device *dev = to_net_dev(cdev); | |
106 | struct gfar_private *priv = netdev_priv(dev); | |
107 | ||
108 | return sprintf(buf, "%d\n", priv->rx_stash_size); | |
109 | } | |
110 | ||
111 | static ssize_t gfar_set_rx_stash_size(struct class_device *cdev, | |
112 | const char *buf, size_t count) | |
113 | { | |
114 | struct net_device *dev = to_net_dev(cdev); | |
115 | struct gfar_private *priv = netdev_priv(dev); | |
116 | unsigned int length = simple_strtoul(buf, NULL, 0); | |
117 | u32 temp; | |
118 | unsigned long flags; | |
119 | ||
fef6108d | 120 | spin_lock_irqsave(&priv->rxlock, flags); |
7f7f5316 AF |
121 | if (length > priv->rx_buffer_size) |
122 | return count; | |
123 | ||
124 | if (length == priv->rx_stash_size) | |
125 | return count; | |
126 | ||
127 | priv->rx_stash_size = length; | |
128 | ||
129 | temp = gfar_read(&priv->regs->attreli); | |
130 | temp &= ~ATTRELI_EL_MASK; | |
131 | temp |= ATTRELI_EL(length); | |
132 | gfar_write(&priv->regs->attreli, temp); | |
133 | ||
134 | /* Turn stashing on/off as appropriate */ | |
135 | temp = gfar_read(&priv->regs->attr); | |
136 | ||
137 | if (length) | |
138 | temp |= ATTR_BUFSTASH; | |
139 | else | |
140 | temp &= ~(ATTR_BUFSTASH); | |
141 | ||
142 | gfar_write(&priv->regs->attr, temp); | |
143 | ||
fef6108d | 144 | spin_unlock_irqrestore(&priv->rxlock, flags); |
7f7f5316 AF |
145 | |
146 | return count; | |
147 | } | |
148 | ||
149 | ||
150 | /* Stashing will only be enabled when rx_stash_size != 0 */ | |
151 | static ssize_t gfar_show_rx_stash_index(struct class_device *cdev, char *buf) | |
152 | { | |
153 | struct net_device *dev = to_net_dev(cdev); | |
154 | struct gfar_private *priv = netdev_priv(dev); | |
155 | ||
156 | return sprintf(buf, "%d\n", priv->rx_stash_index); | |
157 | } | |
158 | ||
159 | static ssize_t gfar_set_rx_stash_index(struct class_device *cdev, | |
160 | const char *buf, size_t count) | |
161 | { | |
162 | struct net_device *dev = to_net_dev(cdev); | |
163 | struct gfar_private *priv = netdev_priv(dev); | |
164 | unsigned short index = simple_strtoul(buf, NULL, 0); | |
165 | u32 temp; | |
166 | unsigned long flags; | |
167 | ||
fef6108d | 168 | spin_lock_irqsave(&priv->rxlock, flags); |
7f7f5316 AF |
169 | if (index > priv->rx_stash_size) |
170 | return count; | |
171 | ||
172 | if (index == priv->rx_stash_index) | |
173 | return count; | |
174 | ||
175 | priv->rx_stash_index = index; | |
176 | ||
177 | temp = gfar_read(&priv->regs->attreli); | |
178 | temp &= ~ATTRELI_EI_MASK; | |
179 | temp |= ATTRELI_EI(index); | |
180 | gfar_write(&priv->regs->attreli, flags); | |
181 | ||
fef6108d | 182 | spin_unlock_irqrestore(&priv->rxlock, flags); |
7f7f5316 AF |
183 | |
184 | return count; | |
185 | } | |
186 | ||
187 | static ssize_t gfar_show_fifo_threshold(struct class_device *cdev, char *buf) | |
188 | { | |
189 | struct net_device *dev = to_net_dev(cdev); | |
190 | struct gfar_private *priv = netdev_priv(dev); | |
191 | ||
192 | return sprintf(buf, "%d\n", priv->fifo_threshold); | |
193 | } | |
194 | ||
195 | static ssize_t gfar_set_fifo_threshold(struct class_device *cdev, | |
196 | const char *buf, size_t count) | |
197 | { | |
198 | struct net_device *dev = to_net_dev(cdev); | |
199 | struct gfar_private *priv = netdev_priv(dev); | |
200 | unsigned int length = simple_strtoul(buf, NULL, 0); | |
201 | u32 temp; | |
202 | unsigned long flags; | |
203 | ||
204 | if (length > GFAR_MAX_FIFO_THRESHOLD) | |
205 | return count; | |
206 | ||
fef6108d | 207 | spin_lock_irqsave(&priv->txlock, flags); |
7f7f5316 AF |
208 | |
209 | priv->fifo_threshold = length; | |
210 | ||
211 | temp = gfar_read(&priv->regs->fifo_tx_thr); | |
212 | temp &= ~FIFO_TX_THR_MASK; | |
213 | temp |= length; | |
214 | gfar_write(&priv->regs->fifo_tx_thr, temp); | |
215 | ||
fef6108d | 216 | spin_unlock_irqrestore(&priv->txlock, flags); |
7f7f5316 AF |
217 | |
218 | return count; | |
219 | } | |
220 | ||
221 | static ssize_t gfar_show_fifo_starve(struct class_device *cdev, char *buf) | |
222 | { | |
223 | struct net_device *dev = to_net_dev(cdev); | |
224 | struct gfar_private *priv = netdev_priv(dev); | |
225 | ||
226 | return sprintf(buf, "%d\n", priv->fifo_starve); | |
227 | } | |
228 | ||
229 | ||
230 | static ssize_t gfar_set_fifo_starve(struct class_device *cdev, | |
231 | const char *buf, size_t count) | |
232 | { | |
233 | struct net_device *dev = to_net_dev(cdev); | |
234 | struct gfar_private *priv = netdev_priv(dev); | |
235 | unsigned int num = simple_strtoul(buf, NULL, 0); | |
236 | u32 temp; | |
237 | unsigned long flags; | |
238 | ||
239 | if (num > GFAR_MAX_FIFO_STARVE) | |
240 | return count; | |
241 | ||
fef6108d | 242 | spin_lock_irqsave(&priv->txlock, flags); |
7f7f5316 AF |
243 | |
244 | priv->fifo_starve = num; | |
245 | ||
246 | temp = gfar_read(&priv->regs->fifo_tx_starve); | |
247 | temp &= ~FIFO_TX_STARVE_MASK; | |
248 | temp |= num; | |
249 | gfar_write(&priv->regs->fifo_tx_starve, temp); | |
250 | ||
fef6108d | 251 | spin_unlock_irqrestore(&priv->txlock, flags); |
7f7f5316 AF |
252 | |
253 | return count; | |
254 | } | |
255 | ||
256 | static ssize_t gfar_show_fifo_starve_off(struct class_device *cdev, char *buf) | |
257 | { | |
258 | struct net_device *dev = to_net_dev(cdev); | |
259 | struct gfar_private *priv = netdev_priv(dev); | |
260 | ||
261 | return sprintf(buf, "%d\n", priv->fifo_starve_off); | |
262 | } | |
263 | ||
264 | static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev, | |
265 | const char *buf, size_t count) | |
266 | { | |
267 | struct net_device *dev = to_net_dev(cdev); | |
268 | struct gfar_private *priv = netdev_priv(dev); | |
269 | unsigned int num = simple_strtoul(buf, NULL, 0); | |
270 | u32 temp; | |
271 | unsigned long flags; | |
272 | ||
273 | if (num > GFAR_MAX_FIFO_STARVE_OFF) | |
274 | return count; | |
275 | ||
fef6108d | 276 | spin_lock_irqsave(&priv->txlock, flags); |
7f7f5316 AF |
277 | |
278 | priv->fifo_starve_off = num; | |
279 | ||
280 | temp = gfar_read(&priv->regs->fifo_tx_starve_shutoff); | |
281 | temp &= ~FIFO_TX_STARVE_OFF_MASK; | |
282 | temp |= num; | |
283 | gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); | |
284 | ||
fef6108d | 285 | spin_unlock_irqrestore(&priv->txlock, flags); |
7f7f5316 AF |
286 | |
287 | return count; | |
288 | } | |
289 | ||
290 | void gfar_init_sysfs(struct net_device *dev) | |
291 | { | |
292 | struct gfar_private *priv = netdev_priv(dev); | |
293 | ||
294 | /* Initialize the default values */ | |
295 | priv->rx_stash_size = DEFAULT_STASH_LENGTH; | |
296 | priv->rx_stash_index = DEFAULT_STASH_INDEX; | |
297 | priv->fifo_threshold = DEFAULT_FIFO_TX_THR; | |
298 | priv->fifo_starve = DEFAULT_FIFO_TX_STARVE; | |
299 | priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF; | |
300 | priv->bd_stash_en = DEFAULT_BD_STASH; | |
301 | ||
302 | /* Create our sysfs files */ | |
303 | GFAR_CREATE_FILE(dev, bd_stash); | |
304 | GFAR_CREATE_FILE(dev, rx_stash_size); | |
305 | GFAR_CREATE_FILE(dev, rx_stash_index); | |
306 | GFAR_CREATE_FILE(dev, fifo_threshold); | |
307 | GFAR_CREATE_FILE(dev, fifo_starve); | |
308 | GFAR_CREATE_FILE(dev, fifo_starve_off); | |
309 | ||
310 | } |