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#include <linux/version.h>
37
38#include "gianfar.h"
39
40#define GFAR_ATTR(_name) \
41static ssize_t gfar_show_##_name(struct device *dev, \
42	 struct device_attribute *attr, char *buf); \
43static ssize_t gfar_set_##_name(struct device *dev, \
44		struct device_attribute *attr, \
45		const char *buf, size_t count); \
46static DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name)
47
48#define GFAR_CREATE_FILE(_dev, _name) \
49	device_create_file(&_dev->dev, &dev_attr_##_name)
50
51GFAR_ATTR(bd_stash);
52GFAR_ATTR(rx_stash_size);
53GFAR_ATTR(rx_stash_index);
54GFAR_ATTR(fifo_threshold);
55GFAR_ATTR(fifo_starve);
56GFAR_ATTR(fifo_starve_off);
57
58static ssize_t gfar_show_bd_stash(struct device *dev,
59				  struct device_attribute *attr, char *buf)
60{
61	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
62
63	return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off");
64}
65
66static ssize_t gfar_set_bd_stash(struct device *dev,
67				 struct device_attribute *attr,
68				 const char *buf, size_t count)
69{
70	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
71	int new_setting = 0;
72	u32 temp;
73	unsigned long flags;
74
75	/* Find out the new setting */
76	if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
77		new_setting = 1;
78	else if (!strncmp("off", buf, count - 1)
79		 || !strncmp("0", buf, count - 1))
80		new_setting = 0;
81	else
82		return count;
83
84	spin_lock_irqsave(&priv->rxlock, flags);
85
86	/* Set the new stashing value */
87	priv->bd_stash_en = new_setting;
88
89	temp = gfar_read(&priv->regs->attr);
90
91	if (new_setting)
92		temp |= ATTR_BDSTASH;
93	else
94		temp &= ~(ATTR_BDSTASH);
95
96	gfar_write(&priv->regs->attr, temp);
97
98	spin_unlock_irqrestore(&priv->rxlock, flags);
99
100	return count;
101}
102
103static ssize_t gfar_show_rx_stash_size(struct device *dev,
104				       struct device_attribute *attr, char *buf)
105{
106	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
107
108	return sprintf(buf, "%d\n", priv->rx_stash_size);
109}
110
111static ssize_t gfar_set_rx_stash_size(struct device *dev,
112				      struct device_attribute *attr,
113				      const char *buf, size_t count)
114{
115	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
116	unsigned int length = simple_strtoul(buf, NULL, 0);
117	u32 temp;
118	unsigned long flags;
119
120	spin_lock_irqsave(&priv->rxlock, flags);
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
144	spin_unlock_irqrestore(&priv->rxlock, flags);
145
146	return count;
147}
148
149/* Stashing will only be enabled when rx_stash_size != 0 */
150static ssize_t gfar_show_rx_stash_index(struct device *dev,
151					struct device_attribute *attr,
152					char *buf)
153{
154	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
155
156	return sprintf(buf, "%d\n", priv->rx_stash_index);
157}
158
159static ssize_t gfar_set_rx_stash_index(struct device *dev,
160				       struct device_attribute *attr,
161				       const char *buf, size_t count)
162{
163	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
164	unsigned short index = simple_strtoul(buf, NULL, 0);
165	u32 temp;
166	unsigned long flags;
167
168	spin_lock_irqsave(&priv->rxlock, flags);
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
182	spin_unlock_irqrestore(&priv->rxlock, flags);
183
184	return count;
185}
186
187static ssize_t gfar_show_fifo_threshold(struct device *dev,
188					struct device_attribute *attr,
189					char *buf)
190{
191	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
192
193	return sprintf(buf, "%d\n", priv->fifo_threshold);
194}
195
196static ssize_t gfar_set_fifo_threshold(struct device *dev,
197				       struct device_attribute *attr,
198				       const char *buf, size_t count)
199{
200	struct gfar_private *priv = netdev_priv(to_net_dev(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->txlock, 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->txlock, flags);
218
219	return count;
220}
221
222static ssize_t gfar_show_fifo_starve(struct device *dev,
223				     struct device_attribute *attr, char *buf)
224{
225	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
226
227	return sprintf(buf, "%d\n", priv->fifo_starve);
228}
229
230static ssize_t gfar_set_fifo_starve(struct device *dev,
231				    struct device_attribute *attr,
232				    const char *buf, size_t count)
233{
234	struct gfar_private *priv = netdev_priv(to_net_dev(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
242	spin_lock_irqsave(&priv->txlock, flags);
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
251	spin_unlock_irqrestore(&priv->txlock, flags);
252
253	return count;
254}
255
256static ssize_t gfar_show_fifo_starve_off(struct device *dev,
257					 struct device_attribute *attr,
258					 char *buf)
259{
260	struct gfar_private *priv = netdev_priv(to_net_dev(dev));
261
262	return sprintf(buf, "%d\n", priv->fifo_starve_off);
263}
264
265static ssize_t gfar_set_fifo_starve_off(struct device *dev,
266					struct device_attribute *attr,
267					const char *buf, size_t count)
268{
269	struct gfar_private *priv = netdev_priv(to_net_dev(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->txlock, 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->txlock, flags);
287
288	return count;
289}
290
291void 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}
312