xref: /openbmc/linux/drivers/s390/net/ctcm_sysfs.c (revision ab73b751)
1 /*
2  * drivers/s390/net/ctcm_sysfs.c
3  *
4  * Copyright IBM Corp. 2007, 2007
5  * Authors:	Peter Tiedemann (ptiedem@de.ibm.com)
6  *
7  */
8 
9 #undef DEBUG
10 #undef DEBUGDATA
11 #undef DEBUGCCW
12 
13 #define KMSG_COMPONENT "ctcm"
14 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
15 
16 #include <linux/device.h>
17 #include <linux/sysfs.h>
18 #include <linux/slab.h>
19 #include "ctcm_main.h"
20 
21 /*
22  * sysfs attributes
23  */
24 
25 static ssize_t ctcm_buffer_show(struct device *dev,
26 				struct device_attribute *attr, char *buf)
27 {
28 	struct ctcm_priv *priv = dev_get_drvdata(dev);
29 
30 	if (!priv)
31 		return -ENODEV;
32 	return sprintf(buf, "%d\n", priv->buffer_size);
33 }
34 
35 static ssize_t ctcm_buffer_write(struct device *dev,
36 		struct device_attribute *attr, const char *buf, size_t count)
37 {
38 	struct net_device *ndev;
39 	int bs1;
40 	struct ctcm_priv *priv = dev_get_drvdata(dev);
41 
42 	ndev = priv->channel[CTCM_READ]->netdev;
43 	if (!(priv && priv->channel[CTCM_READ] && ndev)) {
44 		CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev");
45 		return -ENODEV;
46 	}
47 
48 	sscanf(buf, "%u", &bs1);
49 	if (bs1 > CTCM_BUFSIZE_LIMIT)
50 					goto einval;
51 	if (bs1 < (576 + LL_HEADER_LENGTH + 2))
52 					goto einval;
53 	priv->buffer_size = bs1;	/* just to overwrite the default */
54 
55 	if ((ndev->flags & IFF_RUNNING) &&
56 	    (bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
57 					goto einval;
58 
59 	priv->channel[CTCM_READ]->max_bufsize = bs1;
60 	priv->channel[CTCM_WRITE]->max_bufsize = bs1;
61 	if (!(ndev->flags & IFF_RUNNING))
62 		ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
63 	priv->channel[CTCM_READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
64 	priv->channel[CTCM_WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
65 
66 	CTCM_DBF_DEV(SETUP, ndev, buf);
67 	return count;
68 
69 einval:
70 	CTCM_DBF_DEV(SETUP, ndev, "buff_err");
71 	return -EINVAL;
72 }
73 
74 static void ctcm_print_statistics(struct ctcm_priv *priv)
75 {
76 	char *sbuf;
77 	char *p;
78 
79 	if (!priv)
80 		return;
81 	sbuf = kmalloc(2048, GFP_KERNEL);
82 	if (sbuf == NULL)
83 		return;
84 	p = sbuf;
85 
86 	p += sprintf(p, "  Device FSM state: %s\n",
87 		     fsm_getstate_str(priv->fsm));
88 	p += sprintf(p, "  RX channel FSM state: %s\n",
89 		     fsm_getstate_str(priv->channel[CTCM_READ]->fsm));
90 	p += sprintf(p, "  TX channel FSM state: %s\n",
91 		     fsm_getstate_str(priv->channel[CTCM_WRITE]->fsm));
92 	p += sprintf(p, "  Max. TX buffer used: %ld\n",
93 		     priv->channel[WRITE]->prof.maxmulti);
94 	p += sprintf(p, "  Max. chained SKBs: %ld\n",
95 		     priv->channel[WRITE]->prof.maxcqueue);
96 	p += sprintf(p, "  TX single write ops: %ld\n",
97 		     priv->channel[WRITE]->prof.doios_single);
98 	p += sprintf(p, "  TX multi write ops: %ld\n",
99 		     priv->channel[WRITE]->prof.doios_multi);
100 	p += sprintf(p, "  Netto bytes written: %ld\n",
101 		     priv->channel[WRITE]->prof.txlen);
102 	p += sprintf(p, "  Max. TX IO-time: %ld\n",
103 		     priv->channel[WRITE]->prof.tx_time);
104 
105 	printk(KERN_INFO "Statistics for %s:\n%s",
106 				priv->channel[CTCM_WRITE]->netdev->name, sbuf);
107 	kfree(sbuf);
108 	return;
109 }
110 
111 static ssize_t stats_show(struct device *dev,
112 			  struct device_attribute *attr, char *buf)
113 {
114 	struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
115 	struct ctcm_priv *priv = dev_get_drvdata(dev);
116 
117 	if (!priv || gdev->state != CCWGROUP_ONLINE)
118 		return -ENODEV;
119 	ctcm_print_statistics(priv);
120 	return sprintf(buf, "0\n");
121 }
122 
123 static ssize_t stats_write(struct device *dev, struct device_attribute *attr,
124 				const char *buf, size_t count)
125 {
126 	struct ctcm_priv *priv = dev_get_drvdata(dev);
127 	if (!priv)
128 		return -ENODEV;
129 	/* Reset statistics */
130 	memset(&priv->channel[WRITE]->prof, 0,
131 				sizeof(priv->channel[CTCM_WRITE]->prof));
132 	return count;
133 }
134 
135 static ssize_t ctcm_proto_show(struct device *dev,
136 				struct device_attribute *attr, char *buf)
137 {
138 	struct ctcm_priv *priv = dev_get_drvdata(dev);
139 	if (!priv)
140 		return -ENODEV;
141 
142 	return sprintf(buf, "%d\n", priv->protocol);
143 }
144 
145 static ssize_t ctcm_proto_store(struct device *dev,
146 		struct device_attribute *attr, const char *buf, size_t count)
147 {
148 	int value;
149 	struct ctcm_priv *priv = dev_get_drvdata(dev);
150 
151 	if (!priv)
152 		return -ENODEV;
153 	sscanf(buf, "%u", &value);
154 	if (!((value == CTCM_PROTO_S390)  ||
155 	      (value == CTCM_PROTO_LINUX) ||
156 	      (value == CTCM_PROTO_MPC) ||
157 	      (value == CTCM_PROTO_OS390)))
158 		return -EINVAL;
159 	priv->protocol = value;
160 	CTCM_DBF_DEV(SETUP, dev, buf);
161 
162 	return count;
163 }
164 
165 static const char *ctcm_type[] = {
166 	"not a channel",
167 	"CTC/A",
168 	"FICON channel",
169 	"ESCON channel",
170 	"unknown channel type",
171 	"unsupported channel type",
172 };
173 
174 static ssize_t ctcm_type_show(struct device *dev,
175 				struct device_attribute *attr, char *buf)
176 {
177 	struct ccwgroup_device *cgdev;
178 
179 	cgdev = to_ccwgroupdev(dev);
180 	if (!cgdev)
181 		return -ENODEV;
182 
183 	return sprintf(buf, "%s\n",
184 			ctcm_type[cgdev->cdev[0]->id.driver_info]);
185 }
186 
187 static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write);
188 static DEVICE_ATTR(protocol, 0644, ctcm_proto_show, ctcm_proto_store);
189 static DEVICE_ATTR(type, 0444, ctcm_type_show, NULL);
190 static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
191 
192 static struct attribute *ctcm_attr[] = {
193 	&dev_attr_protocol.attr,
194 	&dev_attr_type.attr,
195 	&dev_attr_buffer.attr,
196 	&dev_attr_stats.attr,
197 	NULL,
198 };
199 
200 static struct attribute_group ctcm_attr_group = {
201 	.attrs = ctcm_attr,
202 };
203 const struct attribute_group *ctcm_attr_groups[] = {
204 	&ctcm_attr_group,
205 	NULL,
206 };
207