@ -147,75 +147,153 @@ static struct nfit_test *to_nfit_test(struct device *dev)
return container_of ( pdev , struct nfit_test , pdev ) ;
}
static int nfit_test_cmd_get_config_size ( struct nd_cmd_get_config_size * nd_cmd ,
unsigned int buf_len )
{
if ( buf_len < sizeof ( * nd_cmd ) )
return - EINVAL ;
nd_cmd - > status = 0 ;
nd_cmd - > config_size = LABEL_SIZE ;
nd_cmd - > max_xfer = SZ_4K ;
return 0 ;
}
static int nfit_test_cmd_get_config_data ( struct nd_cmd_get_config_data_hdr
* nd_cmd , unsigned int buf_len , void * label )
{
unsigned int len , offset = nd_cmd - > in_offset ;
int rc ;
if ( buf_len < sizeof ( * nd_cmd ) )
return - EINVAL ;
if ( offset > = LABEL_SIZE )
return - EINVAL ;
if ( nd_cmd - > in_length + sizeof ( * nd_cmd ) > buf_len )
return - EINVAL ;
nd_cmd - > status = 0 ;
len = min ( nd_cmd - > in_length , LABEL_SIZE - offset ) ;
memcpy ( nd_cmd - > out_buf , label + offset , len ) ;
rc = buf_len - sizeof ( * nd_cmd ) - len ;
return rc ;
}
static int nfit_test_cmd_set_config_data ( struct nd_cmd_set_config_hdr * nd_cmd ,
unsigned int buf_len , void * label )
{
unsigned int len , offset = nd_cmd - > in_offset ;
u32 * status ;
int rc ;
if ( buf_len < sizeof ( * nd_cmd ) )
return - EINVAL ;
if ( offset > = LABEL_SIZE )
return - EINVAL ;
if ( nd_cmd - > in_length + sizeof ( * nd_cmd ) + 4 > buf_len )
return - EINVAL ;
status = ( void * ) nd_cmd + nd_cmd - > in_length + sizeof ( * nd_cmd ) ;
* status = 0 ;
len = min ( nd_cmd - > in_length , LABEL_SIZE - offset ) ;
memcpy ( label + offset , nd_cmd - > in_buf , len ) ;
rc = buf_len - sizeof ( * nd_cmd ) - ( len + 4 ) ;
return rc ;
}
static int nfit_test_cmd_ars_cap ( struct nd_cmd_ars_cap * nd_cmd ,
unsigned int buf_len )
{
if ( buf_len < sizeof ( * nd_cmd ) )
return - EINVAL ;
nd_cmd - > max_ars_out = 256 ;
nd_cmd - > status = ( ND_ARS_PERSISTENT | ND_ARS_VOLATILE ) < < 16 ;
return 0 ;
}
static int nfit_test_cmd_ars_start ( struct nd_cmd_ars_start * nd_cmd ,
unsigned int buf_len )
{
if ( buf_len < sizeof ( * nd_cmd ) )
return - EINVAL ;
nd_cmd - > status = 0 ;
return 0 ;
}
static int nfit_test_cmd_ars_status ( struct nd_cmd_ars_status * nd_cmd ,
unsigned int buf_len )
{
if ( buf_len < sizeof ( * nd_cmd ) )
return - EINVAL ;
nd_cmd - > out_length = 256 ;
nd_cmd - > num_records = 0 ;
nd_cmd - > status = 0 ;
return 0 ;
}
static int nfit_test_ctl ( struct nvdimm_bus_descriptor * nd_desc ,
struct nvdimm * nvdimm , unsigned int cmd , void * buf ,
unsigned int buf_len )
{
struct acpi_nfit_desc * acpi_desc = to_acpi_desc ( nd_desc ) ;
struct nfit_test * t = container_of ( acpi_desc , typeof ( * t ) , acpi_desc ) ;
struct nfit_mem * nfit_mem = nvdimm_provider_data ( nvdimm ) ;
int i , rc ;
int i , rc = 0 ;
if ( nvdimm ) {
struct nfit_mem * nfit_mem = nvdimm_provider_data ( nvdimm ) ;
if ( ! nfit_mem | | ! test_bit ( cmd , & nfit_mem - > dsm_mask ) )
return - ENOTTY ;
if ( ! nfit_mem | | ! test_bit ( cmd , & nfit_mem - > dsm_mask ) )
return - ENOTTY ;
/* lookup label space for the given dimm */
for ( i = 0 ; i < ARRAY_SIZE ( handle ) ; i + + )
if ( __to_nfit_memdev ( nfit_mem ) - > device_handle = = handle [ i ] )
/* lookup label space for the given dimm */
for ( i = 0 ; i < ARRAY_SIZE ( handle ) ; i + + )
if ( __to_nfit_memdev ( nfit_mem ) - > device_handle = =
handle [ i ] )
break ;
if ( i > = ARRAY_SIZE ( handle ) )
return - ENXIO ;
switch ( cmd ) {
case ND_CMD_GET_CONFIG_SIZE :
rc = nfit_test_cmd_get_config_size ( buf , buf_len ) ;
break ;
if ( i > = ARRAY_SIZE ( handle ) )
return - ENXIO ;
case ND_CMD_GET_CONFIG_DATA :
rc = nfit_test_cmd_get_config_data ( buf , buf_len ,
t - > label [ i ] ) ;
break ;
case ND_CMD_SET_CONFIG_DATA :
rc = nfit_test_cmd_set_config_data ( buf , buf_len ,
t - > label [ i ] ) ;
break ;
default :
return - ENOTTY ;
}
} else {
if ( ! nd_desc | | ! test_bit ( cmd , & nd_desc - > dsm_mask ) )
return - ENOTTY ;
switch ( cmd ) {
case ND_CMD_GET_CONFIG_SIZE : {
struct nd_cmd_get_config_size * nd_cmd = buf ;
if ( buf_len < sizeof ( * nd_cmd ) )
return - EINVAL ;
nd_cmd - > status = 0 ;
nd_cmd - > config_size = LABEL_SIZE ;
nd_cmd - > max_xfer = SZ_4K ;
rc = 0 ;
break ;
}
case ND_CMD_GET_CONFIG_DATA : {
struct nd_cmd_get_config_data_hdr * nd_cmd = buf ;
unsigned int len , offset = nd_cmd - > in_offset ;
if ( buf_len < sizeof ( * nd_cmd ) )
return - EINVAL ;
if ( offset > = LABEL_SIZE )
return - EINVAL ;
if ( nd_cmd - > in_length + sizeof ( * nd_cmd ) > buf_len )
return - EINVAL ;
nd_cmd - > status = 0 ;
len = min ( nd_cmd - > in_length , LABEL_SIZE - offset ) ;
memcpy ( nd_cmd - > out_buf , t - > label [ i ] + offset , len ) ;
rc = buf_len - sizeof ( * nd_cmd ) - len ;
break ;
}
case ND_CMD_SET_CONFIG_DATA : {
struct nd_cmd_set_config_hdr * nd_cmd = buf ;
unsigned int len , offset = nd_cmd - > in_offset ;
u32 * status ;
if ( buf_len < sizeof ( * nd_cmd ) )
return - EINVAL ;
if ( offset > = LABEL_SIZE )
return - EINVAL ;
if ( nd_cmd - > in_length + sizeof ( * nd_cmd ) + 4 > buf_len )
return - EINVAL ;
status = buf + nd_cmd - > in_length + sizeof ( * nd_cmd ) ;
* status = 0 ;
len = min ( nd_cmd - > in_length , LABEL_SIZE - offset ) ;
memcpy ( t - > label [ i ] + offset , nd_cmd - > in_buf , len ) ;
rc = buf_len - sizeof ( * nd_cmd ) - ( len + 4 ) ;
break ;
}
default :
return - ENOTTY ;
switch ( cmd ) {
case ND_CMD_ARS_CAP :
rc = nfit_test_cmd_ars_cap ( buf , buf_len ) ;
break ;
case ND_CMD_ARS_START :
rc = nfit_test_cmd_ars_start ( buf , buf_len ) ;
break ;
case ND_CMD_ARS_STATUS :
rc = nfit_test_cmd_ars_status ( buf , buf_len ) ;
break ;
default :
return - ENOTTY ;
}
}
return rc ;
@ -876,6 +954,9 @@ static void nfit_test0_setup(struct nfit_test *t)
set_bit ( ND_CMD_GET_CONFIG_SIZE , & acpi_desc - > dimm_dsm_force_en ) ;
set_bit ( ND_CMD_GET_CONFIG_DATA , & acpi_desc - > dimm_dsm_force_en ) ;
set_bit ( ND_CMD_SET_CONFIG_DATA , & acpi_desc - > dimm_dsm_force_en ) ;
set_bit ( ND_CMD_ARS_CAP , & acpi_desc - > bus_dsm_force_en ) ;
set_bit ( ND_CMD_ARS_START , & acpi_desc - > bus_dsm_force_en ) ;
set_bit ( ND_CMD_ARS_STATUS , & acpi_desc - > bus_dsm_force_en ) ;
nd_desc = & acpi_desc - > nd_desc ;
nd_desc - > ndctl = nfit_test_ctl ;
}