Merge branch 'omap-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind...
[linux-2.6] / drivers / net / gianfar_sysfs.c
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 (galak@kernel.crashing.org)
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/kernel.h>
23 #include <linux/string.h>
24 #include <linux/errno.h>
25 #include <linux/unistd.h>
26 #include <linux/slab.h>
27 #include <linux/init.h>
28 #include <linux/delay.h>
29 #include <linux/etherdevice.h>
30 #include <linux/spinlock.h>
31 #include <linux/mm.h>
32 #include <linux/device.h>
33
34 #include <asm/uaccess.h>
35 #include <linux/module.h>
36
37 #include "gianfar.h"
38
39 static ssize_t gfar_show_bd_stash(struct device *dev,
40                                   struct device_attribute *attr, char *buf)
41 {
42         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
43
44         return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off");
45 }
46
47 static ssize_t gfar_set_bd_stash(struct device *dev,
48                                  struct device_attribute *attr,
49                                  const char *buf, size_t count)
50 {
51         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
52         int new_setting = 0;
53         u32 temp;
54         unsigned long flags;
55
56         /* Find out the new setting */
57         if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
58                 new_setting = 1;
59         else if (!strncmp("off", buf, count - 1)
60                  || !strncmp("0", buf, count - 1))
61                 new_setting = 0;
62         else
63                 return count;
64
65         spin_lock_irqsave(&priv->rxlock, flags);
66
67         /* Set the new stashing value */
68         priv->bd_stash_en = new_setting;
69
70         temp = gfar_read(&priv->regs->attr);
71
72         if (new_setting)
73                 temp |= ATTR_BDSTASH;
74         else
75                 temp &= ~(ATTR_BDSTASH);
76
77         gfar_write(&priv->regs->attr, temp);
78
79         spin_unlock_irqrestore(&priv->rxlock, flags);
80
81         return count;
82 }
83
84 DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash);
85
86 static ssize_t gfar_show_rx_stash_size(struct device *dev,
87                                        struct device_attribute *attr, char *buf)
88 {
89         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
90
91         return sprintf(buf, "%d\n", priv->rx_stash_size);
92 }
93
94 static ssize_t gfar_set_rx_stash_size(struct device *dev,
95                                       struct device_attribute *attr,
96                                       const char *buf, size_t count)
97 {
98         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
99         unsigned int length = simple_strtoul(buf, NULL, 0);
100         u32 temp;
101         unsigned long flags;
102
103         spin_lock_irqsave(&priv->rxlock, flags);
104         if (length > priv->rx_buffer_size)
105                 goto out;
106
107         if (length == priv->rx_stash_size)
108                 goto out;
109
110         priv->rx_stash_size = length;
111
112         temp = gfar_read(&priv->regs->attreli);
113         temp &= ~ATTRELI_EL_MASK;
114         temp |= ATTRELI_EL(length);
115         gfar_write(&priv->regs->attreli, temp);
116
117         /* Turn stashing on/off as appropriate */
118         temp = gfar_read(&priv->regs->attr);
119
120         if (length)
121                 temp |= ATTR_BUFSTASH;
122         else
123                 temp &= ~(ATTR_BUFSTASH);
124
125         gfar_write(&priv->regs->attr, temp);
126
127 out:
128         spin_unlock_irqrestore(&priv->rxlock, flags);
129
130         return count;
131 }
132
133 DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size,
134             gfar_set_rx_stash_size);
135
136 /* Stashing will only be enabled when rx_stash_size != 0 */
137 static ssize_t gfar_show_rx_stash_index(struct device *dev,
138                                         struct device_attribute *attr,
139                                         char *buf)
140 {
141         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
142
143         return sprintf(buf, "%d\n", priv->rx_stash_index);
144 }
145
146 static ssize_t gfar_set_rx_stash_index(struct device *dev,
147                                        struct device_attribute *attr,
148                                        const char *buf, size_t count)
149 {
150         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
151         unsigned short index = simple_strtoul(buf, NULL, 0);
152         u32 temp;
153         unsigned long flags;
154
155         spin_lock_irqsave(&priv->rxlock, flags);
156         if (index > priv->rx_stash_size)
157                 goto out;
158
159         if (index == priv->rx_stash_index)
160                 goto out;
161
162         priv->rx_stash_index = index;
163
164         temp = gfar_read(&priv->regs->attreli);
165         temp &= ~ATTRELI_EI_MASK;
166         temp |= ATTRELI_EI(index);
167         gfar_write(&priv->regs->attreli, flags);
168
169 out:
170         spin_unlock_irqrestore(&priv->rxlock, flags);
171
172         return count;
173 }
174
175 DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index,
176             gfar_set_rx_stash_index);
177
178 static ssize_t gfar_show_fifo_threshold(struct device *dev,
179                                         struct device_attribute *attr,
180                                         char *buf)
181 {
182         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
183
184         return sprintf(buf, "%d\n", priv->fifo_threshold);
185 }
186
187 static ssize_t gfar_set_fifo_threshold(struct device *dev,
188                                        struct device_attribute *attr,
189                                        const char *buf, size_t count)
190 {
191         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
192         unsigned int length = simple_strtoul(buf, NULL, 0);
193         u32 temp;
194         unsigned long flags;
195
196         if (length > GFAR_MAX_FIFO_THRESHOLD)
197                 return count;
198
199         spin_lock_irqsave(&priv->txlock, flags);
200
201         priv->fifo_threshold = length;
202
203         temp = gfar_read(&priv->regs->fifo_tx_thr);
204         temp &= ~FIFO_TX_THR_MASK;
205         temp |= length;
206         gfar_write(&priv->regs->fifo_tx_thr, temp);
207
208         spin_unlock_irqrestore(&priv->txlock, flags);
209
210         return count;
211 }
212
213 DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold,
214             gfar_set_fifo_threshold);
215
216 static ssize_t gfar_show_fifo_starve(struct device *dev,
217                                      struct device_attribute *attr, char *buf)
218 {
219         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
220
221         return sprintf(buf, "%d\n", priv->fifo_starve);
222 }
223
224 static ssize_t gfar_set_fifo_starve(struct device *dev,
225                                     struct device_attribute *attr,
226                                     const char *buf, size_t count)
227 {
228         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
229         unsigned int num = simple_strtoul(buf, NULL, 0);
230         u32 temp;
231         unsigned long flags;
232
233         if (num > GFAR_MAX_FIFO_STARVE)
234                 return count;
235
236         spin_lock_irqsave(&priv->txlock, flags);
237
238         priv->fifo_starve = num;
239
240         temp = gfar_read(&priv->regs->fifo_tx_starve);
241         temp &= ~FIFO_TX_STARVE_MASK;
242         temp |= num;
243         gfar_write(&priv->regs->fifo_tx_starve, temp);
244
245         spin_unlock_irqrestore(&priv->txlock, flags);
246
247         return count;
248 }
249
250 DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve, gfar_set_fifo_starve);
251
252 static ssize_t gfar_show_fifo_starve_off(struct device *dev,
253                                          struct device_attribute *attr,
254                                          char *buf)
255 {
256         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
257
258         return sprintf(buf, "%d\n", priv->fifo_starve_off);
259 }
260
261 static ssize_t gfar_set_fifo_starve_off(struct device *dev,
262                                         struct device_attribute *attr,
263                                         const char *buf, size_t count)
264 {
265         struct gfar_private *priv = netdev_priv(to_net_dev(dev));
266         unsigned int num = simple_strtoul(buf, NULL, 0);
267         u32 temp;
268         unsigned long flags;
269
270         if (num > GFAR_MAX_FIFO_STARVE_OFF)
271                 return count;
272
273         spin_lock_irqsave(&priv->txlock, flags);
274
275         priv->fifo_starve_off = num;
276
277         temp = gfar_read(&priv->regs->fifo_tx_starve_shutoff);
278         temp &= ~FIFO_TX_STARVE_OFF_MASK;
279         temp |= num;
280         gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp);
281
282         spin_unlock_irqrestore(&priv->txlock, flags);
283
284         return count;
285 }
286
287 DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off,
288             gfar_set_fifo_starve_off);
289
290 void gfar_init_sysfs(struct net_device *dev)
291 {
292         struct gfar_private *priv = netdev_priv(dev);
293         int rc;
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         rc = device_create_file(&dev->dev, &dev_attr_bd_stash);
305         rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_size);
306         rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_index);
307         rc |= device_create_file(&dev->dev, &dev_attr_fifo_threshold);
308         rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve);
309         rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve_off);
310         if (rc)
311                 dev_err(&dev->dev, "Error creating gianfar sysfs files.\n");
312 }