@ -28,6 +28,7 @@
# include "qapi/visitor.h"
# include "qemu/config-file.h"
# include "qemu/error-report.h"
# include "qemu/main-loop.h"
# include "qom/object_interfaces.h"
# include "hw/virtio/virtio-crypto.h"
@ -203,17 +204,53 @@ static int cryptodev_backend_account(CryptoDevBackend *backend,
return len ;
}
static void cryptodev_backend_throttle_timer_cb ( void * opaque )
{
CryptoDevBackend * backend = ( CryptoDevBackend * ) opaque ;
CryptoDevBackendOpInfo * op_info , * tmpop ;
int ret ;
QTAILQ_FOREACH_SAFE ( op_info , & backend - > opinfos , next , tmpop ) {
QTAILQ_REMOVE ( & backend - > opinfos , op_info , next ) ;
ret = cryptodev_backend_account ( backend , op_info ) ;
if ( ret < 0 ) {
op_info - > cb ( op_info - > opaque , ret ) ;
continue ;
}
throttle_account ( & backend - > ts , true , ret ) ;
cryptodev_backend_operation ( backend , op_info ) ;
if ( throttle_enabled ( & backend - > tc ) & &
throttle_schedule_timer ( & backend - > ts , & backend - > tt , true ) ) {
break ;
}
}
}
int cryptodev_backend_crypto_operation (
CryptoDevBackend * backend ,
CryptoDevBackendOpInfo * op_info )
{
int ret ;
if ( ! throttle_enabled ( & backend - > tc ) ) {
goto do_account ;
}
if ( throttle_schedule_timer ( & backend - > ts , & backend - > tt , true ) | |
! QTAILQ_EMPTY ( & backend - > opinfos ) ) {
QTAILQ_INSERT_TAIL ( & backend - > opinfos , op_info , next ) ;
return 0 ;
}
do_account :
ret = cryptodev_backend_account ( backend , op_info ) ;
if ( ret < 0 ) {
return ret ;
}
throttle_account ( & backend - > ts , true , ret ) ;
return cryptodev_backend_operation ( backend , op_info ) ;
}
@ -245,12 +282,98 @@ cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
backend - > conf . peers . queues = value ;
}
static void cryptodev_backend_set_throttle ( CryptoDevBackend * backend , int field ,
uint64_t value , Error * * errp )
{
uint64_t orig = backend - > tc . buckets [ field ] . avg ;
bool enabled = throttle_enabled ( & backend - > tc ) ;
if ( orig = = value ) {
return ;
}
backend - > tc . buckets [ field ] . avg = value ;
if ( ! throttle_enabled ( & backend - > tc ) ) {
throttle_timers_destroy ( & backend - > tt ) ;
cryptodev_backend_throttle_timer_cb ( backend ) ; /* drain opinfos */
return ;
}
if ( ! throttle_is_valid ( & backend - > tc , errp ) ) {
backend - > tc . buckets [ field ] . avg = orig ; /* revert change */
return ;
}
if ( ! enabled ) {
throttle_init ( & backend - > ts ) ;
throttle_timers_init ( & backend - > tt , qemu_get_aio_context ( ) ,
QEMU_CLOCK_REALTIME ,
cryptodev_backend_throttle_timer_cb , /* FIXME */
cryptodev_backend_throttle_timer_cb , backend ) ;
}
throttle_config ( & backend - > ts , QEMU_CLOCK_REALTIME , & backend - > tc ) ;
}
static void cryptodev_backend_get_bps ( Object * obj , Visitor * v ,
const char * name , void * opaque ,
Error * * errp )
{
CryptoDevBackend * backend = CRYPTODEV_BACKEND ( obj ) ;
uint64_t value = backend - > tc . buckets [ THROTTLE_BPS_TOTAL ] . avg ;
visit_type_uint64 ( v , name , & value , errp ) ;
}
static void cryptodev_backend_set_bps ( Object * obj , Visitor * v , const char * name ,
void * opaque , Error * * errp )
{
CryptoDevBackend * backend = CRYPTODEV_BACKEND ( obj ) ;
uint64_t value ;
if ( ! visit_type_uint64 ( v , name , & value , errp ) ) {
return ;
}
cryptodev_backend_set_throttle ( backend , THROTTLE_BPS_TOTAL , value , errp ) ;
}
static void cryptodev_backend_get_ops ( Object * obj , Visitor * v , const char * name ,
void * opaque , Error * * errp )
{
CryptoDevBackend * backend = CRYPTODEV_BACKEND ( obj ) ;
uint64_t value = backend - > tc . buckets [ THROTTLE_OPS_TOTAL ] . avg ;
visit_type_uint64 ( v , name , & value , errp ) ;
}
static void cryptodev_backend_set_ops ( Object * obj , Visitor * v ,
const char * name , void * opaque ,
Error * * errp )
{
CryptoDevBackend * backend = CRYPTODEV_BACKEND ( obj ) ;
uint64_t value ;
if ( ! visit_type_uint64 ( v , name , & value , errp ) ) {
return ;
}
cryptodev_backend_set_throttle ( backend , THROTTLE_OPS_TOTAL , value , errp ) ;
}
static void
cryptodev_backend_complete ( UserCreatable * uc , Error * * errp )
{
CryptoDevBackend * backend = CRYPTODEV_BACKEND ( uc ) ;
CryptoDevBackendClass * bc = CRYPTODEV_BACKEND_GET_CLASS ( uc ) ;
uint32_t services ;
uint64_t value ;
QTAILQ_INIT ( & backend - > opinfos ) ;
value = backend - > tc . buckets [ THROTTLE_OPS_TOTAL ] . avg ;
cryptodev_backend_set_throttle ( backend , THROTTLE_OPS_TOTAL , value , errp ) ;
value = backend - > tc . buckets [ THROTTLE_BPS_TOTAL ] . avg ;
cryptodev_backend_set_throttle ( backend , THROTTLE_BPS_TOTAL , value , errp ) ;
if ( bc - > init ) {
bc - > init ( backend , errp ) ;
@ -294,8 +417,12 @@ cryptodev_backend_can_be_deleted(UserCreatable *uc)
static void cryptodev_backend_instance_init ( Object * obj )
{
CryptoDevBackend * backend = CRYPTODEV_BACKEND ( obj ) ;
/* Initialize devices' queues property to 1 */
object_property_set_int ( obj , " queues " , 1 , NULL ) ;
throttle_config_init ( & backend - > tc ) ;
}
static void cryptodev_backend_finalize ( Object * obj )
@ -303,6 +430,9 @@ static void cryptodev_backend_finalize(Object *obj)
CryptoDevBackend * backend = CRYPTODEV_BACKEND ( obj ) ;
cryptodev_backend_cleanup ( backend , NULL ) ;
if ( throttle_enabled ( & backend - > tc ) ) {
throttle_timers_destroy ( & backend - > tt ) ;
}
}
static void
@ -318,6 +448,14 @@ cryptodev_backend_class_init(ObjectClass *oc, void *data)
cryptodev_backend_get_queues ,
cryptodev_backend_set_queues ,
NULL , NULL ) ;
object_class_property_add ( oc , " throttle-bps " , " uint64 " ,
cryptodev_backend_get_bps ,
cryptodev_backend_set_bps ,
NULL , NULL ) ;
object_class_property_add ( oc , " throttle-ops " , " uint64 " ,
cryptodev_backend_get_ops ,
cryptodev_backend_set_ops ,
NULL , NULL ) ;
}
static const TypeInfo cryptodev_backend_info = {