2015-07-30 15:17:43 -04:00
/*
2017-04-12 20:29:29 -07:00
* Copyright ( c ) 2015 - 2017 Intel Corporation .
2015-07-30 15:17:43 -04:00
*
* This file is provided under a dual BSD / GPLv2 license . When using or
* redistributing this file , you may do so under either license .
*
* GPL LICENSE SUMMARY
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* BSD LICENSE
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* - Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* - Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in
* the documentation and / or other materials provided with the
* distribution .
* - Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
* LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
*/
# include <linux/ctype.h>
# include "hfi.h"
# include "mad.h"
# include "trace.h"
/*
* Start of per - port congestion control structures and support code
*/
/*
* Congestion control table size followed by table entries
*/
static ssize_t read_cc_table_bin ( struct file * filp , struct kobject * kobj ,
2016-02-14 20:21:52 -08:00
struct bin_attribute * bin_attr ,
char * buf , loff_t pos , size_t count )
2015-07-30 15:17:43 -04:00
{
int ret ;
struct hfi1_pportdata * ppd =
container_of ( kobj , struct hfi1_pportdata , pport_cc_kobj ) ;
struct cc_state * cc_state ;
ret = ppd - > total_cct_entry * sizeof ( struct ib_cc_table_entry_shadow )
+ sizeof ( __be16 ) ;
if ( pos > ret )
return - EINVAL ;
if ( count > ret - pos )
count = ret - pos ;
if ( ! count )
return count ;
rcu_read_lock ( ) ;
cc_state = get_cc_state ( ppd ) ;
2016-02-14 20:19:49 -08:00
if ( ! cc_state ) {
2015-07-30 15:17:43 -04:00
rcu_read_unlock ( ) ;
return - EINVAL ;
}
2016-04-12 10:49:58 -07:00
memcpy ( buf , ( void * ) & cc_state - > cct + pos , count ) ;
2015-07-30 15:17:43 -04:00
rcu_read_unlock ( ) ;
return count ;
}
static void port_release ( struct kobject * kobj )
{
/* nothing to do since memory is freed by hfi1_free_devdata() */
}
2017-08-02 15:31:30 +05:30
static const struct bin_attribute cc_table_bin_attr = {
2015-07-30 15:17:43 -04:00
. attr = { . name = " cc_table_bin " , . mode = 0444 } ,
. read = read_cc_table_bin ,
. size = PAGE_SIZE ,
} ;
/*
* Congestion settings : port control , control map and an array of 16
* entries for the congestion entries - increase , timer , event log
* trigger threshold and the minimum injection rate delay .
*/
static ssize_t read_cc_setting_bin ( struct file * filp , struct kobject * kobj ,
2016-02-14 20:21:52 -08:00
struct bin_attribute * bin_attr ,
char * buf , loff_t pos , size_t count )
2015-07-30 15:17:43 -04:00
{
int ret ;
struct hfi1_pportdata * ppd =
container_of ( kobj , struct hfi1_pportdata , pport_cc_kobj ) ;
struct cc_state * cc_state ;
ret = sizeof ( struct opa_congestion_setting_attr_shadow ) ;
if ( pos > ret )
return - EINVAL ;
if ( count > ret - pos )
count = ret - pos ;
if ( ! count )
return count ;
rcu_read_lock ( ) ;
cc_state = get_cc_state ( ppd ) ;
2016-02-14 20:19:49 -08:00
if ( ! cc_state ) {
2015-07-30 15:17:43 -04:00
rcu_read_unlock ( ) ;
return - EINVAL ;
}
2016-04-12 10:49:58 -07:00
memcpy ( buf , ( void * ) & cc_state - > cong_setting + pos , count ) ;
2015-07-30 15:17:43 -04:00
rcu_read_unlock ( ) ;
return count ;
}
2017-08-02 15:31:30 +05:30
static const struct bin_attribute cc_setting_bin_attr = {
2015-07-30 15:17:43 -04:00
. attr = { . name = " cc_settings_bin " , . mode = 0444 } ,
. read = read_cc_setting_bin ,
. size = PAGE_SIZE ,
} ;
2016-02-03 14:32:57 -08:00
struct hfi1_port_attr {
struct attribute attr ;
ssize_t ( * show ) ( struct hfi1_pportdata * , char * ) ;
ssize_t ( * store ) ( struct hfi1_pportdata * , const char * , size_t ) ;
} ;
static ssize_t cc_prescan_show ( struct hfi1_pportdata * ppd , char * buf )
{
return sprintf ( buf , " %s \n " , ppd - > cc_prescan ? " on " : " off " ) ;
}
static ssize_t cc_prescan_store ( struct hfi1_pportdata * ppd , const char * buf ,
size_t count )
{
if ( ! memcmp ( buf , " on " , 2 ) )
ppd - > cc_prescan = true ;
else if ( ! memcmp ( buf , " off " , 3 ) )
ppd - > cc_prescan = false ;
return count ;
}
static struct hfi1_port_attr cc_prescan_attr =
__ATTR ( cc_prescan , 0600 , cc_prescan_show , cc_prescan_store ) ;
static ssize_t cc_attr_show ( struct kobject * kobj , struct attribute * attr ,
char * buf )
{
struct hfi1_port_attr * port_attr =
container_of ( attr , struct hfi1_port_attr , attr ) ;
struct hfi1_pportdata * ppd =
container_of ( kobj , struct hfi1_pportdata , pport_cc_kobj ) ;
return port_attr - > show ( ppd , buf ) ;
}
static ssize_t cc_attr_store ( struct kobject * kobj , struct attribute * attr ,
const char * buf , size_t count )
{
struct hfi1_port_attr * port_attr =
container_of ( attr , struct hfi1_port_attr , attr ) ;
struct hfi1_pportdata * ppd =
container_of ( kobj , struct hfi1_pportdata , pport_cc_kobj ) ;
return port_attr - > store ( ppd , buf , count ) ;
}
static const struct sysfs_ops port_cc_sysfs_ops = {
. show = cc_attr_show ,
. store = cc_attr_store
} ;
static struct attribute * port_cc_default_attributes [ ] = {
2017-05-10 10:54:12 -05:00
& cc_prescan_attr . attr ,
NULL
2016-02-03 14:32:57 -08:00
} ;
static struct kobj_type port_cc_ktype = {
. release = port_release ,
. sysfs_ops = & port_cc_sysfs_ops ,
. default_attrs = port_cc_default_attributes
} ;
2015-07-30 15:17:43 -04:00
/* Start sc2vl */
# define HFI1_SC2VL_ATTR(N) \
static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_ # # N = { \
. attr = { . name = __stringify ( N ) , . mode = 0444 } , \
. sc = N \
}
struct hfi1_sc2vl_attr {
struct attribute attr ;
int sc ;
} ;
HFI1_SC2VL_ATTR ( 0 ) ;
HFI1_SC2VL_ATTR ( 1 ) ;
HFI1_SC2VL_ATTR ( 2 ) ;
HFI1_SC2VL_ATTR ( 3 ) ;
HFI1_SC2VL_ATTR ( 4 ) ;
HFI1_SC2VL_ATTR ( 5 ) ;
HFI1_SC2VL_ATTR ( 6 ) ;
HFI1_SC2VL_ATTR ( 7 ) ;
HFI1_SC2VL_ATTR ( 8 ) ;
HFI1_SC2VL_ATTR ( 9 ) ;
HFI1_SC2VL_ATTR ( 10 ) ;
HFI1_SC2VL_ATTR ( 11 ) ;
HFI1_SC2VL_ATTR ( 12 ) ;
HFI1_SC2VL_ATTR ( 13 ) ;
HFI1_SC2VL_ATTR ( 14 ) ;
HFI1_SC2VL_ATTR ( 15 ) ;
HFI1_SC2VL_ATTR ( 16 ) ;
HFI1_SC2VL_ATTR ( 17 ) ;
HFI1_SC2VL_ATTR ( 18 ) ;
HFI1_SC2VL_ATTR ( 19 ) ;
HFI1_SC2VL_ATTR ( 20 ) ;
HFI1_SC2VL_ATTR ( 21 ) ;
HFI1_SC2VL_ATTR ( 22 ) ;
HFI1_SC2VL_ATTR ( 23 ) ;
HFI1_SC2VL_ATTR ( 24 ) ;
HFI1_SC2VL_ATTR ( 25 ) ;
HFI1_SC2VL_ATTR ( 26 ) ;
HFI1_SC2VL_ATTR ( 27 ) ;
HFI1_SC2VL_ATTR ( 28 ) ;
HFI1_SC2VL_ATTR ( 29 ) ;
HFI1_SC2VL_ATTR ( 30 ) ;
HFI1_SC2VL_ATTR ( 31 ) ;
static struct attribute * sc2vl_default_attributes [ ] = {
& hfi1_sc2vl_attr_0 . attr ,
& hfi1_sc2vl_attr_1 . attr ,
& hfi1_sc2vl_attr_2 . attr ,
& hfi1_sc2vl_attr_3 . attr ,
& hfi1_sc2vl_attr_4 . attr ,
& hfi1_sc2vl_attr_5 . attr ,
& hfi1_sc2vl_attr_6 . attr ,
& hfi1_sc2vl_attr_7 . attr ,
& hfi1_sc2vl_attr_8 . attr ,
& hfi1_sc2vl_attr_9 . attr ,
& hfi1_sc2vl_attr_10 . attr ,
& hfi1_sc2vl_attr_11 . attr ,
& hfi1_sc2vl_attr_12 . attr ,
& hfi1_sc2vl_attr_13 . attr ,
& hfi1_sc2vl_attr_14 . attr ,
& hfi1_sc2vl_attr_15 . attr ,
& hfi1_sc2vl_attr_16 . attr ,
& hfi1_sc2vl_attr_17 . attr ,
& hfi1_sc2vl_attr_18 . attr ,
& hfi1_sc2vl_attr_19 . attr ,
& hfi1_sc2vl_attr_20 . attr ,
& hfi1_sc2vl_attr_21 . attr ,
& hfi1_sc2vl_attr_22 . attr ,
& hfi1_sc2vl_attr_23 . attr ,
& hfi1_sc2vl_attr_24 . attr ,
& hfi1_sc2vl_attr_25 . attr ,
& hfi1_sc2vl_attr_26 . attr ,
& hfi1_sc2vl_attr_27 . attr ,
& hfi1_sc2vl_attr_28 . attr ,
& hfi1_sc2vl_attr_29 . attr ,
& hfi1_sc2vl_attr_30 . attr ,
& hfi1_sc2vl_attr_31 . attr ,
NULL
} ;
static ssize_t sc2vl_attr_show ( struct kobject * kobj , struct attribute * attr ,
char * buf )
{
struct hfi1_sc2vl_attr * sattr =
container_of ( attr , struct hfi1_sc2vl_attr , attr ) ;
struct hfi1_pportdata * ppd =
container_of ( kobj , struct hfi1_pportdata , sc2vl_kobj ) ;
struct hfi1_devdata * dd = ppd - > dd ;
return sprintf ( buf , " %u \n " , * ( ( u8 * ) dd - > sc2vl + sattr - > sc ) ) ;
}
static const struct sysfs_ops hfi1_sc2vl_ops = {
. show = sc2vl_attr_show ,
} ;
static struct kobj_type hfi1_sc2vl_ktype = {
. release = port_release ,
. sysfs_ops = & hfi1_sc2vl_ops ,
. default_attrs = sc2vl_default_attributes
} ;
/* End sc2vl */
/* Start sl2sc */
# define HFI1_SL2SC_ATTR(N) \
static struct hfi1_sl2sc_attr hfi1_sl2sc_attr_ # # N = { \
. attr = { . name = __stringify ( N ) , . mode = 0444 } , \
. sl = N \
}
struct hfi1_sl2sc_attr {
struct attribute attr ;
int sl ;
} ;
HFI1_SL2SC_ATTR ( 0 ) ;
HFI1_SL2SC_ATTR ( 1 ) ;
HFI1_SL2SC_ATTR ( 2 ) ;
HFI1_SL2SC_ATTR ( 3 ) ;
HFI1_SL2SC_ATTR ( 4 ) ;
HFI1_SL2SC_ATTR ( 5 ) ;
HFI1_SL2SC_ATTR ( 6 ) ;
HFI1_SL2SC_ATTR ( 7 ) ;
HFI1_SL2SC_ATTR ( 8 ) ;
HFI1_SL2SC_ATTR ( 9 ) ;
HFI1_SL2SC_ATTR ( 10 ) ;
HFI1_SL2SC_ATTR ( 11 ) ;
HFI1_SL2SC_ATTR ( 12 ) ;
HFI1_SL2SC_ATTR ( 13 ) ;
HFI1_SL2SC_ATTR ( 14 ) ;
HFI1_SL2SC_ATTR ( 15 ) ;
HFI1_SL2SC_ATTR ( 16 ) ;
HFI1_SL2SC_ATTR ( 17 ) ;
HFI1_SL2SC_ATTR ( 18 ) ;
HFI1_SL2SC_ATTR ( 19 ) ;
HFI1_SL2SC_ATTR ( 20 ) ;
HFI1_SL2SC_ATTR ( 21 ) ;
HFI1_SL2SC_ATTR ( 22 ) ;
HFI1_SL2SC_ATTR ( 23 ) ;
HFI1_SL2SC_ATTR ( 24 ) ;
HFI1_SL2SC_ATTR ( 25 ) ;
HFI1_SL2SC_ATTR ( 26 ) ;
HFI1_SL2SC_ATTR ( 27 ) ;
HFI1_SL2SC_ATTR ( 28 ) ;
HFI1_SL2SC_ATTR ( 29 ) ;
HFI1_SL2SC_ATTR ( 30 ) ;
HFI1_SL2SC_ATTR ( 31 ) ;
static struct attribute * sl2sc_default_attributes [ ] = {
& hfi1_sl2sc_attr_0 . attr ,
& hfi1_sl2sc_attr_1 . attr ,
& hfi1_sl2sc_attr_2 . attr ,
& hfi1_sl2sc_attr_3 . attr ,
& hfi1_sl2sc_attr_4 . attr ,
& hfi1_sl2sc_attr_5 . attr ,
& hfi1_sl2sc_attr_6 . attr ,
& hfi1_sl2sc_attr_7 . attr ,
& hfi1_sl2sc_attr_8 . attr ,
& hfi1_sl2sc_attr_9 . attr ,
& hfi1_sl2sc_attr_10 . attr ,
& hfi1_sl2sc_attr_11 . attr ,
& hfi1_sl2sc_attr_12 . attr ,
& hfi1_sl2sc_attr_13 . attr ,
& hfi1_sl2sc_attr_14 . attr ,
& hfi1_sl2sc_attr_15 . attr ,
& hfi1_sl2sc_attr_16 . attr ,
& hfi1_sl2sc_attr_17 . attr ,
& hfi1_sl2sc_attr_18 . attr ,
& hfi1_sl2sc_attr_19 . attr ,
& hfi1_sl2sc_attr_20 . attr ,
& hfi1_sl2sc_attr_21 . attr ,
& hfi1_sl2sc_attr_22 . attr ,
& hfi1_sl2sc_attr_23 . attr ,
& hfi1_sl2sc_attr_24 . attr ,
& hfi1_sl2sc_attr_25 . attr ,
& hfi1_sl2sc_attr_26 . attr ,
& hfi1_sl2sc_attr_27 . attr ,
& hfi1_sl2sc_attr_28 . attr ,
& hfi1_sl2sc_attr_29 . attr ,
& hfi1_sl2sc_attr_30 . attr ,
& hfi1_sl2sc_attr_31 . attr ,
NULL
} ;
static ssize_t sl2sc_attr_show ( struct kobject * kobj , struct attribute * attr ,
char * buf )
{
struct hfi1_sl2sc_attr * sattr =
container_of ( attr , struct hfi1_sl2sc_attr , attr ) ;
struct hfi1_pportdata * ppd =
container_of ( kobj , struct hfi1_pportdata , sl2sc_kobj ) ;
struct hfi1_ibport * ibp = & ppd - > ibport_data ;
return sprintf ( buf , " %u \n " , ibp - > sl_to_sc [ sattr - > sl ] ) ;
}
static const struct sysfs_ops hfi1_sl2sc_ops = {
. show = sl2sc_attr_show ,
} ;
static struct kobj_type hfi1_sl2sc_ktype = {
. release = port_release ,
. sysfs_ops = & hfi1_sl2sc_ops ,
. default_attrs = sl2sc_default_attributes
} ;
/* End sl2sc */
/* Start vl2mtu */
# define HFI1_VL2MTU_ATTR(N) \
static struct hfi1_vl2mtu_attr hfi1_vl2mtu_attr_ # # N = { \
. attr = { . name = __stringify ( N ) , . mode = 0444 } , \
. vl = N \
}
struct hfi1_vl2mtu_attr {
struct attribute attr ;
int vl ;
} ;
HFI1_VL2MTU_ATTR ( 0 ) ;
HFI1_VL2MTU_ATTR ( 1 ) ;
HFI1_VL2MTU_ATTR ( 2 ) ;
HFI1_VL2MTU_ATTR ( 3 ) ;
HFI1_VL2MTU_ATTR ( 4 ) ;
HFI1_VL2MTU_ATTR ( 5 ) ;
HFI1_VL2MTU_ATTR ( 6 ) ;
HFI1_VL2MTU_ATTR ( 7 ) ;
HFI1_VL2MTU_ATTR ( 8 ) ;
HFI1_VL2MTU_ATTR ( 9 ) ;
HFI1_VL2MTU_ATTR ( 10 ) ;
HFI1_VL2MTU_ATTR ( 11 ) ;
HFI1_VL2MTU_ATTR ( 12 ) ;
HFI1_VL2MTU_ATTR ( 13 ) ;
HFI1_VL2MTU_ATTR ( 14 ) ;
HFI1_VL2MTU_ATTR ( 15 ) ;
static struct attribute * vl2mtu_default_attributes [ ] = {
& hfi1_vl2mtu_attr_0 . attr ,
& hfi1_vl2mtu_attr_1 . attr ,
& hfi1_vl2mtu_attr_2 . attr ,
& hfi1_vl2mtu_attr_3 . attr ,
& hfi1_vl2mtu_attr_4 . attr ,
& hfi1_vl2mtu_attr_5 . attr ,
& hfi1_vl2mtu_attr_6 . attr ,
& hfi1_vl2mtu_attr_7 . attr ,
& hfi1_vl2mtu_attr_8 . attr ,
& hfi1_vl2mtu_attr_9 . attr ,
& hfi1_vl2mtu_attr_10 . attr ,
& hfi1_vl2mtu_attr_11 . attr ,
& hfi1_vl2mtu_attr_12 . attr ,
& hfi1_vl2mtu_attr_13 . attr ,
& hfi1_vl2mtu_attr_14 . attr ,
& hfi1_vl2mtu_attr_15 . attr ,
NULL
} ;
static ssize_t vl2mtu_attr_show ( struct kobject * kobj , struct attribute * attr ,
char * buf )
{
struct hfi1_vl2mtu_attr * vlattr =
container_of ( attr , struct hfi1_vl2mtu_attr , attr ) ;
struct hfi1_pportdata * ppd =
container_of ( kobj , struct hfi1_pportdata , vl2mtu_kobj ) ;
struct hfi1_devdata * dd = ppd - > dd ;
return sprintf ( buf , " %u \n " , dd - > vld [ vlattr - > vl ] . mtu ) ;
}
static const struct sysfs_ops hfi1_vl2mtu_ops = {
. show = vl2mtu_attr_show ,
} ;
static struct kobj_type hfi1_vl2mtu_ktype = {
. release = port_release ,
. sysfs_ops = & hfi1_vl2mtu_ops ,
. default_attrs = vl2mtu_default_attributes
} ;
/* end of per-port file structures and support code */
/*
* Start of per - unit ( or driver , in some cases , but replicated
* per unit ) functions ( these get a device * )
*/
static ssize_t show_rev ( struct device * device , struct device_attribute * attr ,
char * buf )
{
struct hfi1_ibdev * dev =
2016-01-19 14:41:33 -08:00
container_of ( device , struct hfi1_ibdev , rdi . ibdev . dev ) ;
2015-07-30 15:17:43 -04:00
return sprintf ( buf , " %x \n " , dd_from_dev ( dev ) - > minrev ) ;
}
static ssize_t show_hfi ( struct device * device , struct device_attribute * attr ,
char * buf )
{
struct hfi1_ibdev * dev =
2016-01-19 14:41:33 -08:00
container_of ( device , struct hfi1_ibdev , rdi . ibdev . dev ) ;
2015-07-30 15:17:43 -04:00
struct hfi1_devdata * dd = dd_from_dev ( dev ) ;
int ret ;
if ( ! dd - > boardname )
ret = - EINVAL ;
else
ret = scnprintf ( buf , PAGE_SIZE , " %s \n " , dd - > boardname ) ;
return ret ;
}
static ssize_t show_boardversion ( struct device * device ,
struct device_attribute * attr , char * buf )
{
struct hfi1_ibdev * dev =
2016-01-19 14:41:33 -08:00
container_of ( device , struct hfi1_ibdev , rdi . ibdev . dev ) ;
2015-07-30 15:17:43 -04:00
struct hfi1_devdata * dd = dd_from_dev ( dev ) ;
/* The string printed here is already newline-terminated. */
return scnprintf ( buf , PAGE_SIZE , " %s " , dd - > boardversion ) ;
}
static ssize_t show_nctxts ( struct device * device ,
struct device_attribute * attr , char * buf )
{
struct hfi1_ibdev * dev =
2016-01-19 14:41:33 -08:00
container_of ( device , struct hfi1_ibdev , rdi . ibdev . dev ) ;
2015-07-30 15:17:43 -04:00
struct hfi1_devdata * dd = dd_from_dev ( dev ) ;
/*
* Return the smaller of send and receive contexts .
* Normally , user level applications would require both a send
* and a receive context , so returning the smaller of the two counts
* give a more accurate picture of total contexts available .
*/
return scnprintf ( buf , PAGE_SIZE , " %u \n " ,
2017-10-02 11:04:19 -07:00
min ( dd - > num_user_contexts ,
2015-07-30 15:17:43 -04:00
( u32 ) dd - > sc_sizes [ SC_USER ] . count ) ) ;
}
static ssize_t show_nfreectxts ( struct device * device ,
2016-02-14 20:21:52 -08:00
struct device_attribute * attr , char * buf )
2015-07-30 15:17:43 -04:00
{
struct hfi1_ibdev * dev =
2016-01-19 14:41:33 -08:00
container_of ( device , struct hfi1_ibdev , rdi . ibdev . dev ) ;
2015-07-30 15:17:43 -04:00
struct hfi1_devdata * dd = dd_from_dev ( dev ) ;
/* Return the number of free user ports (contexts) available. */
return scnprintf ( buf , PAGE_SIZE , " %u \n " , dd - > freectxts ) ;
}
static ssize_t show_serial ( struct device * device ,
struct device_attribute * attr , char * buf )
{
struct hfi1_ibdev * dev =
2016-01-19 14:41:33 -08:00
container_of ( device , struct hfi1_ibdev , rdi . ibdev . dev ) ;
2015-07-30 15:17:43 -04:00
struct hfi1_devdata * dd = dd_from_dev ( dev ) ;
return scnprintf ( buf , PAGE_SIZE , " %s " , dd - > serial ) ;
}
static ssize_t store_chip_reset ( struct device * device ,
struct device_attribute * attr , const char * buf ,
size_t count )
{
struct hfi1_ibdev * dev =
2016-01-19 14:41:33 -08:00
container_of ( device , struct hfi1_ibdev , rdi . ibdev . dev ) ;
2015-07-30 15:17:43 -04:00
struct hfi1_devdata * dd = dd_from_dev ( dev ) ;
int ret ;
if ( count < 5 | | memcmp ( buf , " reset " , 5 ) | | ! dd - > diag_client ) {
ret = - EINVAL ;
goto bail ;
}
ret = hfi1_reset_device ( dd - > unit ) ;
bail :
return ret < 0 ? ret : count ;
}
/*
* Convert the reported temperature from an integer ( reported in
* units of 0.25 C ) to a floating point number .
*/
# define temp2str(temp, buf, size, idx) \
scnprintf ( ( buf ) + ( idx ) , ( size ) - ( idx ) , " %u.%02u " , \
( ( temp ) > > 2 ) , ( ( temp ) & 0x3 ) * 25 )
/*
* Dump tempsense values , in decimal , to ease shell - scripts .
*/
static ssize_t show_tempsense ( struct device * device ,
struct device_attribute * attr , char * buf )
{
struct hfi1_ibdev * dev =
2016-01-19 14:41:33 -08:00
container_of ( device , struct hfi1_ibdev , rdi . ibdev . dev ) ;
2015-07-30 15:17:43 -04:00
struct hfi1_devdata * dd = dd_from_dev ( dev ) ;
struct hfi1_temp temp ;
2015-10-15 13:54:35 +05:30
int ret ;
2015-07-30 15:17:43 -04:00
ret = hfi1_tempsense_rd ( dd , & temp ) ;
if ( ! ret ) {
int idx = 0 ;
idx + = temp2str ( temp . curr , buf , PAGE_SIZE , idx ) ;
idx + = temp2str ( temp . lo_lim , buf , PAGE_SIZE , idx ) ;
idx + = temp2str ( temp . hi_lim , buf , PAGE_SIZE , idx ) ;
idx + = temp2str ( temp . crit_lim , buf , PAGE_SIZE , idx ) ;
idx + = scnprintf ( buf + idx , PAGE_SIZE - idx ,
" %u %u %u \n " , temp . triggers & 0x1 ,
temp . triggers & 0x2 , temp . triggers & 0x4 ) ;
ret = idx ;
}
return ret ;
}
/*
* end of per - unit ( or driver , in some cases , but replicated
* per unit ) functions
*/
/* start of per-unit file structures and support code */
static DEVICE_ATTR ( hw_rev , S_IRUGO , show_rev , NULL ) ;
static DEVICE_ATTR ( board_id , S_IRUGO , show_hfi , NULL ) ;
static DEVICE_ATTR ( nctxts , S_IRUGO , show_nctxts , NULL ) ;
static DEVICE_ATTR ( nfreectxts , S_IRUGO , show_nfreectxts , NULL ) ;
static DEVICE_ATTR ( serial , S_IRUGO , show_serial , NULL ) ;
static DEVICE_ATTR ( boardversion , S_IRUGO , show_boardversion , NULL ) ;
static DEVICE_ATTR ( tempsense , S_IRUGO , show_tempsense , NULL ) ;
static DEVICE_ATTR ( chip_reset , S_IWUSR , NULL , store_chip_reset ) ;
static struct device_attribute * hfi1_attributes [ ] = {
& dev_attr_hw_rev ,
& dev_attr_board_id ,
& dev_attr_nctxts ,
& dev_attr_nfreectxts ,
& dev_attr_serial ,
& dev_attr_boardversion ,
& dev_attr_tempsense ,
& dev_attr_chip_reset ,
} ;
int hfi1_create_port_files ( struct ib_device * ibdev , u8 port_num ,
struct kobject * kobj )
{
struct hfi1_pportdata * ppd ;
struct hfi1_devdata * dd = dd_from_ibdev ( ibdev ) ;
int ret ;
if ( ! port_num | | port_num > dd - > num_pports ) {
dd_dev_err ( dd ,
2016-02-14 20:21:52 -08:00
" Skipping infiniband class with invalid port %u \n " ,
port_num ) ;
2015-07-30 15:17:43 -04:00
return - ENODEV ;
}
ppd = & dd - > pport [ port_num - 1 ] ;
ret = kobject_init_and_add ( & ppd - > sc2vl_kobj , & hfi1_sc2vl_ktype , kobj ,
" sc2vl " ) ;
if ( ret ) {
dd_dev_err ( dd ,
" Skipping sc2vl sysfs info, (err %d) port %u \n " ,
ret , port_num ) ;
goto bail ;
}
kobject_uevent ( & ppd - > sc2vl_kobj , KOBJ_ADD ) ;
ret = kobject_init_and_add ( & ppd - > sl2sc_kobj , & hfi1_sl2sc_ktype , kobj ,
" sl2sc " ) ;
if ( ret ) {
dd_dev_err ( dd ,
" Skipping sl2sc sysfs info, (err %d) port %u \n " ,
ret , port_num ) ;
goto bail_sc2vl ;
}
kobject_uevent ( & ppd - > sl2sc_kobj , KOBJ_ADD ) ;
ret = kobject_init_and_add ( & ppd - > vl2mtu_kobj , & hfi1_vl2mtu_ktype , kobj ,
" vl2mtu " ) ;
if ( ret ) {
dd_dev_err ( dd ,
" Skipping vl2mtu sysfs info, (err %d) port %u \n " ,
ret , port_num ) ;
goto bail_sl2sc ;
}
kobject_uevent ( & ppd - > vl2mtu_kobj , KOBJ_ADD ) ;
ret = kobject_init_and_add ( & ppd - > pport_cc_kobj , & port_cc_ktype ,
kobj , " CCMgtA " ) ;
if ( ret ) {
dd_dev_err ( dd ,
2016-02-14 20:21:52 -08:00
" Skipping Congestion Control sysfs info, (err %d) port %u \n " ,
ret , port_num ) ;
2015-07-30 15:17:43 -04:00
goto bail_vl2mtu ;
}
kobject_uevent ( & ppd - > pport_cc_kobj , KOBJ_ADD ) ;
2016-02-14 20:21:52 -08:00
ret = sysfs_create_bin_file ( & ppd - > pport_cc_kobj , & cc_setting_bin_attr ) ;
2015-07-30 15:17:43 -04:00
if ( ret ) {
dd_dev_err ( dd ,
2016-02-14 20:21:52 -08:00
" Skipping Congestion Control setting sysfs info, (err %d) port %u \n " ,
ret , port_num ) ;
2015-07-30 15:17:43 -04:00
goto bail_cc ;
}
2016-02-14 20:21:52 -08:00
ret = sysfs_create_bin_file ( & ppd - > pport_cc_kobj , & cc_table_bin_attr ) ;
2015-07-30 15:17:43 -04:00
if ( ret ) {
dd_dev_err ( dd ,
2016-02-14 20:21:52 -08:00
" Skipping Congestion Control table sysfs info, (err %d) port %u \n " ,
ret , port_num ) ;
2015-07-30 15:17:43 -04:00
goto bail_cc_entry_bin ;
}
dd_dev_info ( dd ,
2016-05-12 10:23:35 -07:00
" Congestion Control Agent enabled for port %d \n " ,
port_num ) ;
2015-07-30 15:17:43 -04:00
return 0 ;
bail_cc_entry_bin :
sysfs_remove_bin_file ( & ppd - > pport_cc_kobj ,
& cc_setting_bin_attr ) ;
bail_cc :
kobject_put ( & ppd - > pport_cc_kobj ) ;
bail_vl2mtu :
kobject_put ( & ppd - > vl2mtu_kobj ) ;
bail_sl2sc :
kobject_put ( & ppd - > sl2sc_kobj ) ;
bail_sc2vl :
kobject_put ( & ppd - > sc2vl_kobj ) ;
bail :
return ret ;
}
2016-09-25 07:44:23 -07:00
struct sde_attribute {
struct attribute attr ;
ssize_t ( * show ) ( struct sdma_engine * sde , char * buf ) ;
ssize_t ( * store ) ( struct sdma_engine * sde , const char * buf , size_t cnt ) ;
} ;
static ssize_t sde_show ( struct kobject * kobj , struct attribute * attr , char * buf )
{
struct sde_attribute * sde_attr =
container_of ( attr , struct sde_attribute , attr ) ;
struct sdma_engine * sde =
container_of ( kobj , struct sdma_engine , kobj ) ;
if ( ! sde_attr - > show )
return - EINVAL ;
return sde_attr - > show ( sde , buf ) ;
}
static ssize_t sde_store ( struct kobject * kobj , struct attribute * attr ,
const char * buf , size_t count )
{
struct sde_attribute * sde_attr =
container_of ( attr , struct sde_attribute , attr ) ;
struct sdma_engine * sde =
container_of ( kobj , struct sdma_engine , kobj ) ;
if ( ! capable ( CAP_SYS_ADMIN ) )
return - EPERM ;
if ( ! sde_attr - > store )
return - EINVAL ;
return sde_attr - > store ( sde , buf , count ) ;
}
static const struct sysfs_ops sde_sysfs_ops = {
. show = sde_show ,
. store = sde_store ,
} ;
static struct kobj_type sde_ktype = {
. sysfs_ops = & sde_sysfs_ops ,
} ;
# define SDE_ATTR(_name, _mode, _show, _store) \
struct sde_attribute sde_attr_ # # _name = \
__ATTR ( _name , _mode , _show , _store )
static ssize_t sde_show_cpu_to_sde_map ( struct sdma_engine * sde , char * buf )
{
return sdma_get_cpu_to_sde_map ( sde , buf ) ;
}
static ssize_t sde_store_cpu_to_sde_map ( struct sdma_engine * sde ,
const char * buf , size_t count )
{
return sdma_set_cpu_to_sde_map ( sde , buf , count ) ;
}
2016-09-25 07:44:30 -07:00
static ssize_t sde_show_vl ( struct sdma_engine * sde , char * buf )
{
int vl ;
vl = sdma_engine_get_vl ( sde ) ;
if ( vl < 0 )
return vl ;
return snprintf ( buf , PAGE_SIZE , " %d \n " , vl ) ;
}
2016-09-25 07:44:23 -07:00
static SDE_ATTR ( cpu_list , S_IWUSR | S_IRUGO ,
sde_show_cpu_to_sde_map ,
sde_store_cpu_to_sde_map ) ;
2016-09-25 07:44:30 -07:00
static SDE_ATTR ( vl , S_IRUGO , sde_show_vl , NULL ) ;
2016-09-25 07:44:23 -07:00
static struct sde_attribute * sde_attribs [ ] = {
2016-09-25 07:44:30 -07:00
& sde_attr_cpu_list ,
& sde_attr_vl
2016-09-25 07:44:23 -07:00
} ;
2015-07-30 15:17:43 -04:00
/*
* Register and create our files in / sys / class / infiniband .
*/
int hfi1_verbs_register_sysfs ( struct hfi1_devdata * dd )
{
2016-01-19 14:41:33 -08:00
struct ib_device * dev = & dd - > verbs_dev . rdi . ibdev ;
2016-09-25 07:44:23 -07:00
struct device * class_dev = & dev - > dev ;
int i , j , ret ;
2015-07-30 15:17:43 -04:00
for ( i = 0 ; i < ARRAY_SIZE ( hfi1_attributes ) ; + + i ) {
ret = device_create_file ( & dev - > dev , hfi1_attributes [ i ] ) ;
if ( ret )
goto bail ;
}
2016-09-25 07:44:23 -07:00
for ( i = 0 ; i < dd - > num_sdma ; i + + ) {
ret = kobject_init_and_add ( & dd - > per_sdma [ i ] . kobj ,
& sde_ktype , & class_dev - > kobj ,
" sdma%d " , i ) ;
if ( ret )
goto bail ;
for ( j = 0 ; j < ARRAY_SIZE ( sde_attribs ) ; j + + ) {
ret = sysfs_create_file ( & dd - > per_sdma [ i ] . kobj ,
& sde_attribs [ j ] - > attr ) ;
if ( ret )
goto bail ;
}
}
2015-07-30 15:17:43 -04:00
return 0 ;
bail :
for ( i = 0 ; i < ARRAY_SIZE ( hfi1_attributes ) ; + + i )
device_remove_file ( & dev - > dev , hfi1_attributes [ i ] ) ;
2016-09-25 07:44:23 -07:00
for ( i = 0 ; i < dd - > num_sdma ; i + + )
kobject_del ( & dd - > per_sdma [ i ] . kobj ) ;
2015-07-30 15:17:43 -04:00
return ret ;
}
/*
* Unregister and remove our files in / sys / class / infiniband .
*/
void hfi1_verbs_unregister_sysfs ( struct hfi1_devdata * dd )
{
struct hfi1_pportdata * ppd ;
int i ;
for ( i = 0 ; i < dd - > num_pports ; i + + ) {
ppd = & dd - > pport [ i ] ;
sysfs_remove_bin_file ( & ppd - > pport_cc_kobj ,
& cc_setting_bin_attr ) ;
sysfs_remove_bin_file ( & ppd - > pport_cc_kobj ,
& cc_table_bin_attr ) ;
kobject_put ( & ppd - > pport_cc_kobj ) ;
kobject_put ( & ppd - > vl2mtu_kobj ) ;
kobject_put ( & ppd - > sl2sc_kobj ) ;
kobject_put ( & ppd - > sc2vl_kobj ) ;
}
}