2019-05-29 17:18:09 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2015-05-31 21:41:48 +03:00
/*
* Copyright ( c ) 2013 - 2015 Intel Corporation . All rights reserved .
*/
# include <linux/vmalloc.h>
# include <linux/module.h>
# include <linux/device.h>
# include <linux/sizes.h>
# include <linux/ndctl.h>
# include <linux/slab.h>
# include <linux/mm.h>
# include <linux/nd.h>
2015-06-09 23:09:36 +03:00
# include "label.h"
2015-05-31 21:41:48 +03:00
# include "nd.h"
static int nvdimm_probe ( struct device * dev )
{
struct nvdimm_drvdata * ndd ;
int rc ;
2019-01-19 19:45:56 +03:00
rc = nvdimm_security_setup_events ( dev ) ;
if ( rc < 0 ) {
dev_err ( dev , " security event setup failed: %d \n " , rc ) ;
return rc ;
}
2016-08-16 22:08:40 +03:00
rc = nvdimm_check_config_data ( dev ) ;
if ( rc ) {
/* not required for non-aliased nvdimm, ex. NVDIMM-N */
if ( rc = = - ENOTTY )
rc = 0 ;
return rc ;
}
2018-12-06 23:40:01 +03:00
/*
* The locked status bit reflects explicit status codes from the
* label reading commands , revalidate it each time the driver is
* activated and re - reads the label area .
*/
2018-06-13 19:08:36 +03:00
nvdimm_clear_locked ( dev ) ;
2015-05-31 21:41:48 +03:00
ndd = kzalloc ( sizeof ( * ndd ) , GFP_KERNEL ) ;
if ( ! ndd )
return - ENOMEM ;
dev_set_drvdata ( dev , ndd ) ;
2015-06-09 23:09:36 +03:00
ndd - > dpa . name = dev_name ( dev ) ;
ndd - > ns_current = - 1 ;
ndd - > ns_next = - 1 ;
ndd - > dpa . start = 0 ;
ndd - > dpa . end = - 1 ;
2015-05-31 21:41:48 +03:00
ndd - > dev = dev ;
2015-06-18 00:14:46 +03:00
get_device ( dev ) ;
kref_init ( & ndd - > kref ) ;
2015-05-31 21:41:48 +03:00
2018-12-06 23:40:01 +03:00
/*
* Attempt to unlock , if the DIMM supports security commands ,
* otherwise the locked indication is determined by explicit
* status codes from the label reading commands .
*/
rc = nvdimm_security_unlock ( dev ) ;
if ( rc < 0 )
2018-12-22 22:35:41 +03:00
dev_dbg ( dev , " failed to unlock dimm: %d \n " , rc ) ;
2018-12-06 23:40:01 +03:00
2018-06-13 19:08:36 +03:00
/*
* EACCES failures reading the namespace label - area - properties
* are interpreted as the DIMM capacity being locked but the
* namespace labels themselves being accessible .
*/
2015-05-31 21:41:48 +03:00
rc = nvdimm_init_nsarea ( ndd ) ;
2018-06-13 19:08:36 +03:00
if ( rc = = - EACCES ) {
/*
* See nvdimm_namespace_common_probe ( ) where we fail to
* allow namespaces to probe while the DIMM is locked ,
* but we do allow for namespace enumeration .
*/
2017-05-04 21:47:22 +03:00
nvdimm_set_locked ( dev ) ;
2018-06-13 19:08:36 +03:00
rc = 0 ;
}
2015-05-31 21:41:48 +03:00
if ( rc )
goto err ;
2018-06-13 19:08:36 +03:00
/*
* EACCES failures reading the namespace label - data are
* interpreted as the label area being locked in addition to the
* DIMM capacity . We fail the dimm probe to prevent regions from
* attempting to parse the label area .
*/
2018-10-11 02:39:20 +03:00
rc = nd_label_data_init ( ndd ) ;
2017-09-24 19:57:34 +03:00
if ( rc = = - EACCES )
nvdimm_set_locked ( dev ) ;
2015-05-31 21:41:48 +03:00
if ( rc )
goto err ;
dev_dbg ( dev , " config data size: %d \n " , ndd - > nsarea . config_size ) ;
2015-06-09 23:09:36 +03:00
nvdimm_bus_lock ( dev ) ;
2018-04-06 21:25:38 +03:00
if ( ndd - > ns_current > = 0 ) {
rc = nd_label_reserve_dpa ( ndd ) ;
if ( rc = = 0 )
2020-01-30 23:06:18 +03:00
nvdimm_set_labeling ( dev ) ;
2018-04-06 21:25:38 +03:00
}
2015-06-09 23:09:36 +03:00
nvdimm_bus_unlock ( dev ) ;
if ( rc )
goto err ;
2015-05-31 21:41:48 +03:00
return 0 ;
err :
2015-06-18 00:14:46 +03:00
put_ndd ( ndd ) ;
2015-05-31 21:41:48 +03:00
return rc ;
}
2021-02-12 20:10:43 +03:00
static void nvdimm_remove ( struct device * dev )
2015-05-31 21:41:48 +03:00
{
struct nvdimm_drvdata * ndd = dev_get_drvdata ( dev ) ;
2015-06-09 23:09:36 +03:00
nvdimm_bus_lock ( dev ) ;
dev_set_drvdata ( dev , NULL ) ;
nvdimm_bus_unlock ( dev ) ;
2015-06-18 00:14:46 +03:00
put_ndd ( ndd ) ;
2015-05-31 21:41:48 +03:00
}
static struct nd_device_driver nvdimm_driver = {
. probe = nvdimm_probe ,
. remove = nvdimm_remove ,
. drv = {
. name = " nvdimm " ,
} ,
. type = ND_DRIVER_DIMM ,
} ;
int __init nvdimm_init ( void )
{
return nd_driver_register ( & nvdimm_driver ) ;
}
2015-05-31 22:02:11 +03:00
void nvdimm_exit ( void )
2015-05-31 21:41:48 +03:00
{
driver_unregister ( & nvdimm_driver . drv ) ;
}
MODULE_ALIAS_ND_DEVICE ( ND_DEVICE_DIMM ) ;