2005-04-16 15:20:36 -07:00
/*
*
2006-02-01 03:06:31 -08:00
* linux / drivers / s390 / net / qeth_fs . c
2005-04-16 15:20:36 -07:00
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to procfs .
*
* Copyright 2000 , 2003 IBM Corporation
*
* Author ( s ) : Thomas Spatzier < tspat @ de . ibm . com >
*
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/proc_fs.h>
# include <linux/seq_file.h>
# include <linux/list.h>
# include <linux/rwsem.h>
# include "qeth.h"
# include "qeth_mpc.h"
# include "qeth_fs.h"
/***** /proc/qeth *****/
# define QETH_PROCFILE_NAME "qeth"
static struct proc_dir_entry * qeth_procfile ;
2005-08-08 09:22:36 -07:00
static int
qeth_procfile_seq_match ( struct device * dev , void * data )
{
2005-12-13 08:23:26 +01:00
return ( dev ? 1 : 0 ) ;
2005-08-08 09:22:36 -07:00
}
2005-04-16 15:20:36 -07:00
static void *
qeth_procfile_seq_start ( struct seq_file * s , loff_t * offset )
{
2005-12-13 08:23:26 +01:00
struct device * dev = NULL ;
loff_t nr = 0 ;
2006-05-26 21:58:38 -04:00
2005-12-13 08:23:26 +01:00
if ( * offset = = 0 )
2005-04-16 15:20:36 -07:00
return SEQ_START_TOKEN ;
2005-12-13 08:23:26 +01:00
while ( 1 ) {
2005-08-08 09:22:36 -07:00
dev = driver_find_device ( & qeth_ccwgroup_driver . driver , dev ,
NULL , qeth_procfile_seq_match ) ;
2005-12-13 08:23:26 +01:00
if ( + + nr = = * offset )
break ;
put_device ( dev ) ;
}
return dev ;
2005-04-16 15:20:36 -07:00
}
static void
qeth_procfile_seq_stop ( struct seq_file * s , void * it )
{
}
static void *
qeth_procfile_seq_next ( struct seq_file * s , void * it , loff_t * offset )
{
2005-08-08 09:22:36 -07:00
struct device * prev , * next ;
2006-05-26 21:58:38 -04:00
if ( it = = SEQ_START_TOKEN )
2005-12-13 08:23:26 +01:00
prev = NULL ;
else
prev = ( struct device * ) it ;
2005-08-08 09:22:36 -07:00
next = driver_find_device ( & qeth_ccwgroup_driver . driver ,
prev , NULL , qeth_procfile_seq_match ) ;
2005-12-13 08:23:26 +01:00
( * offset ) + + ;
2005-08-08 09:22:36 -07:00
return ( void * ) next ;
2005-04-16 15:20:36 -07:00
}
static inline const char *
qeth_get_router_str ( struct qeth_card * card , int ipv )
{
2006-03-22 16:03:41 +01:00
enum qeth_routing_types routing_type = NO_ROUTER ;
2005-04-16 15:20:36 -07:00
2005-12-13 08:23:26 +01:00
if ( ipv = = 4 ) {
2005-04-16 15:20:36 -07:00
routing_type = card - > options . route4 . type ;
} else {
# ifdef CONFIG_QETH_IPV6
routing_type = card - > options . route6 . type ;
# else
return " n/a " ;
# endif /* CONFIG_QETH_IPV6 */
}
2006-03-22 16:03:41 +01:00
switch ( routing_type ) {
case PRIMARY_ROUTER :
2005-04-16 15:20:36 -07:00
return " pri " ;
2006-03-22 16:03:41 +01:00
case SECONDARY_ROUTER :
2005-04-16 15:20:36 -07:00
return " sec " ;
2006-03-22 16:03:41 +01:00
case MULTICAST_ROUTER :
2005-04-16 15:20:36 -07:00
if ( card - > info . broadcast_capable = = QETH_BROADCAST_WITHOUT_ECHO )
return " mc+ " ;
return " mc " ;
2006-03-22 16:03:41 +01:00
case PRIMARY_CONNECTOR :
2005-04-16 15:20:36 -07:00
if ( card - > info . broadcast_capable = = QETH_BROADCAST_WITHOUT_ECHO )
return " p+c " ;
return " p.c " ;
2006-03-22 16:03:41 +01:00
case SECONDARY_CONNECTOR :
2005-04-16 15:20:36 -07:00
if ( card - > info . broadcast_capable = = QETH_BROADCAST_WITHOUT_ECHO )
return " s+c " ;
return " s.c " ;
2006-03-22 16:03:41 +01:00
default : /* NO_ROUTER */
2005-04-16 15:20:36 -07:00
return " no " ;
2006-03-22 16:03:41 +01:00
}
2005-04-16 15:20:36 -07:00
}
static int
qeth_procfile_seq_show ( struct seq_file * s , void * it )
{
struct device * device ;
struct qeth_card * card ;
char tmp [ 12 ] ; /* for qeth_get_prioq_str */
if ( it = = SEQ_START_TOKEN ) {
seq_printf ( s , " devices CHPID interface "
" cardtype port chksum prio-q'ing rtr4 "
" rtr6 fsz cnt \n " ) ;
seq_printf ( s , " -------------------------- ----- ---------- "
" -------------- ---- ------ ---------- ---- "
" ---- ----- ----- \n " ) ;
} else {
2005-08-08 09:22:36 -07:00
device = ( struct device * ) it ;
2005-04-16 15:20:36 -07:00
card = device - > driver_data ;
seq_printf ( s , " %s/%s/%s x%02X %-10s %-14s %-4i " ,
CARD_RDEV_ID ( card ) ,
CARD_WDEV_ID ( card ) ,
CARD_DDEV_ID ( card ) ,
card - > info . chpid ,
QETH_CARD_IFNAME ( card ) ,
qeth_get_cardname_short ( card ) ,
card - > info . portno ) ;
if ( card - > lan_online )
seq_printf ( s , " %-6s %-10s %-4s %-4s %-5s %-5i \n " ,
qeth_get_checksum_str ( card ) ,
qeth_get_prioq_str ( card , tmp ) ,
qeth_get_router_str ( card , 4 ) ,
qeth_get_router_str ( card , 6 ) ,
qeth_get_bufsize_str ( card ) ,
card - > qdio . in_buf_pool . buf_count ) ;
else
seq_printf ( s , " +++ LAN OFFLINE +++ \n " ) ;
2005-12-13 08:23:26 +01:00
put_device ( device ) ;
2005-04-16 15:20:36 -07:00
}
return 0 ;
}
static struct seq_operations qeth_procfile_seq_ops = {
. start = qeth_procfile_seq_start ,
. stop = qeth_procfile_seq_stop ,
. next = qeth_procfile_seq_next ,
. show = qeth_procfile_seq_show ,
} ;
static int
qeth_procfile_open ( struct inode * inode , struct file * file )
{
return seq_open ( file , & qeth_procfile_seq_ops ) ;
}
2007-02-12 00:55:34 -08:00
static const struct file_operations qeth_procfile_fops = {
2005-04-16 15:20:36 -07:00
. owner = THIS_MODULE ,
. open = qeth_procfile_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = seq_release ,
} ;
/***** /proc/qeth_perf *****/
# define QETH_PERF_PROCFILE_NAME "qeth_perf"
static struct proc_dir_entry * qeth_perf_procfile ;
static int
qeth_perf_procfile_seq_show ( struct seq_file * s , void * it )
{
struct device * device ;
struct qeth_card * card ;
2006-05-26 21:58:38 -04:00
2005-12-13 08:23:26 +01:00
if ( it = = SEQ_START_TOKEN )
return 0 ;
2005-08-08 09:22:36 -07:00
device = ( struct device * ) it ;
2005-04-16 15:20:36 -07:00
card = device - > driver_data ;
seq_printf ( s , " For card with devnos %s/%s/%s (%s): \n " ,
CARD_RDEV_ID ( card ) ,
CARD_WDEV_ID ( card ) ,
CARD_DDEV_ID ( card ) ,
QETH_CARD_IFNAME ( card )
) ;
2006-09-15 16:26:34 +02:00
if ( ! card - > options . performance_stats )
seq_printf ( s , " Performance statistics are deactivated. \n " ) ;
2006-03-22 16:03:39 +01:00
seq_printf ( s , " Skb's/buffers received : %lu/%u \n "
" Skb's/buffers sent : %lu/%u \n \n " ,
2006-09-15 16:26:34 +02:00
card - > stats . rx_packets -
card - > perf_stats . initial_rx_packets ,
card - > perf_stats . bufs_rec ,
card - > stats . tx_packets -
card - > perf_stats . initial_tx_packets ,
card - > perf_stats . bufs_sent
2005-04-16 15:20:36 -07:00
) ;
2006-03-22 16:03:39 +01:00
seq_printf ( s , " Skb's/buffers sent without packing : %lu/%u \n "
" Skb's/buffers sent with packing : %u/%u \n \n " ,
2006-09-15 16:26:34 +02:00
card - > stats . tx_packets - card - > perf_stats . initial_tx_packets
- card - > perf_stats . skbs_sent_pack ,
2005-04-16 15:20:36 -07:00
card - > perf_stats . bufs_sent - card - > perf_stats . bufs_sent_pack ,
card - > perf_stats . skbs_sent_pack ,
card - > perf_stats . bufs_sent_pack
) ;
2006-03-22 16:03:39 +01:00
seq_printf ( s , " Skbs sent in SG mode : %u \n "
" Skb fragments sent in SG mode : %u \n \n " ,
2005-04-16 15:20:36 -07:00
card - > perf_stats . sg_skbs_sent ,
card - > perf_stats . sg_frags_sent ) ;
2007-07-12 12:51:34 +02:00
seq_printf ( s , " Skbs received in SG mode : %u \n "
" Skb fragments received in SG mode : %u \n "
" Page allocations for rx SG mode : %u \n \n " ,
card - > perf_stats . sg_skbs_rx ,
card - > perf_stats . sg_frags_rx ,
card - > perf_stats . sg_alloc_page_rx ) ;
2006-03-22 16:03:39 +01:00
seq_printf ( s , " large_send tx (in Kbytes) : %u \n "
" large_send count : %u \n \n " ,
2005-04-16 15:20:36 -07:00
card - > perf_stats . large_send_bytes > > 10 ,
card - > perf_stats . large_send_cnt ) ;
2006-03-22 16:03:39 +01:00
seq_printf ( s , " Packing state changes no pkg.->packing : %u/%u \n "
2005-04-16 15:20:36 -07:00
" Watermarks L/H : %i/%i \n "
" Current buffer usage (outbound q's) : "
" %i/%i/%i/%i \n \n " ,
card - > perf_stats . sc_dp_p , card - > perf_stats . sc_p_dp ,
QETH_LOW_WATERMARK_PACK , QETH_HIGH_WATERMARK_PACK ,
atomic_read ( & card - > qdio . out_qs [ 0 ] - > used_buffers ) ,
( card - > qdio . no_out_queues > 1 ) ?
atomic_read ( & card - > qdio . out_qs [ 1 ] - > used_buffers )
: 0 ,
( card - > qdio . no_out_queues > 2 ) ?
atomic_read ( & card - > qdio . out_qs [ 2 ] - > used_buffers )
: 0 ,
( card - > qdio . no_out_queues > 3 ) ?
atomic_read ( & card - > qdio . out_qs [ 3 ] - > used_buffers )
: 0
) ;
2006-03-22 16:03:39 +01:00
seq_printf ( s , " Inbound handler time (in us) : %u \n "
" Inbound handler count : %u \n "
" Inbound do_QDIO time (in us) : %u \n "
" Inbound do_QDIO count : %u \n \n "
" Outbound handler time (in us) : %u \n "
" Outbound handler count : %u \n \n "
" Outbound time (in us, incl QDIO) : %u \n "
" Outbound count : %u \n "
" Outbound do_QDIO time (in us) : %u \n "
" Outbound do_QDIO count : %u \n \n " ,
2005-04-16 15:20:36 -07:00
card - > perf_stats . inbound_time ,
card - > perf_stats . inbound_cnt ,
card - > perf_stats . inbound_do_qdio_time ,
card - > perf_stats . inbound_do_qdio_cnt ,
card - > perf_stats . outbound_handler_time ,
card - > perf_stats . outbound_handler_cnt ,
card - > perf_stats . outbound_time ,
card - > perf_stats . outbound_cnt ,
card - > perf_stats . outbound_do_qdio_time ,
card - > perf_stats . outbound_do_qdio_cnt
) ;
2005-12-13 08:23:26 +01:00
put_device ( device ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
static struct seq_operations qeth_perf_procfile_seq_ops = {
2005-12-13 08:23:26 +01:00
. start = qeth_procfile_seq_start ,
. stop = qeth_procfile_seq_stop ,
. next = qeth_procfile_seq_next ,
2005-04-16 15:20:36 -07:00
. show = qeth_perf_procfile_seq_show ,
} ;
static int
qeth_perf_procfile_open ( struct inode * inode , struct file * file )
{
return seq_open ( file , & qeth_perf_procfile_seq_ops ) ;
}
2007-02-12 00:55:34 -08:00
static const struct file_operations qeth_perf_procfile_fops = {
2005-04-16 15:20:36 -07:00
. owner = THIS_MODULE ,
. open = qeth_perf_procfile_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = seq_release ,
} ;
int __init
qeth_create_procfs_entries ( void )
{
qeth_procfile = create_proc_entry ( QETH_PROCFILE_NAME ,
S_IFREG | 0444 , NULL ) ;
if ( qeth_procfile )
qeth_procfile - > proc_fops = & qeth_procfile_fops ;
qeth_perf_procfile = create_proc_entry ( QETH_PERF_PROCFILE_NAME ,
S_IFREG | 0444 , NULL ) ;
if ( qeth_perf_procfile )
qeth_perf_procfile - > proc_fops = & qeth_perf_procfile_fops ;
if ( qeth_procfile & &
2006-09-15 16:26:34 +02:00
qeth_perf_procfile )
2005-04-16 15:20:36 -07:00
return 0 ;
else
return - ENOMEM ;
}
void __exit
qeth_remove_procfs_entries ( void )
{
if ( qeth_procfile )
remove_proc_entry ( QETH_PROCFILE_NAME , NULL ) ;
if ( qeth_perf_procfile )
remove_proc_entry ( QETH_PERF_PROCFILE_NAME , NULL ) ;
}