2012-11-29 14:36:55 +01:00
/*
* Copyright IBM Corp . 2012
*
* Author ( s ) :
* Jan Glauber < jang @ linux . vnet . ibm . com >
*/
2014-07-16 17:21:01 +02:00
# define KMSG_COMPONENT "zpci"
# define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
2012-11-29 14:36:55 +01:00
# include <linux/kernel.h>
# include <linux/stat.h>
# include <linux/pci.h>
2015-11-27 11:22:57 +01:00
# include <asm/sclp.h>
2014-04-16 16:10:18 +02:00
# define zpci_attr(name, fmt, member) \
static ssize_t name # # _show ( struct device * dev , \
struct device_attribute * attr , char * buf ) \
{ \
2015-06-23 14:06:35 +02:00
struct zpci_dev * zdev = to_zpci ( to_pci_dev ( dev ) ) ; \
2014-04-16 16:10:18 +02:00
\
return sprintf ( buf , fmt , zdev - > member ) ; \
} \
static DEVICE_ATTR_RO ( name )
zpci_attr ( function_id , " 0x%08x \n " , fid ) ;
zpci_attr ( function_handle , " 0x%08x \n " , fh ) ;
zpci_attr ( pchid , " 0x%04x \n " , pchid ) ;
zpci_attr ( pfgid , " 0x%02x \n " , pfgid ) ;
2014-04-16 16:12:05 +02:00
zpci_attr ( vfn , " 0x%04x \n " , vfn ) ;
zpci_attr ( pft , " 0x%02x \n " , pft ) ;
zpci_attr ( uid , " 0x%x \n " , uid ) ;
zpci_attr ( segment0 , " 0x%02x \n " , pfip [ 0 ] ) ;
zpci_attr ( segment1 , " 0x%02x \n " , pfip [ 1 ] ) ;
zpci_attr ( segment2 , " 0x%02x \n " , pfip [ 2 ] ) ;
zpci_attr ( segment3 , " 0x%02x \n " , pfip [ 3 ] ) ;
2014-04-16 16:10:18 +02:00
static ssize_t recover_store ( struct device * dev , struct device_attribute * attr ,
2014-02-03 14:03:04 -05:00
const char * buf , size_t count )
2013-08-29 19:35:19 +02:00
{
struct pci_dev * pdev = to_pci_dev ( dev ) ;
2015-06-23 14:06:35 +02:00
struct zpci_dev * zdev = to_zpci ( pdev ) ;
2013-08-29 19:35:19 +02:00
int ret ;
2014-02-03 14:03:04 -05:00
if ( ! device_remove_file_self ( dev , attr ) )
return count ;
2015-07-28 19:14:51 +02:00
pci_lock_rescan_remove ( ) ;
2013-08-29 19:35:19 +02:00
pci_stop_and_remove_bus_device ( pdev ) ;
ret = zpci_disable_device ( zdev ) ;
if ( ret )
2015-07-28 19:14:51 +02:00
goto error ;
2013-08-29 19:35:19 +02:00
ret = zpci_enable_device ( zdev ) ;
if ( ret )
2015-07-28 19:14:51 +02:00
goto error ;
2013-08-29 19:35:19 +02:00
pci_rescan_bus ( zdev - > bus ) ;
2015-07-28 19:14:51 +02:00
pci_unlock_rescan_remove ( ) ;
2014-02-03 14:03:04 -05:00
return count ;
2015-07-28 19:14:51 +02:00
error :
pci_unlock_rescan_remove ( ) ;
return ret ;
2013-08-29 19:35:19 +02:00
}
2014-04-16 16:10:18 +02:00
static DEVICE_ATTR_WO ( recover ) ;
2013-08-29 19:35:19 +02:00
2014-04-16 16:12:05 +02:00
static ssize_t util_string_read ( struct file * filp , struct kobject * kobj ,
struct bin_attribute * attr , char * buf ,
loff_t off , size_t count )
{
struct device * dev = kobj_to_dev ( kobj ) ;
struct pci_dev * pdev = to_pci_dev ( dev ) ;
2015-06-23 14:06:35 +02:00
struct zpci_dev * zdev = to_zpci ( pdev ) ;
2014-04-16 16:12:05 +02:00
return memory_read_from_buffer ( buf , count , & off , zdev - > util_str ,
sizeof ( zdev - > util_str ) ) ;
}
static BIN_ATTR_RO ( util_string , CLP_UTIL_STR_LEN ) ;
2015-11-27 11:22:57 +01:00
static ssize_t report_error_write ( struct file * filp , struct kobject * kobj ,
struct bin_attribute * attr , char * buf ,
loff_t off , size_t count )
{
struct zpci_report_error_header * report = ( void * ) buf ;
struct device * dev = kobj_to_dev ( kobj ) ;
struct pci_dev * pdev = to_pci_dev ( dev ) ;
struct zpci_dev * zdev = to_zpci ( pdev ) ;
int ret ;
if ( off | | ( count < sizeof ( * report ) ) )
return - EINVAL ;
ret = sclp_pci_report ( report , zdev - > fh , zdev - > fid ) ;
return ret ? ret : count ;
}
static BIN_ATTR ( report_error , S_IWUSR , NULL , report_error_write , PAGE_SIZE ) ;
2014-04-16 16:12:05 +02:00
static struct bin_attribute * zpci_bin_attrs [ ] = {
& bin_attr_util_string ,
2015-11-27 11:22:57 +01:00
& bin_attr_report_error ,
2014-04-16 16:12:05 +02:00
NULL ,
} ;
2014-04-16 16:11:00 +02:00
static struct attribute * zpci_dev_attrs [ ] = {
& dev_attr_function_id . attr ,
& dev_attr_function_handle . attr ,
& dev_attr_pchid . attr ,
& dev_attr_pfgid . attr ,
2014-04-16 16:12:05 +02:00
& dev_attr_pft . attr ,
& dev_attr_vfn . attr ,
& dev_attr_uid . attr ,
2014-04-16 16:11:00 +02:00
& dev_attr_recover . attr ,
NULL ,
} ;
static struct attribute_group zpci_attr_group = {
. attrs = zpci_dev_attrs ,
2014-04-16 16:12:05 +02:00
. bin_attrs = zpci_bin_attrs ,
} ;
static struct attribute * pfip_attrs [ ] = {
& dev_attr_segment0 . attr ,
& dev_attr_segment1 . attr ,
& dev_attr_segment2 . attr ,
& dev_attr_segment3 . attr ,
NULL ,
} ;
static struct attribute_group pfip_attr_group = {
. name = " pfip " ,
. attrs = pfip_attrs ,
2014-04-16 16:11:00 +02:00
} ;
2014-04-16 16:12:05 +02:00
2014-04-16 16:11:00 +02:00
const struct attribute_group * zpci_attr_groups [ ] = {
& zpci_attr_group ,
2014-04-16 16:12:05 +02:00
& pfip_attr_group ,
2012-11-29 14:36:55 +01:00
NULL ,
} ;