2019-05-19 15:08:20 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2007-10-22 05:03:36 +04:00
# include <linux/virtio.h>
# include <linux/spinlock.h>
# include <linux/virtio_config.h>
2022-06-22 09:38:36 +03:00
# include <linux/virtio_anchor.h>
2011-07-04 00:20:30 +04:00
# include <linux/module.h>
2012-05-03 06:20:51 +04:00
# include <linux/idr.h>
2021-07-27 08:23:52 +03:00
# include <linux/of.h>
2014-12-04 19:49:58 +03:00
# include <uapi/linux/virtio_ids.h>
2007-10-22 05:03:36 +04:00
2008-05-31 00:09:42 +04:00
/* Unique numbering for virtio devices. */
2012-05-03 06:20:51 +04:00
static DEFINE_IDA ( virtio_index_ida ) ;
2008-05-31 00:09:42 +04:00
2007-10-22 05:03:36 +04:00
static ssize_t device_show ( struct device * _d ,
struct device_attribute * attr , char * buf )
{
2012-12-11 04:34:50 +04:00
struct virtio_device * dev = dev_to_virtio ( _d ) ;
2022-11-24 19:12:14 +03:00
return sysfs_emit ( buf , " 0x%04x \n " , dev - > id . device ) ;
2007-10-22 05:03:36 +04:00
}
2013-10-08 05:27:39 +04:00
static DEVICE_ATTR_RO ( device ) ;
2007-10-22 05:03:36 +04:00
static ssize_t vendor_show ( struct device * _d ,
struct device_attribute * attr , char * buf )
{
2012-12-11 04:34:50 +04:00
struct virtio_device * dev = dev_to_virtio ( _d ) ;
2022-11-24 19:12:14 +03:00
return sysfs_emit ( buf , " 0x%04x \n " , dev - > id . vendor ) ;
2007-10-22 05:03:36 +04:00
}
2013-10-08 05:27:39 +04:00
static DEVICE_ATTR_RO ( vendor ) ;
2007-10-22 05:03:36 +04:00
static ssize_t status_show ( struct device * _d ,
struct device_attribute * attr , char * buf )
{
2012-12-11 04:34:50 +04:00
struct virtio_device * dev = dev_to_virtio ( _d ) ;
2022-11-24 19:12:14 +03:00
return sysfs_emit ( buf , " 0x%08x \n " , dev - > config - > get_status ( dev ) ) ;
2007-10-22 05:03:36 +04:00
}
2013-10-08 05:27:39 +04:00
static DEVICE_ATTR_RO ( status ) ;
2007-10-22 05:03:39 +04:00
static ssize_t modalias_show ( struct device * _d ,
struct device_attribute * attr , char * buf )
{
2012-12-11 04:34:50 +04:00
struct virtio_device * dev = dev_to_virtio ( _d ) ;
2022-11-24 19:12:14 +03:00
return sysfs_emit ( buf , " virtio:d%08Xv%08X \n " ,
2007-10-22 05:03:39 +04:00
dev - > id . device , dev - > id . vendor ) ;
}
2013-10-08 05:27:39 +04:00
static DEVICE_ATTR_RO ( modalias ) ;
2009-06-13 08:16:37 +04:00
static ssize_t features_show ( struct device * _d ,
struct device_attribute * attr , char * buf )
{
2012-12-11 04:34:50 +04:00
struct virtio_device * dev = dev_to_virtio ( _d ) ;
2009-06-13 08:16:37 +04:00
unsigned int i ;
ssize_t len = 0 ;
/* We actually represent this as a bitstring, as it could be
* arbitrary length in future . */
2014-10-07 18:39:42 +04:00
for ( i = 0 ; i < sizeof ( dev - > features ) * 8 ; i + + )
2022-11-24 19:12:14 +03:00
len + = sysfs_emit_at ( buf , len , " %c " ,
2014-10-07 18:39:42 +04:00
__virtio_test_bit ( dev , i ) ? ' 1 ' : ' 0 ' ) ;
2022-11-24 19:12:14 +03:00
len + = sysfs_emit_at ( buf , len , " \n " ) ;
2009-06-13 08:16:37 +04:00
return len ;
}
2013-10-08 05:27:39 +04:00
static DEVICE_ATTR_RO ( features ) ;
static struct attribute * virtio_dev_attrs [ ] = {
& dev_attr_device . attr ,
& dev_attr_vendor . attr ,
& dev_attr_status . attr ,
& dev_attr_modalias . attr ,
& dev_attr_features . attr ,
NULL ,
2007-10-22 05:03:36 +04:00
} ;
2013-10-08 05:27:39 +04:00
ATTRIBUTE_GROUPS ( virtio_dev ) ;
2007-10-22 05:03:36 +04:00
static inline int virtio_id_match ( const struct virtio_device * dev ,
const struct virtio_device_id * id )
{
2009-05-26 17:46:10 +04:00
if ( id - > device ! = dev - > id . device & & id - > device ! = VIRTIO_DEV_ANY_ID )
2007-10-22 05:03:36 +04:00
return 0 ;
2009-05-26 17:46:09 +04:00
return id - > vendor = = VIRTIO_DEV_ANY_ID | | id - > vendor = = dev - > id . vendor ;
2007-10-22 05:03:36 +04:00
}
/* This looks through all the IDs a driver claims to support. If any of them
* match , we return 1 and the kernel will call virtio_dev_probe ( ) . */
static int virtio_dev_match ( struct device * _dv , struct device_driver * _dr )
{
unsigned int i ;
2012-12-11 04:34:50 +04:00
struct virtio_device * dev = dev_to_virtio ( _dv ) ;
2007-10-22 05:03:36 +04:00
const struct virtio_device_id * ids ;
2012-12-10 12:38:33 +04:00
ids = drv_to_virtio ( _dr ) - > id_table ;
2007-10-22 05:03:36 +04:00
for ( i = 0 ; ids [ i ] . device ; i + + )
if ( virtio_id_match ( dev , & ids [ i ] ) )
return 1 ;
return 0 ;
}
2023-01-11 14:30:17 +03:00
static int virtio_uevent ( const struct device * _dv , struct kobj_uevent_env * env )
2007-10-22 05:03:39 +04:00
{
2023-01-11 14:30:17 +03:00
const struct virtio_device * dev = dev_to_virtio ( _dv ) ;
2007-10-22 05:03:39 +04:00
return add_uevent_var ( env , " MODALIAS=virtio:d%08Xv%08X " ,
dev - > id . device , dev - > id . vendor ) ;
}
2008-05-03 06:50:50 +04:00
void virtio_check_driver_offered_feature ( const struct virtio_device * vdev ,
unsigned int fbit )
{
unsigned int i ;
2012-12-10 12:38:33 +04:00
struct virtio_driver * drv = drv_to_virtio ( vdev - > dev . driver ) ;
2008-05-03 06:50:50 +04:00
for ( i = 0 ; i < drv - > feature_table_size ; i + + )
if ( drv - > feature_table [ i ] = = fbit )
return ;
2014-10-23 19:07:47 +04:00
if ( drv - > feature_table_legacy ) {
for ( i = 0 ; i < drv - > feature_table_size_legacy ; i + + )
if ( drv - > feature_table_legacy [ i ] = = fbit )
return ;
}
2008-05-03 06:50:50 +04:00
BUG ( ) ;
}
EXPORT_SYMBOL_GPL ( virtio_check_driver_offered_feature ) ;
2014-10-15 03:51:55 +04:00
static void __virtio_config_changed ( struct virtio_device * dev )
{
struct virtio_driver * drv = drv_to_virtio ( dev - > dev . driver ) ;
if ( ! dev - > config_enabled )
dev - > config_change_pending = true ;
else if ( drv & & drv - > config_changed )
drv - > config_changed ( dev ) ;
}
void virtio_config_changed ( struct virtio_device * dev )
{
unsigned long flags ;
spin_lock_irqsave ( & dev - > config_lock , flags ) ;
__virtio_config_changed ( dev ) ;
spin_unlock_irqrestore ( & dev - > config_lock , flags ) ;
}
EXPORT_SYMBOL_GPL ( virtio_config_changed ) ;
2021-02-20 19:28:18 +03:00
static void virtio_config_disable ( struct virtio_device * dev )
2014-10-15 03:51:55 +04:00
{
spin_lock_irq ( & dev - > config_lock ) ;
dev - > config_enabled = false ;
spin_unlock_irq ( & dev - > config_lock ) ;
}
2021-02-20 19:28:18 +03:00
static void virtio_config_enable ( struct virtio_device * dev )
2014-10-15 03:51:55 +04:00
{
spin_lock_irq ( & dev - > config_lock ) ;
dev - > config_enabled = true ;
if ( dev - > config_change_pending )
__virtio_config_changed ( dev ) ;
dev - > config_change_pending = false ;
spin_unlock_irq ( & dev - > config_lock ) ;
}
2017-02-03 06:16:01 +03:00
void virtio_add_status ( struct virtio_device * dev , unsigned int status )
{
2019-01-31 15:53:14 +03:00
might_sleep ( ) ;
2017-02-03 06:16:01 +03:00
dev - > config - > set_status ( dev , dev - > config - > get_status ( dev ) | status ) ;
}
EXPORT_SYMBOL_GPL ( virtio_add_status ) ;
2014-10-15 03:51:55 +04:00
2022-01-14 22:58:41 +03:00
/* Do some validation, then set FEATURES_OK */
static int virtio_features_ok ( struct virtio_device * dev )
2014-12-11 14:37:13 +03:00
{
2022-04-18 05:54:35 +03:00
unsigned int status ;
2014-12-11 14:37:13 +03:00
2019-01-31 15:53:14 +03:00
might_sleep ( ) ;
2014-12-11 14:37:13 +03:00
2022-06-22 09:38:36 +03:00
if ( virtio_check_mem_acc_cb ( dev ) ) {
2020-09-10 11:53:49 +03:00
if ( ! virtio_has_feature ( dev , VIRTIO_F_VERSION_1 ) ) {
dev_warn ( & dev - > dev ,
" device must provide VIRTIO_F_VERSION_1 \n " ) ;
return - ENODEV ;
}
if ( ! virtio_has_feature ( dev , VIRTIO_F_ACCESS_PLATFORM ) ) {
dev_warn ( & dev - > dev ,
" device must provide VIRTIO_F_ACCESS_PLATFORM \n " ) ;
return - ENODEV ;
}
}
2014-12-11 14:37:13 +03:00
if ( ! virtio_has_feature ( dev , VIRTIO_F_VERSION_1 ) )
return 0 ;
2017-02-03 06:16:01 +03:00
virtio_add_status ( dev , VIRTIO_CONFIG_S_FEATURES_OK ) ;
2014-12-11 14:37:13 +03:00
status = dev - > config - > get_status ( dev ) ;
if ( ! ( status & VIRTIO_CONFIG_S_FEATURES_OK ) ) {
dev_err ( & dev - > dev , " virtio: device refuses features: %x \n " ,
status ) ;
return - ENODEV ;
}
return 0 ;
}
2022-01-14 23:54:01 +03:00
/**
* virtio_reset_device - quiesce device for removal
* @ dev : the device to reset
*
* Prevents device from sending interrupts and accessing memory .
*
* Generally used for cleanup during driver / device removal .
*
* Once this has been invoked , caller must ensure that
* virtqueue_notify / virtqueue_kick are not in progress .
*
* Note : this guarantees that vq callbacks are not in progress , however caller
* is responsible for preventing access from other contexts , such as a system
* call / workqueue / bh . Invoking virtio_break_device then flushing any such
* contexts is one way to handle that .
* */
2021-10-13 13:55:44 +03:00
void virtio_reset_device ( struct virtio_device * dev )
{
2022-06-22 04:29:40 +03:00
# ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
2022-05-27 09:01:19 +03:00
/*
* The below virtio_synchronize_cbs ( ) guarantees that any
* interrupt for this line arriving after
* virtio_synchronize_vqs ( ) has completed is guaranteed to see
* vq - > broken as true .
*/
virtio_break_device ( dev ) ;
virtio_synchronize_cbs ( dev ) ;
2022-06-22 04:29:40 +03:00
# endif
2022-05-27 09:01:19 +03:00
2021-10-13 13:55:44 +03:00
dev - > config - > reset ( dev ) ;
}
EXPORT_SYMBOL_GPL ( virtio_reset_device ) ;
2007-10-22 05:03:36 +04:00
static int virtio_dev_probe ( struct device * _d )
{
2008-05-03 06:50:50 +04:00
int err , i ;
2012-12-11 04:34:50 +04:00
struct virtio_device * dev = dev_to_virtio ( _d ) ;
2012-12-10 12:38:33 +04:00
struct virtio_driver * drv = drv_to_virtio ( dev - > dev . driver ) ;
2014-10-07 18:39:43 +04:00
u64 device_features ;
2014-10-23 18:57:30 +04:00
u64 driver_features ;
2014-10-23 19:07:47 +04:00
u64 driver_features_legacy ;
2007-10-22 05:03:36 +04:00
2008-05-03 06:50:50 +04:00
/* We have a driver! */
2017-02-03 06:16:01 +03:00
virtio_add_status ( dev , VIRTIO_CONFIG_S_DRIVER ) ;
2008-05-03 06:50:50 +04:00
/* Figure out what features the device supports. */
device_features = dev - > config - > get_features ( dev ) ;
2014-10-23 18:57:30 +04:00
/* Figure out what features the driver supports. */
driver_features = 0 ;
2008-05-03 06:50:50 +04:00
for ( i = 0 ; i < drv - > feature_table_size ; i + + ) {
unsigned int f = drv - > feature_table [ i ] ;
2014-10-07 18:39:43 +04:00
BUG_ON ( f > = 64 ) ;
2014-10-23 18:57:30 +04:00
driver_features | = ( 1ULL < < f ) ;
2008-05-03 06:50:50 +04:00
}
2014-10-23 19:07:47 +04:00
/* Some drivers have a separate feature table for virtio v1.0 */
if ( drv - > feature_table_legacy ) {
driver_features_legacy = 0 ;
for ( i = 0 ; i < drv - > feature_table_size_legacy ; i + + ) {
unsigned int f = drv - > feature_table_legacy [ i ] ;
BUG_ON ( f > = 64 ) ;
driver_features_legacy | = ( 1ULL < < f ) ;
}
} else {
driver_features_legacy = driver_features ;
}
2014-12-01 16:52:40 +03:00
if ( device_features & ( 1ULL < < VIRTIO_F_VERSION_1 ) )
2014-10-23 19:07:47 +04:00
dev - > features = driver_features & device_features ;
else
dev - > features = driver_features_legacy & device_features ;
2014-10-23 18:57:30 +04:00
2008-07-25 21:06:07 +04:00
/* Transport features always preserved to pass to finalize_features. */
2008-07-25 21:06:07 +04:00
for ( i = VIRTIO_TRANSPORT_F_START ; i < VIRTIO_TRANSPORT_F_END ; i + + )
2014-10-07 18:39:43 +04:00
if ( device_features & ( 1ULL < < i ) )
2014-10-07 18:39:42 +04:00
__virtio_set_bit ( dev , i ) ;
2008-07-25 21:06:07 +04:00
2022-01-14 22:58:41 +03:00
err = dev - > config - > finalize_features ( dev ) ;
if ( err )
goto err ;
2017-03-29 19:06:20 +03:00
if ( drv - > validate ) {
2022-01-14 22:58:41 +03:00
u64 features = dev - > features ;
2017-03-29 19:06:20 +03:00
err = drv - > validate ( dev ) ;
if ( err )
goto err ;
2022-01-14 22:58:41 +03:00
/* Did validation change any features? Then write them again. */
if ( features ! = dev - > features ) {
err = dev - > config - > finalize_features ( dev ) ;
if ( err )
goto err ;
}
2017-03-29 19:06:20 +03:00
}
2022-01-14 22:58:41 +03:00
err = virtio_features_ok ( dev ) ;
2014-12-04 21:20:27 +03:00
if ( err )
goto err ;
2009-06-13 08:16:35 +04:00
2007-10-22 05:03:36 +04:00
err = drv - > probe ( dev ) ;
if ( err )
2014-10-22 18:41:38 +04:00
goto err ;
2014-10-15 03:51:55 +04:00
2015-02-17 08:42:44 +03:00
/* If probe didn't do it, mark device DRIVER_OK ourselves. */
if ( ! ( dev - > config - > get_status ( dev ) & VIRTIO_CONFIG_S_DRIVER_OK ) )
virtio_device_ready ( dev ) ;
2014-10-22 18:41:38 +04:00
if ( drv - > scan )
drv - > scan ( dev ) ;
2009-06-13 08:16:35 +04:00
2014-10-22 18:41:38 +04:00
virtio_config_enable ( dev ) ;
return 0 ;
err :
2017-02-03 06:16:01 +03:00
virtio_add_status ( dev , VIRTIO_CONFIG_S_FAILED ) ;
2007-10-22 05:03:36 +04:00
return err ;
2014-10-22 18:41:38 +04:00
2007-10-22 05:03:36 +04:00
}
2021-07-13 22:35:22 +03:00
static void virtio_dev_remove ( struct device * _d )
2007-11-19 19:20:42 +03:00
{
2012-12-11 04:34:50 +04:00
struct virtio_device * dev = dev_to_virtio ( _d ) ;
2012-12-10 12:38:33 +04:00
struct virtio_driver * drv = drv_to_virtio ( dev - > dev . driver ) ;
2007-11-19 19:20:42 +03:00
2014-10-15 03:51:55 +04:00
virtio_config_disable ( dev ) ;
2007-11-19 19:20:42 +03:00
drv - > remove ( dev ) ;
2008-02-05 07:50:03 +03:00
/* Driver should have reset device. */
2012-09-28 09:35:16 +04:00
WARN_ON_ONCE ( dev - > config - > get_status ( dev ) ) ;
2008-02-05 07:50:03 +03:00
/* Acknowledge the device's existence again. */
2017-02-03 06:16:01 +03:00
virtio_add_status ( dev , VIRTIO_CONFIG_S_ACKNOWLEDGE ) ;
2021-07-27 08:23:52 +03:00
of_node_put ( dev - > dev . of_node ) ;
2007-11-19 19:20:42 +03:00
}
2008-06-13 16:46:40 +04:00
static struct bus_type virtio_bus = {
. name = " virtio " ,
. match = virtio_dev_match ,
2013-10-08 05:27:39 +04:00
. dev_groups = virtio_dev_groups ,
2008-06-13 16:46:40 +04:00
. uevent = virtio_uevent ,
. probe = virtio_dev_probe ,
. remove = virtio_dev_remove ,
} ;
2007-10-22 05:03:36 +04:00
int register_virtio_driver ( struct virtio_driver * driver )
{
2008-05-03 06:50:50 +04:00
/* Catch this early. */
BUG_ON ( driver - > feature_table_size & & ! driver - > feature_table ) ;
2007-10-22 05:03:36 +04:00
driver - > driver . bus = & virtio_bus ;
return driver_register ( & driver - > driver ) ;
}
EXPORT_SYMBOL_GPL ( register_virtio_driver ) ;
void unregister_virtio_driver ( struct virtio_driver * driver )
{
driver_unregister ( & driver - > driver ) ;
}
EXPORT_SYMBOL_GPL ( unregister_virtio_driver ) ;
2021-07-27 08:23:52 +03:00
static int virtio_device_of_init ( struct virtio_device * dev )
{
struct device_node * np , * pnode = dev_of_node ( dev - > dev . parent ) ;
char compat [ ] = " virtio,deviceXXXXXXXX " ;
int ret , count ;
if ( ! pnode )
return 0 ;
count = of_get_available_child_count ( pnode ) ;
if ( ! count )
return 0 ;
/* There can be only 1 child node */
if ( WARN_ON ( count > 1 ) )
return - EINVAL ;
np = of_get_next_available_child ( pnode , NULL ) ;
if ( WARN_ON ( ! np ) )
return - ENODEV ;
ret = snprintf ( compat , sizeof ( compat ) , " virtio,device%x " , dev - > id . device ) ;
BUG_ON ( ret > = sizeof ( compat ) ) ;
2021-09-13 13:38:36 +03:00
/*
* On powerpc / pseries virtio devices are PCI devices so PCI
* vendor / device ids play the role of the " compatible " property .
* Simply don ' t init of_node in this case .
*/
2021-07-27 08:23:52 +03:00
if ( ! of_device_is_compatible ( np , compat ) ) {
2021-09-13 13:38:36 +03:00
ret = 0 ;
2021-07-27 08:23:52 +03:00
goto out ;
}
dev - > dev . of_node = np ;
return 0 ;
out :
of_node_put ( np ) ;
return ret ;
}
2017-12-21 15:39:50 +03:00
/**
* register_virtio_device - register virtio device
* @ dev : virtio device to be registered
*
* On error , the caller must call put_device on & @ dev - > dev ( and not kfree ) ,
* as another code path may have obtained a reference to @ dev .
*
* Returns : 0 on suceess , - error on failure
*/
2007-10-22 05:03:36 +04:00
int register_virtio_device ( struct virtio_device * dev )
{
int err ;
dev - > dev . bus = & virtio_bus ;
2017-12-21 15:39:50 +03:00
device_initialize ( & dev - > dev ) ;
2008-05-31 00:09:42 +04:00
/* Assign a unique device index and hence name. */
2022-05-27 10:33:02 +03:00
err = ida_alloc ( & virtio_index_ida , GFP_KERNEL ) ;
2012-05-03 06:20:51 +04:00
if ( err < 0 )
goto out ;
dev - > index = err ;
2022-07-07 06:17:51 +03:00
err = dev_set_name ( & dev - > dev , " virtio%u " , dev - > index ) ;
if ( err )
goto out_ida_remove ;
2007-10-22 05:03:36 +04:00
2021-07-27 08:23:52 +03:00
err = virtio_device_of_init ( dev ) ;
if ( err )
goto out_ida_remove ;
2014-10-15 03:51:55 +04:00
spin_lock_init ( & dev - > config_lock ) ;
dev - > config_enabled = false ;
dev - > config_change_pending = false ;
2022-05-27 09:01:19 +03:00
INIT_LIST_HEAD ( & dev - > vqs ) ;
spin_lock_init ( & dev - > vqs_list_lock ) ;
2008-02-05 07:50:03 +03:00
/* We always start by resetting the device, in case a previous
* driver messed it up . This also tests that code path a little . */
2022-05-27 09:01:13 +03:00
virtio_reset_device ( dev ) ;
2008-02-05 07:50:03 +03:00
2007-10-22 05:03:36 +04:00
/* Acknowledge that we've seen the device. */
2017-02-03 06:16:01 +03:00
virtio_add_status ( dev , VIRTIO_CONFIG_S_ACKNOWLEDGE ) ;
2007-10-22 05:03:36 +04:00
2017-12-21 15:39:50 +03:00
/*
* device_add ( ) causes the bus infrastructure to look for a matching
* driver .
*/
err = device_add ( & dev - > dev ) ;
2017-11-29 04:23:01 +03:00
if ( err )
2021-07-27 08:23:52 +03:00
goto out_of_node_put ;
return 0 ;
out_of_node_put :
of_node_put ( dev - > dev . of_node ) ;
out_ida_remove :
2022-05-27 10:33:02 +03:00
ida_free ( & virtio_index_ida , dev - > index ) ;
2012-05-03 06:20:51 +04:00
out :
2021-07-27 08:23:52 +03:00
virtio_add_status ( dev , VIRTIO_CONFIG_S_FAILED ) ;
2007-10-22 05:03:36 +04:00
return err ;
}
EXPORT_SYMBOL_GPL ( register_virtio_device ) ;
2020-08-18 10:13:41 +03:00
bool is_virtio_device ( struct device * dev )
{
return dev - > bus = = & virtio_bus ;
}
EXPORT_SYMBOL_GPL ( is_virtio_device ) ;
2007-10-22 05:03:36 +04:00
void unregister_virtio_device ( struct virtio_device * dev )
{
2012-11-09 08:24:12 +04:00
int index = dev - > index ; /* save for after device release */
2007-10-22 05:03:36 +04:00
device_unregister ( & dev - > dev ) ;
2022-05-27 10:33:02 +03:00
ida_free ( & virtio_index_ida , index ) ;
2007-10-22 05:03:36 +04:00
}
EXPORT_SYMBOL_GPL ( unregister_virtio_device ) ;
2014-10-14 04:10:35 +04:00
# ifdef CONFIG_PM_SLEEP
int virtio_device_freeze ( struct virtio_device * dev )
{
struct virtio_driver * drv = drv_to_virtio ( dev - > dev . driver ) ;
2014-10-15 03:51:55 +04:00
virtio_config_disable ( dev ) ;
2014-10-14 04:10:35 +04:00
dev - > failed = dev - > config - > get_status ( dev ) & VIRTIO_CONFIG_S_FAILED ;
if ( drv & & drv - > freeze )
return drv - > freeze ( dev ) ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( virtio_device_freeze ) ;
int virtio_device_restore ( struct virtio_device * dev )
{
struct virtio_driver * drv = drv_to_virtio ( dev - > dev . driver ) ;
2014-12-04 21:20:27 +03:00
int ret ;
2014-10-14 04:10:35 +04:00
/* We always start by resetting the device, in case a previous
* driver messed it up . */
2022-05-27 09:01:13 +03:00
virtio_reset_device ( dev ) ;
2014-10-14 04:10:35 +04:00
/* Acknowledge that we've seen the device. */
2017-02-03 06:16:01 +03:00
virtio_add_status ( dev , VIRTIO_CONFIG_S_ACKNOWLEDGE ) ;
2014-10-14 04:10:35 +04:00
/* Maybe driver failed before freeze.
* Restore the failed status , for debugging . */
if ( dev - > failed )
2017-02-03 06:16:01 +03:00
virtio_add_status ( dev , VIRTIO_CONFIG_S_FAILED ) ;
2014-10-14 04:10:35 +04:00
if ( ! drv )
return 0 ;
/* We have a driver! */
2017-02-03 06:16:01 +03:00
virtio_add_status ( dev , VIRTIO_CONFIG_S_DRIVER ) ;
2014-10-14 04:10:35 +04:00
2022-01-14 22:58:41 +03:00
ret = dev - > config - > finalize_features ( dev ) ;
if ( ret )
goto err ;
ret = virtio_features_ok ( dev ) ;
2014-12-04 21:20:27 +03:00
if ( ret )
goto err ;
2014-10-14 04:10:35 +04:00
if ( drv - > restore ) {
2014-12-04 21:20:27 +03:00
ret = drv - > restore ( dev ) ;
if ( ret )
goto err ;
2014-10-14 04:10:35 +04:00
}
2022-05-27 09:01:12 +03:00
/* If restore didn't do it, mark device DRIVER_OK ourselves. */
if ( ! ( dev - > config - > get_status ( dev ) & VIRTIO_CONFIG_S_DRIVER_OK ) )
virtio_device_ready ( dev ) ;
2014-10-14 04:10:35 +04:00
2014-10-15 03:51:55 +04:00
virtio_config_enable ( dev ) ;
2014-10-14 04:10:35 +04:00
return 0 ;
2014-12-04 21:20:27 +03:00
err :
2017-02-03 06:16:01 +03:00
virtio_add_status ( dev , VIRTIO_CONFIG_S_FAILED ) ;
2014-12-04 21:20:27 +03:00
return ret ;
2014-10-14 04:10:35 +04:00
}
EXPORT_SYMBOL_GPL ( virtio_device_restore ) ;
# endif
2007-10-22 05:03:36 +04:00
static int virtio_init ( void )
{
if ( bus_register ( & virtio_bus ) ! = 0 )
panic ( " virtio bus registration failed " ) ;
return 0 ;
}
2008-02-05 07:50:05 +03:00
static void __exit virtio_exit ( void )
{
bus_unregister ( & virtio_bus ) ;
2015-09-17 03:29:17 +03:00
ida_destroy ( & virtio_index_ida ) ;
2008-02-05 07:50:05 +03:00
}
2007-10-22 05:03:36 +04:00
core_initcall ( virtio_init ) ;
2008-02-05 07:50:05 +03:00
module_exit ( virtio_exit ) ;
MODULE_LICENSE ( " GPL " ) ;