2005-04-17 02:20:36 +04:00
/*
*
2006-02-01 14:06:31 +03:00
* linux / drivers / s390 / net / qeth_sys . c
2005-04-17 02:20:36 +04:00
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs .
*
* Copyright 2000 , 2003 IBM Corporation
*
* Author ( s ) : Thomas Spatzier < tspat @ de . ibm . com >
2005-11-10 15:51:42 +03:00
* Frank Pavlic < fpavlic @ de . ibm . com >
2005-04-17 02:20:36 +04:00
*
*/
# include <linux/list.h>
# include <linux/rwsem.h>
# include <asm/ebcdic.h>
# include "qeth.h"
# include "qeth_mpc.h"
# include "qeth_fs.h"
/*****************************************************************************/
/* */
/* /sys-fs stuff UNDER DEVELOPMENT !!! */
/* */
/*****************************************************************************/
//low/high watermark
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_state_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
switch ( card - > state ) {
case CARD_STATE_DOWN :
return sprintf ( buf , " DOWN \n " ) ;
case CARD_STATE_HARDSETUP :
return sprintf ( buf , " HARDSETUP \n " ) ;
case CARD_STATE_SOFTSETUP :
return sprintf ( buf , " SOFTSETUP \n " ) ;
case CARD_STATE_UP :
if ( card - > lan_online )
return sprintf ( buf , " UP (LAN ONLINE) \ n " ) ;
else
return sprintf ( buf , " UP (LAN OFFLINE) \ n " ) ;
case CARD_STATE_RECOVER :
return sprintf ( buf , " RECOVER \n " ) ;
default :
return sprintf ( buf , " UNKNOWN \n " ) ;
}
}
static DEVICE_ATTR ( state , 0444 , qeth_dev_state_show , NULL ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_chpid_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %02X \n " , card - > info . chpid ) ;
}
static DEVICE_ATTR ( chpid , 0444 , qeth_dev_chpid_show , NULL ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_if_name_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %s \n " , QETH_CARD_IFNAME ( card ) ) ;
}
static DEVICE_ATTR ( if_name , 0444 , qeth_dev_if_name_show , NULL ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_card_type_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %s \n " , qeth_get_cardname_short ( card ) ) ;
}
static DEVICE_ATTR ( card_type , 0444 , qeth_dev_card_type_show , NULL ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_portno_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %i \n " , card - > info . portno ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_portno_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
unsigned int portno ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
portno = simple_strtoul ( buf , & tmp , 16 ) ;
2006-03-22 18:03:41 +03:00
if ( portno > MAX_PORTNO ) {
2005-04-17 02:20:36 +04:00
PRINT_WARN ( " portno 0x%X is out of range \n " , portno ) ;
return - EINVAL ;
}
card - > info . portno = portno ;
return count ;
}
static DEVICE_ATTR ( portno , 0644 , qeth_dev_portno_show , qeth_dev_portno_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_portname_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char portname [ 9 ] = { 0 , } ;
if ( ! card )
return - EINVAL ;
if ( card - > info . portname_required ) {
memcpy ( portname , card - > info . portname + 1 , 8 ) ;
EBCASC ( portname , 8 ) ;
return sprintf ( buf , " %s \n " , portname ) ;
} else
return sprintf ( buf , " no portname required \n " ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_portname_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
int i ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
tmp = strsep ( ( char * * ) & buf , " \n " ) ;
2005-12-13 10:21:47 +03:00
if ( ( strlen ( tmp ) > 8 ) | | ( strlen ( tmp ) = = 0 ) )
2005-04-17 02:20:36 +04:00
return - EINVAL ;
card - > info . portname [ 0 ] = strlen ( tmp ) ;
/* for beauty reasons */
for ( i = 1 ; i < 9 ; i + + )
card - > info . portname [ i ] = ' ' ;
strcpy ( card - > info . portname + 1 , tmp ) ;
ASCEBC ( card - > info . portname + 1 , 8 ) ;
return count ;
}
static DEVICE_ATTR ( portname , 0644 , qeth_dev_portname_show ,
qeth_dev_portname_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_checksum_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %s checksumming \n " , qeth_get_checksum_str ( card ) ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_checksum_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
tmp = strsep ( ( char * * ) & buf , " \n " ) ;
if ( ! strcmp ( tmp , " sw_checksumming " ) )
card - > options . checksum_type = SW_CHECKSUMMING ;
else if ( ! strcmp ( tmp , " hw_checksumming " ) )
card - > options . checksum_type = HW_CHECKSUMMING ;
else if ( ! strcmp ( tmp , " no_checksumming " ) )
card - > options . checksum_type = NO_CHECKSUMMING ;
else {
PRINT_WARN ( " Unknown checksumming type '%s' \n " , tmp ) ;
return - EINVAL ;
}
return count ;
}
static DEVICE_ATTR ( checksumming , 0644 , qeth_dev_checksum_show ,
qeth_dev_checksum_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_prioqing_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
switch ( card - > qdio . do_prio_queueing ) {
case QETH_PRIO_Q_ING_PREC :
return sprintf ( buf , " %s \n " , " by precedence " ) ;
case QETH_PRIO_Q_ING_TOS :
return sprintf ( buf , " %s \n " , " by type of service " ) ;
default :
return sprintf ( buf , " always queue %i \n " ,
card - > qdio . default_out_queue ) ;
}
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_prioqing_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
/* check if 1920 devices are supported ,
* if though we have to permit priority queueing
*/
if ( card - > qdio . no_out_queues = = 1 ) {
PRINT_WARN ( " Priority queueing disabled due "
" to hardware limitations! \n " ) ;
card - > qdio . do_prio_queueing = QETH_PRIOQ_DEFAULT ;
return - EPERM ;
}
tmp = strsep ( ( char * * ) & buf , " \n " ) ;
if ( ! strcmp ( tmp , " prio_queueing_prec " ) )
card - > qdio . do_prio_queueing = QETH_PRIO_Q_ING_PREC ;
else if ( ! strcmp ( tmp , " prio_queueing_tos " ) )
card - > qdio . do_prio_queueing = QETH_PRIO_Q_ING_TOS ;
else if ( ! strcmp ( tmp , " no_prio_queueing:0 " ) ) {
card - > qdio . do_prio_queueing = QETH_NO_PRIO_QUEUEING ;
card - > qdio . default_out_queue = 0 ;
} else if ( ! strcmp ( tmp , " no_prio_queueing:1 " ) ) {
card - > qdio . do_prio_queueing = QETH_NO_PRIO_QUEUEING ;
card - > qdio . default_out_queue = 1 ;
} else if ( ! strcmp ( tmp , " no_prio_queueing:2 " ) ) {
card - > qdio . do_prio_queueing = QETH_NO_PRIO_QUEUEING ;
card - > qdio . default_out_queue = 2 ;
} else if ( ! strcmp ( tmp , " no_prio_queueing:3 " ) ) {
card - > qdio . do_prio_queueing = QETH_NO_PRIO_QUEUEING ;
card - > qdio . default_out_queue = 3 ;
} else if ( ! strcmp ( tmp , " no_prio_queueing " ) ) {
card - > qdio . do_prio_queueing = QETH_NO_PRIO_QUEUEING ;
card - > qdio . default_out_queue = QETH_DEFAULT_QUEUE ;
} else {
PRINT_WARN ( " Unknown queueing type '%s' \n " , tmp ) ;
return - EINVAL ;
}
return count ;
}
static DEVICE_ATTR ( priority_queueing , 0644 , qeth_dev_prioqing_show ,
qeth_dev_prioqing_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_bufcnt_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %i \n " , card - > qdio . in_buf_pool . buf_count ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_bufcnt_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
int cnt , old_cnt ;
int rc ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
old_cnt = card - > qdio . in_buf_pool . buf_count ;
cnt = simple_strtoul ( buf , & tmp , 10 ) ;
cnt = ( cnt < QETH_IN_BUF_COUNT_MIN ) ? QETH_IN_BUF_COUNT_MIN :
( ( cnt > QETH_IN_BUF_COUNT_MAX ) ? QETH_IN_BUF_COUNT_MAX : cnt ) ;
if ( old_cnt ! = cnt ) {
if ( ( rc = qeth_realloc_buffer_pool ( card , cnt ) ) )
PRINT_WARN ( " Error (%d) while setting "
" buffer count. \n " , rc ) ;
}
return count ;
}
static DEVICE_ATTR ( buffer_count , 0644 , qeth_dev_bufcnt_show ,
qeth_dev_bufcnt_store ) ;
2007-02-05 23:18:53 +03:00
static ssize_t
2005-04-17 02:20:36 +04:00
qeth_dev_route_show ( struct qeth_card * card , struct qeth_routing_info * route ,
char * buf )
{
switch ( route - > type ) {
case PRIMARY_ROUTER :
return sprintf ( buf , " %s \n " , " primary router " ) ;
case SECONDARY_ROUTER :
return sprintf ( buf , " %s \n " , " secondary router " ) ;
case MULTICAST_ROUTER :
if ( card - > info . broadcast_capable = = QETH_BROADCAST_WITHOUT_ECHO )
return sprintf ( buf , " %s \n " , " multicast router+ " ) ;
else
return sprintf ( buf , " %s \n " , " multicast router " ) ;
case PRIMARY_CONNECTOR :
if ( card - > info . broadcast_capable = = QETH_BROADCAST_WITHOUT_ECHO )
return sprintf ( buf , " %s \n " , " primary connector+ " ) ;
else
return sprintf ( buf , " %s \n " , " primary connector " ) ;
case SECONDARY_CONNECTOR :
if ( card - > info . broadcast_capable = = QETH_BROADCAST_WITHOUT_ECHO )
return sprintf ( buf , " %s \n " , " secondary connector+ " ) ;
else
return sprintf ( buf , " %s \n " , " secondary connector " ) ;
default :
return sprintf ( buf , " %s \n " , " no " ) ;
}
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_route4_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_route_show ( card , & card - > options . route4 , buf ) ;
}
2007-02-05 23:18:53 +03:00
static ssize_t
2005-04-17 02:20:36 +04:00
qeth_dev_route_store ( struct qeth_card * card , struct qeth_routing_info * route ,
enum qeth_prot_versions prot , const char * buf , size_t count )
{
enum qeth_routing_types old_route_type = route - > type ;
char * tmp ;
int rc ;
tmp = strsep ( ( char * * ) & buf , " \n " ) ;
if ( ! strcmp ( tmp , " no_router " ) ) {
route - > type = NO_ROUTER ;
} else if ( ! strcmp ( tmp , " primary_connector " ) ) {
route - > type = PRIMARY_CONNECTOR ;
} else if ( ! strcmp ( tmp , " secondary_connector " ) ) {
route - > type = SECONDARY_CONNECTOR ;
} else if ( ! strcmp ( tmp , " primary_router " ) ) {
route - > type = PRIMARY_ROUTER ;
} else if ( ! strcmp ( tmp , " secondary_router " ) ) {
route - > type = SECONDARY_ROUTER ;
} else if ( ! strcmp ( tmp , " multicast_router " ) ) {
route - > type = MULTICAST_ROUTER ;
} else {
PRINT_WARN ( " Invalid routing type '%s'. \n " , tmp ) ;
return - EINVAL ;
}
if ( ( ( card - > state = = CARD_STATE_SOFTSETUP ) | |
( card - > state = = CARD_STATE_UP ) ) & &
( old_route_type ! = route - > type ) ) {
if ( prot = = QETH_PROT_IPV4 )
rc = qeth_setrouting_v4 ( card ) ;
else if ( prot = = QETH_PROT_IPV6 )
rc = qeth_setrouting_v6 ( card ) ;
}
return count ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_route4_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_route_store ( card , & card - > options . route4 ,
QETH_PROT_IPV4 , buf , count ) ;
}
static DEVICE_ATTR ( route4 , 0644 , qeth_dev_route4_show , qeth_dev_route4_store ) ;
# ifdef CONFIG_QETH_IPV6
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_route6_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
if ( ! qeth_is_supported ( card , IPA_IPV6 ) )
return sprintf ( buf , " %s \n " , " n/a " ) ;
return qeth_dev_route_show ( card , & card - > options . route6 , buf ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_route6_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
if ( ! qeth_is_supported ( card , IPA_IPV6 ) ) {
PRINT_WARN ( " IPv6 not supported for interface %s. \n "
" Routing status no changed. \n " ,
QETH_CARD_IFNAME ( card ) ) ;
return - ENOTSUPP ;
}
return qeth_dev_route_store ( card , & card - > options . route6 ,
QETH_PROT_IPV6 , buf , count ) ;
}
static DEVICE_ATTR ( route6 , 0644 , qeth_dev_route6_show , qeth_dev_route6_store ) ;
# endif
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_add_hhlen_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %i \n " , card - > options . add_hhlen ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_add_hhlen_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
int i ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
i = simple_strtoul ( buf , & tmp , 10 ) ;
if ( ( i < 0 ) | | ( i > MAX_ADD_HHLEN ) ) {
PRINT_WARN ( " add_hhlen out of range \n " ) ;
return - EINVAL ;
}
card - > options . add_hhlen = i ;
return count ;
}
static DEVICE_ATTR ( add_hhlen , 0644 , qeth_dev_add_hhlen_show ,
qeth_dev_add_hhlen_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_fake_ll_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %i \n " , card - > options . fake_ll ? 1 : 0 ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_fake_ll_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
int i ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
i = simple_strtoul ( buf , & tmp , 16 ) ;
if ( ( i ! = 0 ) & & ( i ! = 1 ) ) {
PRINT_WARN ( " fake_ll: write 0 or 1 to this file! \n " ) ;
return - EINVAL ;
}
card - > options . fake_ll = i ;
return count ;
}
static DEVICE_ATTR ( fake_ll , 0644 , qeth_dev_fake_ll_show ,
qeth_dev_fake_ll_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_fake_broadcast_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %i \n " , card - > options . fake_broadcast ? 1 : 0 ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_fake_broadcast_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
int i ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
i = simple_strtoul ( buf , & tmp , 16 ) ;
if ( ( i = = 0 ) | | ( i = = 1 ) )
card - > options . fake_broadcast = i ;
else {
PRINT_WARN ( " fake_broadcast: write 0 or 1 to this file! \n " ) ;
return - EINVAL ;
}
return count ;
}
static DEVICE_ATTR ( fake_broadcast , 0644 , qeth_dev_fake_broadcast_show ,
qeth_dev_fake_broadcast_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_recover_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
int i ;
if ( ! card )
return - EINVAL ;
if ( card - > state ! = CARD_STATE_UP )
return - EPERM ;
i = simple_strtoul ( buf , & tmp , 16 ) ;
if ( i = = 1 )
qeth_schedule_recovery ( card ) ;
return count ;
}
static DEVICE_ATTR ( recover , 0200 , NULL , qeth_dev_recover_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_broadcast_mode_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
if ( ! ( ( card - > info . link_type = = QETH_LINK_TYPE_HSTR ) | |
( card - > info . link_type = = QETH_LINK_TYPE_LANE_TR ) ) )
return sprintf ( buf , " n/a \n " ) ;
return sprintf ( buf , " %s \n " , ( card - > options . broadcast_mode = =
QETH_TR_BROADCAST_ALLRINGS ) ?
" all rings " : " local " ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_broadcast_mode_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
if ( ! ( ( card - > info . link_type = = QETH_LINK_TYPE_HSTR ) | |
( card - > info . link_type = = QETH_LINK_TYPE_LANE_TR ) ) ) {
PRINT_WARN ( " Device is not a tokenring device! \n " ) ;
return - EINVAL ;
}
tmp = strsep ( ( char * * ) & buf , " \n " ) ;
if ( ! strcmp ( tmp , " local " ) ) {
card - > options . broadcast_mode = QETH_TR_BROADCAST_LOCAL ;
return count ;
} else if ( ! strcmp ( tmp , " all_rings " ) ) {
card - > options . broadcast_mode = QETH_TR_BROADCAST_ALLRINGS ;
return count ;
} else {
PRINT_WARN ( " broadcast_mode: invalid mode %s! \n " ,
tmp ) ;
return - EINVAL ;
}
return count ;
}
static DEVICE_ATTR ( broadcast_mode , 0644 , qeth_dev_broadcast_mode_show ,
qeth_dev_broadcast_mode_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_canonical_macaddr_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
if ( ! ( ( card - > info . link_type = = QETH_LINK_TYPE_HSTR ) | |
( card - > info . link_type = = QETH_LINK_TYPE_LANE_TR ) ) )
return sprintf ( buf , " n/a \n " ) ;
return sprintf ( buf , " %i \n " , ( card - > options . macaddr_mode = =
QETH_TR_MACADDR_CANONICAL ) ? 1 : 0 ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_canonical_macaddr_store ( struct device * dev , struct device_attribute * attr , const char * buf ,
2005-04-17 02:20:36 +04:00
size_t count )
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
int i ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
if ( ! ( ( card - > info . link_type = = QETH_LINK_TYPE_HSTR ) | |
( card - > info . link_type = = QETH_LINK_TYPE_LANE_TR ) ) ) {
PRINT_WARN ( " Device is not a tokenring device! \n " ) ;
return - EINVAL ;
}
i = simple_strtoul ( buf , & tmp , 16 ) ;
if ( ( i = = 0 ) | | ( i = = 1 ) )
card - > options . macaddr_mode = i ?
QETH_TR_MACADDR_CANONICAL :
QETH_TR_MACADDR_NONCANONICAL ;
else {
PRINT_WARN ( " canonical_macaddr: write 0 or 1 to this file! \n " ) ;
return - EINVAL ;
}
return count ;
}
static DEVICE_ATTR ( canonical_macaddr , 0644 , qeth_dev_canonical_macaddr_show ,
qeth_dev_canonical_macaddr_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_layer2_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %i \n " , card - > options . layer2 ? 1 : 0 ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_layer2_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
int i ;
if ( ! card )
return - EINVAL ;
2005-09-14 20:05:31 +04:00
if ( card - > info . type = = QETH_CARD_TYPE_IQD ) {
PRINT_WARN ( " Layer2 on Hipersockets is not supported! \n " ) ;
return - EPERM ;
}
2005-04-17 02:20:36 +04:00
if ( ( ( card - > state ! = CARD_STATE_DOWN ) & &
2005-09-14 20:05:31 +04:00
( card - > state ! = CARD_STATE_RECOVER ) ) )
2005-04-17 02:20:36 +04:00
return - EPERM ;
i = simple_strtoul ( buf , & tmp , 16 ) ;
if ( ( i = = 0 ) | | ( i = = 1 ) )
card - > options . layer2 = i ;
else {
PRINT_WARN ( " layer2: write 0 or 1 to this file! \n " ) ;
return - EINVAL ;
}
return count ;
}
static DEVICE_ATTR ( layer2 , 0644 , qeth_dev_layer2_show ,
qeth_dev_layer2_store ) ;
2006-09-15 18:26:34 +04:00
static ssize_t
qeth_dev_performance_stats_show ( struct device * dev , struct device_attribute * attr , char * buf )
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %i \n " , card - > options . performance_stats ? 1 : 0 ) ;
}
static ssize_t
qeth_dev_performance_stats_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
int i ;
if ( ! card )
return - EINVAL ;
i = simple_strtoul ( buf , & tmp , 16 ) ;
if ( ( i = = 0 ) | | ( i = = 1 ) ) {
if ( i = = card - > options . performance_stats )
return count ;
card - > options . performance_stats = i ;
if ( i = = 0 )
memset ( & card - > perf_stats , 0 ,
sizeof ( struct qeth_perf_stats ) ) ;
card - > perf_stats . initial_rx_packets = card - > stats . rx_packets ;
card - > perf_stats . initial_tx_packets = card - > stats . tx_packets ;
} else {
PRINT_WARN ( " performance_stats: write 0 or 1 to this file! \n " ) ;
return - EINVAL ;
}
return count ;
}
static DEVICE_ATTR ( performance_stats , 0644 , qeth_dev_performance_stats_show ,
qeth_dev_performance_stats_store ) ;
2005-04-17 02:20:36 +04:00
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_large_send_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
switch ( card - > options . large_send ) {
case QETH_LARGE_SEND_NO :
return sprintf ( buf , " %s \n " , " no " ) ;
case QETH_LARGE_SEND_EDDP :
return sprintf ( buf , " %s \n " , " EDDP " ) ;
case QETH_LARGE_SEND_TSO :
return sprintf ( buf , " %s \n " , " TSO " ) ;
default :
return sprintf ( buf , " %s \n " , " N/A " ) ;
}
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_large_send_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
enum qeth_large_send_types type ;
int rc = 0 ;
char * tmp ;
if ( ! card )
return - EINVAL ;
tmp = strsep ( ( char * * ) & buf , " \n " ) ;
if ( ! strcmp ( tmp , " no " ) ) {
type = QETH_LARGE_SEND_NO ;
} else if ( ! strcmp ( tmp , " EDDP " ) ) {
type = QETH_LARGE_SEND_EDDP ;
} else if ( ! strcmp ( tmp , " TSO " ) ) {
type = QETH_LARGE_SEND_TSO ;
} else {
PRINT_WARN ( " large_send: invalid mode %s! \n " , tmp ) ;
return - EINVAL ;
}
if ( card - > options . large_send = = type )
return count ;
2006-05-27 05:58:38 +04:00
if ( ( rc = qeth_set_large_send ( card , type ) ) )
2005-04-17 02:20:36 +04:00
return rc ;
return count ;
}
static DEVICE_ATTR ( large_send , 0644 , qeth_dev_large_send_show ,
qeth_dev_large_send_store ) ;
static ssize_t
qeth_dev_blkt_show ( char * buf , struct qeth_card * card , int value )
{
if ( ! card )
return - EINVAL ;
return sprintf ( buf , " %i \n " , value ) ;
}
static ssize_t
qeth_dev_blkt_store ( struct qeth_card * card , const char * buf , size_t count ,
int * value , int max_value )
{
char * tmp ;
int i ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
i = simple_strtoul ( buf , & tmp , 10 ) ;
if ( i < = max_value ) {
* value = i ;
} else {
PRINT_WARN ( " blkt total time: write values between "
" 0 and %d to this file! \n " , max_value ) ;
return - EINVAL ;
}
return count ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_blkt_total_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
return qeth_dev_blkt_show ( buf , card , card - > info . blkt . time_total ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_blkt_total_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
return qeth_dev_blkt_store ( card , buf , count ,
& card - > info . blkt . time_total , 1000 ) ;
}
static DEVICE_ATTR ( total , 0644 , qeth_dev_blkt_total_show ,
qeth_dev_blkt_total_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_blkt_inter_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
return qeth_dev_blkt_show ( buf , card , card - > info . blkt . inter_packet ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_blkt_inter_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
return qeth_dev_blkt_store ( card , buf , count ,
& card - > info . blkt . inter_packet , 100 ) ;
}
static DEVICE_ATTR ( inter , 0644 , qeth_dev_blkt_inter_show ,
qeth_dev_blkt_inter_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_blkt_inter_jumbo_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
return qeth_dev_blkt_show ( buf , card ,
card - > info . blkt . inter_packet_jumbo ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_blkt_inter_jumbo_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
return qeth_dev_blkt_store ( card , buf , count ,
& card - > info . blkt . inter_packet_jumbo , 100 ) ;
}
static DEVICE_ATTR ( inter_jumbo , 0644 , qeth_dev_blkt_inter_jumbo_show ,
qeth_dev_blkt_inter_jumbo_store ) ;
static struct device_attribute * qeth_blkt_device_attrs [ ] = {
& dev_attr_total ,
& dev_attr_inter ,
& dev_attr_inter_jumbo ,
NULL ,
} ;
static struct attribute_group qeth_device_blkt_group = {
. name = " blkt " ,
. attrs = ( struct attribute * * ) qeth_blkt_device_attrs ,
} ;
static struct device_attribute * qeth_device_attrs [ ] = {
& dev_attr_state ,
& dev_attr_chpid ,
& dev_attr_if_name ,
& dev_attr_card_type ,
& dev_attr_portno ,
& dev_attr_portname ,
& dev_attr_checksumming ,
& dev_attr_priority_queueing ,
& dev_attr_buffer_count ,
& dev_attr_route4 ,
# ifdef CONFIG_QETH_IPV6
& dev_attr_route6 ,
# endif
& dev_attr_add_hhlen ,
& dev_attr_fake_ll ,
& dev_attr_fake_broadcast ,
& dev_attr_recover ,
& dev_attr_broadcast_mode ,
& dev_attr_canonical_macaddr ,
& dev_attr_layer2 ,
& dev_attr_large_send ,
2006-09-15 18:26:34 +04:00
& dev_attr_performance_stats ,
2005-04-17 02:20:36 +04:00
NULL ,
} ;
static struct attribute_group qeth_device_attr_group = {
. attrs = ( struct attribute * * ) qeth_device_attrs ,
} ;
2005-09-30 12:19:19 +04:00
static struct device_attribute * qeth_osn_device_attrs [ ] = {
& dev_attr_state ,
& dev_attr_chpid ,
& dev_attr_if_name ,
& dev_attr_card_type ,
& dev_attr_buffer_count ,
& dev_attr_recover ,
NULL ,
} ;
static struct attribute_group qeth_osn_device_attr_group = {
. attrs = ( struct attribute * * ) qeth_osn_device_attrs ,
} ;
2005-04-17 02:20:36 +04:00
# define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \
struct device_attribute dev_attr_ # # _id = { \
2007-06-13 22:45:17 +04:00
. attr = { . name = __stringify ( _name ) , . mode = _mode , } , \
2005-04-17 02:20:36 +04:00
. show = _show , \
. store = _store , \
} ;
2007-02-05 23:16:47 +03:00
static int
2005-04-17 02:20:36 +04:00
qeth_check_layer2 ( struct qeth_card * card )
{
if ( card - > options . layer2 )
return - EPERM ;
return 0 ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_enable_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
return sprintf ( buf , " %i \n " , card - > ipato . enabled ? 1 : 0 ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_enable_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
if ( ! card )
return - EINVAL ;
if ( ( card - > state ! = CARD_STATE_DOWN ) & &
( card - > state ! = CARD_STATE_RECOVER ) )
return - EPERM ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
tmp = strsep ( ( char * * ) & buf , " \n " ) ;
if ( ! strcmp ( tmp , " toggle " ) ) {
card - > ipato . enabled = ( card - > ipato . enabled ) ? 0 : 1 ;
} else if ( ! strcmp ( tmp , " 1 " ) ) {
card - > ipato . enabled = 1 ;
} else if ( ! strcmp ( tmp , " 0 " ) ) {
card - > ipato . enabled = 0 ;
} else {
PRINT_WARN ( " ipato_enable: write 0, 1 or 'toggle' to "
" this file \n " ) ;
return - EINVAL ;
}
return count ;
}
static QETH_DEVICE_ATTR ( ipato_enable , enable , 0644 ,
qeth_dev_ipato_enable_show ,
qeth_dev_ipato_enable_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_invert4_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
return sprintf ( buf , " %i \n " , card - > ipato . invert4 ? 1 : 0 ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_invert4_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
if ( ! card )
return - EINVAL ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
tmp = strsep ( ( char * * ) & buf , " \n " ) ;
if ( ! strcmp ( tmp , " toggle " ) ) {
card - > ipato . invert4 = ( card - > ipato . invert4 ) ? 0 : 1 ;
} else if ( ! strcmp ( tmp , " 1 " ) ) {
card - > ipato . invert4 = 1 ;
} else if ( ! strcmp ( tmp , " 0 " ) ) {
card - > ipato . invert4 = 0 ;
} else {
PRINT_WARN ( " ipato_invert4: write 0, 1 or 'toggle' to "
" this file \n " ) ;
return - EINVAL ;
}
return count ;
}
static QETH_DEVICE_ATTR ( ipato_invert4 , invert4 , 0644 ,
qeth_dev_ipato_invert4_show ,
qeth_dev_ipato_invert4_store ) ;
2007-02-05 23:18:53 +03:00
static ssize_t
2005-04-17 02:20:36 +04:00
qeth_dev_ipato_add_show ( char * buf , struct qeth_card * card ,
enum qeth_prot_versions proto )
{
struct qeth_ipato_entry * ipatoe ;
unsigned long flags ;
char addr_str [ 40 ] ;
int entry_len ; /* length of 1 entry string, differs between v4 and v6 */
int i = 0 ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
entry_len = ( proto = = QETH_PROT_IPV4 ) ? 12 : 40 ;
/* add strlen for "/<mask>\n" */
entry_len + = ( proto = = QETH_PROT_IPV4 ) ? 5 : 6 ;
spin_lock_irqsave ( & card - > ip_lock , flags ) ;
list_for_each_entry ( ipatoe , & card - > ipato . entries , entry ) {
if ( ipatoe - > proto ! = proto )
continue ;
/* String must not be longer than PAGE_SIZE. So we check if
* string length gets near PAGE_SIZE . Then we can savely display
* the next IPv6 address ( worst case , compared to IPv4 ) */
if ( ( PAGE_SIZE - i ) < = entry_len )
break ;
qeth_ipaddr_to_string ( proto , ipatoe - > addr , addr_str ) ;
i + = snprintf ( buf + i , PAGE_SIZE - i ,
" %s/%i \n " , addr_str , ipatoe - > mask_bits ) ;
}
spin_unlock_irqrestore ( & card - > ip_lock , flags ) ;
i + = snprintf ( buf + i , PAGE_SIZE - i , " \n " ) ;
return i ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_add4_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_ipato_add_show ( buf , card , QETH_PROT_IPV4 ) ;
}
2007-02-05 23:18:53 +03:00
static int
2005-04-17 02:20:36 +04:00
qeth_parse_ipatoe ( const char * buf , enum qeth_prot_versions proto ,
u8 * addr , int * mask_bits )
{
const char * start , * end ;
char * tmp ;
2006-09-15 18:26:07 +04:00
char buffer [ 40 ] = { 0 , } ;
2005-04-17 02:20:36 +04:00
start = buf ;
/* get address string */
end = strchr ( start , ' / ' ) ;
2006-09-15 18:26:07 +04:00
if ( ! end | | ( end - start > = 40 ) ) {
2005-04-17 02:20:36 +04:00
PRINT_WARN ( " Invalid format for ipato_addx/delx. "
" Use <ip addr>/<mask bits> \n " ) ;
return - EINVAL ;
}
strncpy ( buffer , start , end - start ) ;
if ( qeth_string_to_ipaddr ( buffer , proto , addr ) ) {
PRINT_WARN ( " Invalid IP address format! \n " ) ;
return - EINVAL ;
}
start = end + 1 ;
* mask_bits = simple_strtoul ( start , & tmp , 10 ) ;
2006-09-15 18:26:07 +04:00
if ( ! strlen ( start ) | |
( tmp = = start ) | |
( * mask_bits > ( ( proto = = QETH_PROT_IPV4 ) ? 32 : 128 ) ) ) {
PRINT_WARN ( " Invalid mask bits for ipato_addx/delx ! \n " ) ;
return - EINVAL ;
}
2005-04-17 02:20:36 +04:00
return 0 ;
}
2007-02-05 23:18:53 +03:00
static ssize_t
2005-04-17 02:20:36 +04:00
qeth_dev_ipato_add_store ( const char * buf , size_t count ,
struct qeth_card * card , enum qeth_prot_versions proto )
{
struct qeth_ipato_entry * ipatoe ;
u8 addr [ 16 ] ;
int mask_bits ;
int rc ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
if ( ( rc = qeth_parse_ipatoe ( buf , proto , addr , & mask_bits ) ) )
return rc ;
2006-03-24 14:15:31 +03:00
if ( ! ( ipatoe = kzalloc ( sizeof ( struct qeth_ipato_entry ) , GFP_KERNEL ) ) ) {
2005-04-17 02:20:36 +04:00
PRINT_WARN ( " No memory to allocate ipato entry \n " ) ;
return - ENOMEM ;
}
ipatoe - > proto = proto ;
memcpy ( ipatoe - > addr , addr , ( proto = = QETH_PROT_IPV4 ) ? 4 : 16 ) ;
ipatoe - > mask_bits = mask_bits ;
if ( ( rc = qeth_add_ipato_entry ( card , ipatoe ) ) ) {
kfree ( ipatoe ) ;
return rc ;
}
return count ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_add4_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_ipato_add_store ( buf , count , card , QETH_PROT_IPV4 ) ;
}
static QETH_DEVICE_ATTR ( ipato_add4 , add4 , 0644 ,
qeth_dev_ipato_add4_show ,
qeth_dev_ipato_add4_store ) ;
2007-02-05 23:18:53 +03:00
static ssize_t
2005-04-17 02:20:36 +04:00
qeth_dev_ipato_del_store ( const char * buf , size_t count ,
struct qeth_card * card , enum qeth_prot_versions proto )
{
u8 addr [ 16 ] ;
int mask_bits ;
int rc ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
if ( ( rc = qeth_parse_ipatoe ( buf , proto , addr , & mask_bits ) ) )
return rc ;
qeth_del_ipato_entry ( card , proto , addr , mask_bits ) ;
return count ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_del4_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_ipato_del_store ( buf , count , card , QETH_PROT_IPV4 ) ;
}
static QETH_DEVICE_ATTR ( ipato_del4 , del4 , 0200 , NULL ,
qeth_dev_ipato_del4_store ) ;
# ifdef CONFIG_QETH_IPV6
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_invert6_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
return sprintf ( buf , " %i \n " , card - > ipato . invert6 ? 1 : 0 ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_invert6_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
char * tmp ;
if ( ! card )
return - EINVAL ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
tmp = strsep ( ( char * * ) & buf , " \n " ) ;
if ( ! strcmp ( tmp , " toggle " ) ) {
card - > ipato . invert6 = ( card - > ipato . invert6 ) ? 0 : 1 ;
} else if ( ! strcmp ( tmp , " 1 " ) ) {
card - > ipato . invert6 = 1 ;
} else if ( ! strcmp ( tmp , " 0 " ) ) {
card - > ipato . invert6 = 0 ;
} else {
PRINT_WARN ( " ipato_invert6: write 0, 1 or 'toggle' to "
" this file \n " ) ;
return - EINVAL ;
}
return count ;
}
static QETH_DEVICE_ATTR ( ipato_invert6 , invert6 , 0644 ,
qeth_dev_ipato_invert6_show ,
qeth_dev_ipato_invert6_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_add6_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_ipato_add_show ( buf , card , QETH_PROT_IPV6 ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_add6_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_ipato_add_store ( buf , count , card , QETH_PROT_IPV6 ) ;
}
static QETH_DEVICE_ATTR ( ipato_add6 , add6 , 0644 ,
qeth_dev_ipato_add6_show ,
qeth_dev_ipato_add6_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_ipato_del6_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_ipato_del_store ( buf , count , card , QETH_PROT_IPV6 ) ;
}
static QETH_DEVICE_ATTR ( ipato_del6 , del6 , 0200 , NULL ,
qeth_dev_ipato_del6_store ) ;
# endif /* CONFIG_QETH_IPV6 */
static struct device_attribute * qeth_ipato_device_attrs [ ] = {
& dev_attr_ipato_enable ,
& dev_attr_ipato_invert4 ,
& dev_attr_ipato_add4 ,
& dev_attr_ipato_del4 ,
# ifdef CONFIG_QETH_IPV6
& dev_attr_ipato_invert6 ,
& dev_attr_ipato_add6 ,
& dev_attr_ipato_del6 ,
# endif
NULL ,
} ;
static struct attribute_group qeth_device_ipato_group = {
. name = " ipa_takeover " ,
. attrs = ( struct attribute * * ) qeth_ipato_device_attrs ,
} ;
2007-02-05 23:18:53 +03:00
static ssize_t
2005-04-17 02:20:36 +04:00
qeth_dev_vipa_add_show ( char * buf , struct qeth_card * card ,
enum qeth_prot_versions proto )
{
struct qeth_ipaddr * ipaddr ;
char addr_str [ 40 ] ;
int entry_len ; /* length of 1 entry string, differs between v4 and v6 */
unsigned long flags ;
int i = 0 ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
entry_len = ( proto = = QETH_PROT_IPV4 ) ? 12 : 40 ;
entry_len + = 2 ; /* \n + terminator */
spin_lock_irqsave ( & card - > ip_lock , flags ) ;
list_for_each_entry ( ipaddr , & card - > ip_list , entry ) {
if ( ipaddr - > proto ! = proto )
continue ;
if ( ipaddr - > type ! = QETH_IP_TYPE_VIPA )
continue ;
/* String must not be longer than PAGE_SIZE. So we check if
* string length gets near PAGE_SIZE . Then we can savely display
* the next IPv6 address ( worst case , compared to IPv4 ) */
if ( ( PAGE_SIZE - i ) < = entry_len )
break ;
qeth_ipaddr_to_string ( proto , ( const u8 * ) & ipaddr - > u , addr_str ) ;
i + = snprintf ( buf + i , PAGE_SIZE - i , " %s \n " , addr_str ) ;
}
spin_unlock_irqrestore ( & card - > ip_lock , flags ) ;
i + = snprintf ( buf + i , PAGE_SIZE - i , " \n " ) ;
return i ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_vipa_add4_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_vipa_add_show ( buf , card , QETH_PROT_IPV4 ) ;
}
2007-02-05 23:18:53 +03:00
static int
2005-04-17 02:20:36 +04:00
qeth_parse_vipae ( const char * buf , enum qeth_prot_versions proto ,
u8 * addr )
{
if ( qeth_string_to_ipaddr ( buf , proto , addr ) ) {
PRINT_WARN ( " Invalid IP address format! \n " ) ;
return - EINVAL ;
}
return 0 ;
}
2007-02-05 23:18:53 +03:00
static ssize_t
2005-04-17 02:20:36 +04:00
qeth_dev_vipa_add_store ( const char * buf , size_t count ,
struct qeth_card * card , enum qeth_prot_versions proto )
{
u8 addr [ 16 ] = { 0 , } ;
int rc ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
if ( ( rc = qeth_parse_vipae ( buf , proto , addr ) ) )
return rc ;
if ( ( rc = qeth_add_vipa ( card , proto , addr ) ) )
return rc ;
return count ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_vipa_add4_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_vipa_add_store ( buf , count , card , QETH_PROT_IPV4 ) ;
}
static QETH_DEVICE_ATTR ( vipa_add4 , add4 , 0644 ,
qeth_dev_vipa_add4_show ,
qeth_dev_vipa_add4_store ) ;
2007-02-05 23:18:53 +03:00
static ssize_t
2005-04-17 02:20:36 +04:00
qeth_dev_vipa_del_store ( const char * buf , size_t count ,
struct qeth_card * card , enum qeth_prot_versions proto )
{
u8 addr [ 16 ] ;
int rc ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
if ( ( rc = qeth_parse_vipae ( buf , proto , addr ) ) )
return rc ;
qeth_del_vipa ( card , proto , addr ) ;
return count ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_vipa_del4_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_vipa_del_store ( buf , count , card , QETH_PROT_IPV4 ) ;
}
static QETH_DEVICE_ATTR ( vipa_del4 , del4 , 0200 , NULL ,
qeth_dev_vipa_del4_store ) ;
# ifdef CONFIG_QETH_IPV6
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_vipa_add6_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_vipa_add_show ( buf , card , QETH_PROT_IPV6 ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_vipa_add6_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_vipa_add_store ( buf , count , card , QETH_PROT_IPV6 ) ;
}
static QETH_DEVICE_ATTR ( vipa_add6 , add6 , 0644 ,
qeth_dev_vipa_add6_show ,
qeth_dev_vipa_add6_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_vipa_del6_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
return qeth_dev_vipa_del_store ( buf , count , card , QETH_PROT_IPV6 ) ;
}
static QETH_DEVICE_ATTR ( vipa_del6 , del6 , 0200 , NULL ,
qeth_dev_vipa_del6_store ) ;
# endif /* CONFIG_QETH_IPV6 */
static struct device_attribute * qeth_vipa_device_attrs [ ] = {
& dev_attr_vipa_add4 ,
& dev_attr_vipa_del4 ,
# ifdef CONFIG_QETH_IPV6
& dev_attr_vipa_add6 ,
& dev_attr_vipa_del6 ,
# endif
NULL ,
} ;
static struct attribute_group qeth_device_vipa_group = {
. name = " vipa " ,
. attrs = ( struct attribute * * ) qeth_vipa_device_attrs ,
} ;
2007-02-05 23:18:53 +03:00
static ssize_t
2005-04-17 02:20:36 +04:00
qeth_dev_rxip_add_show ( char * buf , struct qeth_card * card ,
enum qeth_prot_versions proto )
{
struct qeth_ipaddr * ipaddr ;
char addr_str [ 40 ] ;
int entry_len ; /* length of 1 entry string, differs between v4 and v6 */
unsigned long flags ;
int i = 0 ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
entry_len = ( proto = = QETH_PROT_IPV4 ) ? 12 : 40 ;
entry_len + = 2 ; /* \n + terminator */
spin_lock_irqsave ( & card - > ip_lock , flags ) ;
list_for_each_entry ( ipaddr , & card - > ip_list , entry ) {
if ( ipaddr - > proto ! = proto )
continue ;
if ( ipaddr - > type ! = QETH_IP_TYPE_RXIP )
continue ;
/* String must not be longer than PAGE_SIZE. So we check if
* string length gets near PAGE_SIZE . Then we can savely display
* the next IPv6 address ( worst case , compared to IPv4 ) */
if ( ( PAGE_SIZE - i ) < = entry_len )
break ;
qeth_ipaddr_to_string ( proto , ( const u8 * ) & ipaddr - > u , addr_str ) ;
i + = snprintf ( buf + i , PAGE_SIZE - i , " %s \n " , addr_str ) ;
}
spin_unlock_irqrestore ( & card - > ip_lock , flags ) ;
i + = snprintf ( buf + i , PAGE_SIZE - i , " \n " ) ;
return i ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_rxip_add4_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_rxip_add_show ( buf , card , QETH_PROT_IPV4 ) ;
}
2007-02-05 23:18:53 +03:00
static int
2005-04-17 02:20:36 +04:00
qeth_parse_rxipe ( const char * buf , enum qeth_prot_versions proto ,
u8 * addr )
{
if ( qeth_string_to_ipaddr ( buf , proto , addr ) ) {
PRINT_WARN ( " Invalid IP address format! \n " ) ;
return - EINVAL ;
}
return 0 ;
}
2007-02-05 23:18:53 +03:00
static ssize_t
2005-04-17 02:20:36 +04:00
qeth_dev_rxip_add_store ( const char * buf , size_t count ,
struct qeth_card * card , enum qeth_prot_versions proto )
{
u8 addr [ 16 ] = { 0 , } ;
int rc ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
if ( ( rc = qeth_parse_rxipe ( buf , proto , addr ) ) )
return rc ;
if ( ( rc = qeth_add_rxip ( card , proto , addr ) ) )
return rc ;
return count ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_rxip_add4_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_rxip_add_store ( buf , count , card , QETH_PROT_IPV4 ) ;
}
static QETH_DEVICE_ATTR ( rxip_add4 , add4 , 0644 ,
qeth_dev_rxip_add4_show ,
qeth_dev_rxip_add4_store ) ;
2007-02-05 23:18:53 +03:00
static ssize_t
2005-04-17 02:20:36 +04:00
qeth_dev_rxip_del_store ( const char * buf , size_t count ,
struct qeth_card * card , enum qeth_prot_versions proto )
{
u8 addr [ 16 ] ;
int rc ;
if ( qeth_check_layer2 ( card ) )
return - EPERM ;
if ( ( rc = qeth_parse_rxipe ( buf , proto , addr ) ) )
return rc ;
qeth_del_rxip ( card , proto , addr ) ;
return count ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_rxip_del4_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_rxip_del_store ( buf , count , card , QETH_PROT_IPV4 ) ;
}
static QETH_DEVICE_ATTR ( rxip_del4 , del4 , 0200 , NULL ,
qeth_dev_rxip_del4_store ) ;
# ifdef CONFIG_QETH_IPV6
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_rxip_add6_show ( struct device * dev , struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_rxip_add_show ( buf , card , QETH_PROT_IPV6 ) ;
}
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_rxip_add6_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_rxip_add_store ( buf , count , card , QETH_PROT_IPV6 ) ;
}
static QETH_DEVICE_ATTR ( rxip_add6 , add6 , 0644 ,
qeth_dev_rxip_add6_show ,
qeth_dev_rxip_add6_store ) ;
static ssize_t
2005-05-17 14:43:37 +04:00
qeth_dev_rxip_del6_store ( struct device * dev , struct device_attribute * attr , const char * buf , size_t count )
2005-04-17 02:20:36 +04:00
{
struct qeth_card * card = dev - > driver_data ;
if ( ! card )
return - EINVAL ;
return qeth_dev_rxip_del_store ( buf , count , card , QETH_PROT_IPV6 ) ;
}
static QETH_DEVICE_ATTR ( rxip_del6 , del6 , 0200 , NULL ,
qeth_dev_rxip_del6_store ) ;
# endif /* CONFIG_QETH_IPV6 */
static struct device_attribute * qeth_rxip_device_attrs [ ] = {
& dev_attr_rxip_add4 ,
& dev_attr_rxip_del4 ,
# ifdef CONFIG_QETH_IPV6
& dev_attr_rxip_add6 ,
& dev_attr_rxip_del6 ,
# endif
NULL ,
} ;
static struct attribute_group qeth_device_rxip_group = {
. name = " rxip " ,
. attrs = ( struct attribute * * ) qeth_rxip_device_attrs ,
} ;
int
qeth_create_device_attributes ( struct device * dev )
{
int ret ;
2005-09-30 12:19:19 +04:00
struct qeth_card * card = dev - > driver_data ;
2005-04-17 02:20:36 +04:00
2005-09-30 12:19:19 +04:00
if ( card - > info . type = = QETH_CARD_TYPE_OSN )
return sysfs_create_group ( & dev - > kobj ,
& qeth_osn_device_attr_group ) ;
2006-05-27 05:58:38 +04:00
2005-04-17 02:20:36 +04:00
if ( ( ret = sysfs_create_group ( & dev - > kobj , & qeth_device_attr_group ) ) )
return ret ;
if ( ( ret = sysfs_create_group ( & dev - > kobj , & qeth_device_ipato_group ) ) ) {
sysfs_remove_group ( & dev - > kobj , & qeth_device_attr_group ) ;
return ret ;
}
if ( ( ret = sysfs_create_group ( & dev - > kobj , & qeth_device_vipa_group ) ) ) {
sysfs_remove_group ( & dev - > kobj , & qeth_device_attr_group ) ;
sysfs_remove_group ( & dev - > kobj , & qeth_device_ipato_group ) ;
return ret ;
}
if ( ( ret = sysfs_create_group ( & dev - > kobj , & qeth_device_rxip_group ) ) ) {
sysfs_remove_group ( & dev - > kobj , & qeth_device_attr_group ) ;
sysfs_remove_group ( & dev - > kobj , & qeth_device_ipato_group ) ;
sysfs_remove_group ( & dev - > kobj , & qeth_device_vipa_group ) ;
2006-09-15 18:26:07 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2006-09-15 18:26:07 +04:00
if ( ( ret = sysfs_create_group ( & dev - > kobj , & qeth_device_blkt_group ) ) ) {
sysfs_remove_group ( & dev - > kobj , & qeth_device_attr_group ) ;
sysfs_remove_group ( & dev - > kobj , & qeth_device_ipato_group ) ;
sysfs_remove_group ( & dev - > kobj , & qeth_device_vipa_group ) ;
sysfs_remove_group ( & dev - > kobj , & qeth_device_rxip_group ) ;
2005-04-17 02:20:36 +04:00
return ret ;
2006-09-15 18:26:07 +04:00
}
return 0 ;
2005-04-17 02:20:36 +04:00
}
void
qeth_remove_device_attributes ( struct device * dev )
{
2005-09-30 12:19:19 +04:00
struct qeth_card * card = dev - > driver_data ;
2007-08-29 13:26:54 +04:00
if ( card - > info . type = = QETH_CARD_TYPE_OSN ) {
sysfs_remove_group ( & dev - > kobj , & qeth_osn_device_attr_group ) ;
return ;
}
2005-04-17 02:20:36 +04:00
sysfs_remove_group ( & dev - > kobj , & qeth_device_attr_group ) ;
sysfs_remove_group ( & dev - > kobj , & qeth_device_ipato_group ) ;
sysfs_remove_group ( & dev - > kobj , & qeth_device_vipa_group ) ;
sysfs_remove_group ( & dev - > kobj , & qeth_device_rxip_group ) ;
sysfs_remove_group ( & dev - > kobj , & qeth_device_blkt_group ) ;
}
/**********************/
/* DRIVER ATTRIBUTES */
/**********************/
static ssize_t
qeth_driver_group_store ( struct device_driver * ddrv , const char * buf ,
size_t count )
{
const char * start , * end ;
char bus_ids [ 3 ] [ BUS_ID_SIZE ] , * argv [ 3 ] ;
int i ;
int err ;
start = buf ;
for ( i = 0 ; i < 3 ; i + + ) {
static const char delim [ ] = { ' , ' , ' , ' , ' \n ' } ;
int len ;
if ( ! ( end = strchr ( start , delim [ i ] ) ) )
return - EINVAL ;
len = min_t ( ptrdiff_t , BUS_ID_SIZE , end - start ) ;
strncpy ( bus_ids [ i ] , start , len ) ;
bus_ids [ i ] [ len ] = ' \0 ' ;
start = end + 1 ;
argv [ i ] = bus_ids [ i ] ;
}
err = ccwgroup_create ( qeth_root_dev , qeth_ccwgroup_driver . driver_id ,
& qeth_ccw_driver , 3 , argv ) ;
if ( err )
return err ;
else
return count ;
}
2006-07-12 18:41:55 +04:00
static DRIVER_ATTR ( group , 0200 , NULL , qeth_driver_group_store ) ;
2005-04-17 02:20:36 +04:00
static ssize_t
qeth_driver_notifier_register_store ( struct device_driver * ddrv , const char * buf ,
size_t count )
{
int rc ;
int signum ;
char * tmp , * tmp2 ;
tmp = strsep ( ( char * * ) & buf , " \n " ) ;
if ( ! strncmp ( tmp , " unregister " , 10 ) ) {
if ( ( rc = qeth_notifier_unregister ( current ) ) )
return rc ;
return count ;
}
signum = simple_strtoul ( tmp , & tmp2 , 10 ) ;
if ( ( signum < 0 ) | | ( signum > 32 ) ) {
PRINT_WARN ( " Signal number %d is out of range \n " , signum ) ;
return - EINVAL ;
}
if ( ( rc = qeth_notifier_register ( current , signum ) ) )
return rc ;
return count ;
}
2006-07-12 18:41:55 +04:00
static DRIVER_ATTR ( notifier_register , 0200 , NULL ,
2005-04-17 02:20:36 +04:00
qeth_driver_notifier_register_store ) ;
int
qeth_create_driver_attributes ( void )
{
int rc ;
if ( ( rc = driver_create_file ( & qeth_ccwgroup_driver . driver ,
& driver_attr_group ) ) )
return rc ;
return driver_create_file ( & qeth_ccwgroup_driver . driver ,
& driver_attr_notifier_register ) ;
}
void
qeth_remove_driver_attributes ( void )
{
driver_remove_file ( & qeth_ccwgroup_driver . driver ,
& driver_attr_group ) ;
driver_remove_file ( & qeth_ccwgroup_driver . driver ,
& driver_attr_notifier_register ) ;
}