3 * linux/drivers/s390/net/qeth_fs.c
5 * Linux on zSeries OSA Express and HiperSockets support
6 * This file contains code related to procfs.
8 * Copyright 2000,2003 IBM Corporation
10 * Author(s): Thomas Spatzier <tspat@de.ibm.com>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/proc_fs.h>
16 #include <linux/seq_file.h>
17 #include <linux/list.h>
18 #include <linux/rwsem.h>
24 /***** /proc/qeth *****/
25 #define QETH_PROCFILE_NAME "qeth"
26 static struct proc_dir_entry
*qeth_procfile
;
29 qeth_procfile_seq_match(struct device
*dev
, void *data
)
35 qeth_procfile_seq_start(struct seq_file
*s
, loff_t
*offset
)
37 struct device
*dev
= NULL
;
40 down_read(&qeth_ccwgroup_driver
.driver
.bus
->subsys
.rwsem
);
42 return SEQ_START_TOKEN
;
44 dev
= driver_find_device(&qeth_ccwgroup_driver
.driver
, dev
,
45 NULL
, qeth_procfile_seq_match
);
54 qeth_procfile_seq_stop(struct seq_file
*s
, void* it
)
56 up_read(&qeth_ccwgroup_driver
.driver
.bus
->subsys
.rwsem
);
60 qeth_procfile_seq_next(struct seq_file
*s
, void *it
, loff_t
*offset
)
62 struct device
*prev
, *next
;
64 if (it
== SEQ_START_TOKEN
)
67 prev
= (struct device
*) it
;
68 next
= driver_find_device(&qeth_ccwgroup_driver
.driver
,
69 prev
, NULL
, qeth_procfile_seq_match
);
74 static inline const char *
75 qeth_get_router_str(struct qeth_card
*card
, int ipv
)
77 enum qeth_routing_types routing_type
= NO_ROUTER
;
80 routing_type
= card
->options
.route4
.type
;
82 #ifdef CONFIG_QETH_IPV6
83 routing_type
= card
->options
.route6
.type
;
86 #endif /* CONFIG_QETH_IPV6 */
89 switch (routing_type
){
92 case SECONDARY_ROUTER
:
94 case MULTICAST_ROUTER
:
95 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
98 case PRIMARY_CONNECTOR
:
99 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
102 case SECONDARY_CONNECTOR
:
103 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
106 default: /* NO_ROUTER */
112 qeth_procfile_seq_show(struct seq_file
*s
, void *it
)
114 struct device
*device
;
115 struct qeth_card
*card
;
116 char tmp
[12]; /* for qeth_get_prioq_str */
118 if (it
== SEQ_START_TOKEN
){
119 seq_printf(s
, "devices CHPID interface "
120 "cardtype port chksum prio-q'ing rtr4 "
122 seq_printf(s
, "-------------------------- ----- ---------- "
123 "-------------- ---- ------ ---------- ---- "
124 "---- ----- -----\n");
126 device
= (struct device
*) it
;
127 card
= device
->driver_data
;
128 seq_printf(s
, "%s/%s/%s x%02X %-10s %-14s %-4i ",
133 QETH_CARD_IFNAME(card
),
134 qeth_get_cardname_short(card
),
136 if (card
->lan_online
)
137 seq_printf(s
, "%-6s %-10s %-4s %-4s %-5s %-5i\n",
138 qeth_get_checksum_str(card
),
139 qeth_get_prioq_str(card
, tmp
),
140 qeth_get_router_str(card
, 4),
141 qeth_get_router_str(card
, 6),
142 qeth_get_bufsize_str(card
),
143 card
->qdio
.in_buf_pool
.buf_count
);
145 seq_printf(s
, " +++ LAN OFFLINE +++\n");
151 static struct seq_operations qeth_procfile_seq_ops
= {
152 .start
= qeth_procfile_seq_start
,
153 .stop
= qeth_procfile_seq_stop
,
154 .next
= qeth_procfile_seq_next
,
155 .show
= qeth_procfile_seq_show
,
159 qeth_procfile_open(struct inode
*inode
, struct file
*file
)
161 return seq_open(file
, &qeth_procfile_seq_ops
);
164 static struct file_operations qeth_procfile_fops
= {
165 .owner
= THIS_MODULE
,
166 .open
= qeth_procfile_open
,
169 .release
= seq_release
,
172 /***** /proc/qeth_perf *****/
173 #define QETH_PERF_PROCFILE_NAME "qeth_perf"
174 static struct proc_dir_entry
*qeth_perf_procfile
;
176 #ifdef CONFIG_QETH_PERF_STATS
178 qeth_perf_procfile_seq_show(struct seq_file
*s
, void *it
)
180 struct device
*device
;
181 struct qeth_card
*card
;
184 if (it
== SEQ_START_TOKEN
)
187 device
= (struct device
*) it
;
188 card
= device
->driver_data
;
189 seq_printf(s
, "For card with devnos %s/%s/%s (%s):\n",
193 QETH_CARD_IFNAME(card
)
195 seq_printf(s
, " Skb's/buffers received : %lu/%u\n"
196 " Skb's/buffers sent : %lu/%u\n\n",
197 card
->stats
.rx_packets
, card
->perf_stats
.bufs_rec
,
198 card
->stats
.tx_packets
, card
->perf_stats
.bufs_sent
200 seq_printf(s
, " Skb's/buffers sent without packing : %lu/%u\n"
201 " Skb's/buffers sent with packing : %u/%u\n\n",
202 card
->stats
.tx_packets
- card
->perf_stats
.skbs_sent_pack
,
203 card
->perf_stats
.bufs_sent
- card
->perf_stats
.bufs_sent_pack
,
204 card
->perf_stats
.skbs_sent_pack
,
205 card
->perf_stats
.bufs_sent_pack
207 seq_printf(s
, " Skbs sent in SG mode : %u\n"
208 " Skb fragments sent in SG mode : %u\n\n",
209 card
->perf_stats
.sg_skbs_sent
,
210 card
->perf_stats
.sg_frags_sent
);
211 seq_printf(s
, " large_send tx (in Kbytes) : %u\n"
212 " large_send count : %u\n\n",
213 card
->perf_stats
.large_send_bytes
>> 10,
214 card
->perf_stats
.large_send_cnt
);
215 seq_printf(s
, " Packing state changes no pkg.->packing : %u/%u\n"
216 " Watermarks L/H : %i/%i\n"
217 " Current buffer usage (outbound q's) : "
219 card
->perf_stats
.sc_dp_p
, card
->perf_stats
.sc_p_dp
,
220 QETH_LOW_WATERMARK_PACK
, QETH_HIGH_WATERMARK_PACK
,
221 atomic_read(&card
->qdio
.out_qs
[0]->used_buffers
),
222 (card
->qdio
.no_out_queues
> 1)?
223 atomic_read(&card
->qdio
.out_qs
[1]->used_buffers
)
225 (card
->qdio
.no_out_queues
> 2)?
226 atomic_read(&card
->qdio
.out_qs
[2]->used_buffers
)
228 (card
->qdio
.no_out_queues
> 3)?
229 atomic_read(&card
->qdio
.out_qs
[3]->used_buffers
)
232 seq_printf(s
, " Inbound handler time (in us) : %u\n"
233 " Inbound handler count : %u\n"
234 " Inbound do_QDIO time (in us) : %u\n"
235 " Inbound do_QDIO count : %u\n\n"
236 " Outbound handler time (in us) : %u\n"
237 " Outbound handler count : %u\n\n"
238 " Outbound time (in us, incl QDIO) : %u\n"
239 " Outbound count : %u\n"
240 " Outbound do_QDIO time (in us) : %u\n"
241 " Outbound do_QDIO count : %u\n\n",
242 card
->perf_stats
.inbound_time
,
243 card
->perf_stats
.inbound_cnt
,
244 card
->perf_stats
.inbound_do_qdio_time
,
245 card
->perf_stats
.inbound_do_qdio_cnt
,
246 card
->perf_stats
.outbound_handler_time
,
247 card
->perf_stats
.outbound_handler_cnt
,
248 card
->perf_stats
.outbound_time
,
249 card
->perf_stats
.outbound_cnt
,
250 card
->perf_stats
.outbound_do_qdio_time
,
251 card
->perf_stats
.outbound_do_qdio_cnt
257 static struct seq_operations qeth_perf_procfile_seq_ops
= {
258 .start
= qeth_procfile_seq_start
,
259 .stop
= qeth_procfile_seq_stop
,
260 .next
= qeth_procfile_seq_next
,
261 .show
= qeth_perf_procfile_seq_show
,
265 qeth_perf_procfile_open(struct inode
*inode
, struct file
*file
)
267 return seq_open(file
, &qeth_perf_procfile_seq_ops
);
270 static struct file_operations qeth_perf_procfile_fops
= {
271 .owner
= THIS_MODULE
,
272 .open
= qeth_perf_procfile_open
,
275 .release
= seq_release
,
278 #define qeth_perf_procfile_created qeth_perf_procfile
280 #define qeth_perf_procfile_created 1
281 #endif /* CONFIG_QETH_PERF_STATS */
284 qeth_create_procfs_entries(void)
286 qeth_procfile
= create_proc_entry(QETH_PROCFILE_NAME
,
287 S_IFREG
| 0444, NULL
);
289 qeth_procfile
->proc_fops
= &qeth_procfile_fops
;
291 #ifdef CONFIG_QETH_PERF_STATS
292 qeth_perf_procfile
= create_proc_entry(QETH_PERF_PROCFILE_NAME
,
293 S_IFREG
| 0444, NULL
);
294 if (qeth_perf_procfile
)
295 qeth_perf_procfile
->proc_fops
= &qeth_perf_procfile_fops
;
296 #endif /* CONFIG_QETH_PERF_STATS */
299 qeth_perf_procfile_created
)
306 qeth_remove_procfs_entries(void)
309 remove_proc_entry(QETH_PROCFILE_NAME
, NULL
);
310 if (qeth_perf_procfile
)
311 remove_proc_entry(QETH_PERF_PROCFILE_NAME
, NULL
);