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
;
41 return SEQ_START_TOKEN
;
43 dev
= driver_find_device(&qeth_ccwgroup_driver
.driver
, dev
,
44 NULL
, qeth_procfile_seq_match
);
53 qeth_procfile_seq_stop(struct seq_file
*s
, void* it
)
58 qeth_procfile_seq_next(struct seq_file
*s
, void *it
, loff_t
*offset
)
60 struct device
*prev
, *next
;
62 if (it
== SEQ_START_TOKEN
)
65 prev
= (struct device
*) it
;
66 next
= driver_find_device(&qeth_ccwgroup_driver
.driver
,
67 prev
, NULL
, qeth_procfile_seq_match
);
72 static inline const char *
73 qeth_get_router_str(struct qeth_card
*card
, int ipv
)
75 enum qeth_routing_types routing_type
= NO_ROUTER
;
78 routing_type
= card
->options
.route4
.type
;
80 #ifdef CONFIG_QETH_IPV6
81 routing_type
= card
->options
.route6
.type
;
84 #endif /* CONFIG_QETH_IPV6 */
87 switch (routing_type
){
90 case SECONDARY_ROUTER
:
92 case MULTICAST_ROUTER
:
93 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
96 case PRIMARY_CONNECTOR
:
97 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
100 case SECONDARY_CONNECTOR
:
101 if (card
->info
.broadcast_capable
== QETH_BROADCAST_WITHOUT_ECHO
)
104 default: /* NO_ROUTER */
110 qeth_procfile_seq_show(struct seq_file
*s
, void *it
)
112 struct device
*device
;
113 struct qeth_card
*card
;
114 char tmp
[12]; /* for qeth_get_prioq_str */
116 if (it
== SEQ_START_TOKEN
){
117 seq_printf(s
, "devices CHPID interface "
118 "cardtype port chksum prio-q'ing rtr4 "
120 seq_printf(s
, "-------------------------- ----- ---------- "
121 "-------------- ---- ------ ---------- ---- "
122 "---- ----- -----\n");
124 device
= (struct device
*) it
;
125 card
= device
->driver_data
;
126 seq_printf(s
, "%s/%s/%s x%02X %-10s %-14s %-4i ",
131 QETH_CARD_IFNAME(card
),
132 qeth_get_cardname_short(card
),
134 if (card
->lan_online
)
135 seq_printf(s
, "%-6s %-10s %-4s %-4s %-5s %-5i\n",
136 qeth_get_checksum_str(card
),
137 qeth_get_prioq_str(card
, tmp
),
138 qeth_get_router_str(card
, 4),
139 qeth_get_router_str(card
, 6),
140 qeth_get_bufsize_str(card
),
141 card
->qdio
.in_buf_pool
.buf_count
);
143 seq_printf(s
, " +++ LAN OFFLINE +++\n");
149 static struct seq_operations qeth_procfile_seq_ops
= {
150 .start
= qeth_procfile_seq_start
,
151 .stop
= qeth_procfile_seq_stop
,
152 .next
= qeth_procfile_seq_next
,
153 .show
= qeth_procfile_seq_show
,
157 qeth_procfile_open(struct inode
*inode
, struct file
*file
)
159 return seq_open(file
, &qeth_procfile_seq_ops
);
162 static const struct file_operations qeth_procfile_fops
= {
163 .owner
= THIS_MODULE
,
164 .open
= qeth_procfile_open
,
167 .release
= seq_release
,
170 /***** /proc/qeth_perf *****/
171 #define QETH_PERF_PROCFILE_NAME "qeth_perf"
172 static struct proc_dir_entry
*qeth_perf_procfile
;
175 qeth_perf_procfile_seq_show(struct seq_file
*s
, void *it
)
177 struct device
*device
;
178 struct qeth_card
*card
;
181 if (it
== SEQ_START_TOKEN
)
184 device
= (struct device
*) it
;
185 card
= device
->driver_data
;
186 seq_printf(s
, "For card with devnos %s/%s/%s (%s):\n",
190 QETH_CARD_IFNAME(card
)
192 if (!card
->options
.performance_stats
)
193 seq_printf(s
, "Performance statistics are deactivated.\n");
194 seq_printf(s
, " Skb's/buffers received : %lu/%u\n"
195 " Skb's/buffers sent : %lu/%u\n\n",
196 card
->stats
.rx_packets
-
197 card
->perf_stats
.initial_rx_packets
,
198 card
->perf_stats
.bufs_rec
,
199 card
->stats
.tx_packets
-
200 card
->perf_stats
.initial_tx_packets
,
201 card
->perf_stats
.bufs_sent
203 seq_printf(s
, " Skb's/buffers sent without packing : %lu/%u\n"
204 " Skb's/buffers sent with packing : %u/%u\n\n",
205 card
->stats
.tx_packets
- card
->perf_stats
.initial_tx_packets
206 - card
->perf_stats
.skbs_sent_pack
,
207 card
->perf_stats
.bufs_sent
- card
->perf_stats
.bufs_sent_pack
,
208 card
->perf_stats
.skbs_sent_pack
,
209 card
->perf_stats
.bufs_sent_pack
211 seq_printf(s
, " Skbs sent in SG mode : %u\n"
212 " Skb fragments sent in SG mode : %u\n\n",
213 card
->perf_stats
.sg_skbs_sent
,
214 card
->perf_stats
.sg_frags_sent
);
215 seq_printf(s
, " Skbs received in SG mode : %u\n"
216 " Skb fragments received in SG mode : %u\n"
217 " Page allocations for rx SG mode : %u\n\n",
218 card
->perf_stats
.sg_skbs_rx
,
219 card
->perf_stats
.sg_frags_rx
,
220 card
->perf_stats
.sg_alloc_page_rx
);
221 seq_printf(s
, " large_send tx (in Kbytes) : %u\n"
222 " large_send count : %u\n\n",
223 card
->perf_stats
.large_send_bytes
>> 10,
224 card
->perf_stats
.large_send_cnt
);
225 seq_printf(s
, " Packing state changes no pkg.->packing : %u/%u\n"
226 " Watermarks L/H : %i/%i\n"
227 " Current buffer usage (outbound q's) : "
229 card
->perf_stats
.sc_dp_p
, card
->perf_stats
.sc_p_dp
,
230 QETH_LOW_WATERMARK_PACK
, QETH_HIGH_WATERMARK_PACK
,
231 atomic_read(&card
->qdio
.out_qs
[0]->used_buffers
),
232 (card
->qdio
.no_out_queues
> 1)?
233 atomic_read(&card
->qdio
.out_qs
[1]->used_buffers
)
235 (card
->qdio
.no_out_queues
> 2)?
236 atomic_read(&card
->qdio
.out_qs
[2]->used_buffers
)
238 (card
->qdio
.no_out_queues
> 3)?
239 atomic_read(&card
->qdio
.out_qs
[3]->used_buffers
)
242 seq_printf(s
, " Inbound handler time (in us) : %u\n"
243 " Inbound handler count : %u\n"
244 " Inbound do_QDIO time (in us) : %u\n"
245 " Inbound do_QDIO count : %u\n\n"
246 " Outbound handler time (in us) : %u\n"
247 " Outbound handler count : %u\n\n"
248 " Outbound time (in us, incl QDIO) : %u\n"
249 " Outbound count : %u\n"
250 " Outbound do_QDIO time (in us) : %u\n"
251 " Outbound do_QDIO count : %u\n\n",
252 card
->perf_stats
.inbound_time
,
253 card
->perf_stats
.inbound_cnt
,
254 card
->perf_stats
.inbound_do_qdio_time
,
255 card
->perf_stats
.inbound_do_qdio_cnt
,
256 card
->perf_stats
.outbound_handler_time
,
257 card
->perf_stats
.outbound_handler_cnt
,
258 card
->perf_stats
.outbound_time
,
259 card
->perf_stats
.outbound_cnt
,
260 card
->perf_stats
.outbound_do_qdio_time
,
261 card
->perf_stats
.outbound_do_qdio_cnt
267 static struct seq_operations qeth_perf_procfile_seq_ops
= {
268 .start
= qeth_procfile_seq_start
,
269 .stop
= qeth_procfile_seq_stop
,
270 .next
= qeth_procfile_seq_next
,
271 .show
= qeth_perf_procfile_seq_show
,
275 qeth_perf_procfile_open(struct inode
*inode
, struct file
*file
)
277 return seq_open(file
, &qeth_perf_procfile_seq_ops
);
280 static const struct file_operations qeth_perf_procfile_fops
= {
281 .owner
= THIS_MODULE
,
282 .open
= qeth_perf_procfile_open
,
285 .release
= seq_release
,
289 qeth_create_procfs_entries(void)
291 qeth_procfile
= create_proc_entry(QETH_PROCFILE_NAME
,
292 S_IFREG
| 0444, NULL
);
294 qeth_procfile
->proc_fops
= &qeth_procfile_fops
;
296 qeth_perf_procfile
= create_proc_entry(QETH_PERF_PROCFILE_NAME
,
297 S_IFREG
| 0444, NULL
);
298 if (qeth_perf_procfile
)
299 qeth_perf_procfile
->proc_fops
= &qeth_perf_procfile_fops
;
309 qeth_remove_procfs_entries(void)
312 remove_proc_entry(QETH_PROCFILE_NAME
, NULL
);
313 if (qeth_perf_procfile
)
314 remove_proc_entry(QETH_PERF_PROCFILE_NAME
, NULL
);