2019-05-27 08:55:01 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2014-10-08 19:55:01 +11:00
/*
* Copyright 2014 IBM Corp .
*/
# include <linux/module.h>
# include <linux/rcupdate.h>
# include <asm/errno.h>
2015-05-27 16:07:16 +10:00
# include <misc/cxl-base.h>
2023-07-18 08:31:01 -06:00
# include <linux/of.h>
2016-03-04 12:26:39 +01:00
# include <linux/of_platform.h>
2014-10-08 19:55:01 +11:00
# include "cxl.h"
/* protected by rcu */
static struct cxl_calls * cxl_calls ;
atomic_t cxl_use_count = ATOMIC_INIT ( 0 ) ;
EXPORT_SYMBOL ( cxl_use_count ) ;
# ifdef CONFIG_CXL_MODULE
static inline struct cxl_calls * cxl_calls_get ( void )
{
struct cxl_calls * calls = NULL ;
rcu_read_lock ( ) ;
calls = rcu_dereference ( cxl_calls ) ;
if ( calls & & ! try_module_get ( calls - > owner ) )
calls = NULL ;
rcu_read_unlock ( ) ;
return calls ;
}
static inline void cxl_calls_put ( struct cxl_calls * calls )
{
BUG_ON ( calls ! = cxl_calls ) ;
/* we don't need to rcu this, as we hold a reference to the module */
module_put ( cxl_calls - > owner ) ;
}
# else /* !defined CONFIG_CXL_MODULE */
static inline struct cxl_calls * cxl_calls_get ( void )
{
return cxl_calls ;
}
static inline void cxl_calls_put ( struct cxl_calls * calls ) { }
# endif /* CONFIG_CXL_MODULE */
2016-07-14 07:17:03 +10:00
/* AFU refcount management */
struct cxl_afu * cxl_afu_get ( struct cxl_afu * afu )
{
return ( get_device ( & afu - > dev ) = = NULL ) ? NULL : afu ;
}
EXPORT_SYMBOL_GPL ( cxl_afu_get ) ;
void cxl_afu_put ( struct cxl_afu * afu )
{
put_device ( & afu - > dev ) ;
}
EXPORT_SYMBOL_GPL ( cxl_afu_put ) ;
2014-10-08 19:55:01 +11:00
void cxl_slbia ( struct mm_struct * mm )
{
struct cxl_calls * calls ;
calls = cxl_calls_get ( ) ;
if ( ! calls )
return ;
if ( cxl_ctx_in_use ( ) )
calls - > cxl_slbia ( mm ) ;
cxl_calls_put ( calls ) ;
}
int register_cxl_calls ( struct cxl_calls * calls )
{
if ( cxl_calls )
return - EBUSY ;
rcu_assign_pointer ( cxl_calls , calls ) ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( register_cxl_calls ) ;
void unregister_cxl_calls ( struct cxl_calls * calls )
{
BUG_ON ( cxl_calls - > owner ! = calls - > owner ) ;
RCU_INIT_POINTER ( cxl_calls , NULL ) ;
synchronize_rcu ( ) ;
}
EXPORT_SYMBOL_GPL ( unregister_cxl_calls ) ;
2016-03-04 12:26:38 +01:00
int cxl_update_properties ( struct device_node * dn ,
struct property * new_prop )
{
return of_update_property ( dn , new_prop ) ;
}
EXPORT_SYMBOL_GPL ( cxl_update_properties ) ;
2016-03-04 12:26:39 +01:00
static int __init cxl_base_init ( void )
{
2016-07-12 11:30:11 +00:00
struct device_node * np ;
2016-03-04 12:26:39 +01:00
struct platform_device * dev ;
int count = 0 ;
/*
* Scan for compatible devices in guest only
*/
if ( cpu_has_feature ( CPU_FTR_HVMODE ) )
return 0 ;
2016-07-12 11:30:11 +00:00
for_each_compatible_node ( np , NULL , " ibm,coherent-platform-facility " ) {
2016-03-04 12:26:39 +01:00
dev = of_platform_device_create ( np , NULL , NULL ) ;
if ( dev )
count + + ;
}
pr_devel ( " Found %d cxl device(s) \n " , count ) ;
return 0 ;
}
2016-07-03 16:31:53 -04:00
device_initcall ( cxl_base_init ) ;