2019-05-22 10:51:24 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2014-12-07 19:41:16 +03:00
/*
2014-12-08 13:31:02 +03:00
* Virtio PCI driver - legacy device support
2014-12-07 19:41:16 +03:00
*
* This module allows virtio devices to be used over a virtual PCI device .
* This can be used with QEMU based VMMs like KVM or Xen .
*
* Copyright IBM Corp . 2007
2014-12-08 13:31:02 +03:00
* Copyright Red Hat , Inc . 2014
2014-12-07 19:41:16 +03:00
*
* Authors :
* Anthony Liguori < aliguori @ us . ibm . com >
2014-12-08 13:31:02 +03:00
* Rusty Russell < rusty @ rustcorp . com . au >
* Michael S . Tsirkin < mst @ redhat . com >
2014-12-07 19:41:16 +03:00
*/
2021-10-29 12:14:42 +03:00
# include "linux/virtio_pci_legacy.h"
2014-12-08 17:39:45 +03:00
# include "virtio_pci_common.h"
2014-12-07 19:41:16 +03:00
/* virtio config->get_features() implementation */
static u64 vp_get_features ( struct virtio_device * vdev )
{
struct virtio_pci_device * vp_dev = to_vp_device ( vdev ) ;
/* When someone needs more than 32 feature bits, we'll need to
* steal a bit to indicate that the rest are somewhere else . */
2021-10-29 12:14:42 +03:00
return vp_legacy_get_features ( & vp_dev - > ldev ) ;
2014-12-07 19:41:16 +03:00
}
/* virtio config->finalize_features() implementation */
static int vp_finalize_features ( struct virtio_device * vdev )
{
struct virtio_pci_device * vp_dev = to_vp_device ( vdev ) ;
/* Give virtio_ring a chance to accept features. */
vring_transport_features ( vdev ) ;
/* Make sure we don't have any features > 32 bits! */
BUG_ON ( ( u32 ) vdev - > features ! = vdev - > features ) ;
/* We only support 32 feature bits. */
2021-10-29 12:14:42 +03:00
vp_legacy_set_features ( & vp_dev - > ldev , vdev - > features ) ;
2014-12-07 19:41:16 +03:00
return 0 ;
}
/* virtio config->get() implementation */
2022-04-18 05:54:35 +03:00
static void vp_get ( struct virtio_device * vdev , unsigned int offset ,
void * buf , unsigned int len )
2014-12-07 19:41:16 +03:00
{
struct virtio_pci_device * vp_dev = to_vp_device ( vdev ) ;
2021-10-29 12:14:42 +03:00
void __iomem * ioaddr = vp_dev - > ldev . ioaddr +
2018-12-10 03:54:34 +03:00
VIRTIO_PCI_CONFIG_OFF ( vp_dev - > msix_enabled ) +
offset ;
2014-12-07 19:41:16 +03:00
u8 * ptr = buf ;
int i ;
for ( i = 0 ; i < len ; i + + )
ptr [ i ] = ioread8 ( ioaddr + i ) ;
}
/* the config->set() implementation. it's symmetric to the config->get()
* implementation */
2022-04-18 05:54:35 +03:00
static void vp_set ( struct virtio_device * vdev , unsigned int offset ,
const void * buf , unsigned int len )
2014-12-07 19:41:16 +03:00
{
struct virtio_pci_device * vp_dev = to_vp_device ( vdev ) ;
2021-10-29 12:14:42 +03:00
void __iomem * ioaddr = vp_dev - > ldev . ioaddr +
2018-12-10 03:54:34 +03:00
VIRTIO_PCI_CONFIG_OFF ( vp_dev - > msix_enabled ) +
offset ;
2014-12-07 19:41:16 +03:00
const u8 * ptr = buf ;
int i ;
for ( i = 0 ; i < len ; i + + )
iowrite8 ( ptr [ i ] , ioaddr + i ) ;
}
/* config->{get,set}_status() implementations */
static u8 vp_get_status ( struct virtio_device * vdev )
{
struct virtio_pci_device * vp_dev = to_vp_device ( vdev ) ;
2021-10-29 12:14:42 +03:00
return vp_legacy_get_status ( & vp_dev - > ldev ) ;
2014-12-07 19:41:16 +03:00
}
static void vp_set_status ( struct virtio_device * vdev , u8 status )
{
struct virtio_pci_device * vp_dev = to_vp_device ( vdev ) ;
/* We should never be setting status to 0. */
BUG_ON ( status = = 0 ) ;
2021-10-29 12:14:42 +03:00
vp_legacy_set_status ( & vp_dev - > ldev , status ) ;
2014-12-07 19:41:16 +03:00
}
static void vp_reset ( struct virtio_device * vdev )
{
struct virtio_pci_device * vp_dev = to_vp_device ( vdev ) ;
/* 0 status means a reset. */
2021-10-29 12:14:42 +03:00
vp_legacy_set_status ( & vp_dev - > ldev , 0 ) ;
2014-12-07 19:41:16 +03:00
/* Flush out the status write, and flush in device writes,
* including MSi - X interrupts , if any . */
2021-10-29 12:14:42 +03:00
vp_legacy_get_status ( & vp_dev - > ldev ) ;
2022-03-23 06:15:24 +03:00
/* Flush pending VQ/configuration callbacks. */
vp_synchronize_vectors ( vdev ) ;
2014-12-07 19:41:16 +03:00
}
static u16 vp_config_vector ( struct virtio_pci_device * vp_dev , u16 vector )
{
2021-10-29 12:14:42 +03:00
return vp_legacy_config_vector ( & vp_dev - > ldev , vector ) ;
2014-12-07 19:41:16 +03:00
}
static struct virtqueue * setup_vq ( struct virtio_pci_device * vp_dev ,
2017-04-04 21:44:44 +03:00
struct virtio_pci_vq_info * info ,
2022-04-18 05:54:35 +03:00
unsigned int index ,
2014-12-07 19:41:16 +03:00
void ( * callback ) ( struct virtqueue * vq ) ,
const char * name ,
2022-08-01 09:38:54 +03:00
u32 size ,
2017-03-06 19:32:29 +03:00
bool ctx ,
2014-12-07 19:41:16 +03:00
u16 msix_vec )
{
struct virtqueue * vq ;
u16 num ;
int err ;
2018-07-18 12:18:45 +03:00
u64 q_pfn ;
2014-12-07 19:41:16 +03:00
/* Check if queue is either not available or already active. */
2021-10-29 12:14:42 +03:00
num = vp_legacy_get_queue_size ( & vp_dev - > ldev , index ) ;
if ( ! num | | vp_legacy_get_queue_enable ( & vp_dev - > ldev , index ) )
2014-12-07 19:41:16 +03:00
return ERR_PTR ( - ENOENT ) ;
2022-08-01 09:38:54 +03:00
if ( ! size | | size > num )
size = num ;
2017-04-04 21:44:44 +03:00
info - > msix_vector = msix_vec ;
2016-02-03 08:46:39 +03:00
/* create the vring */
2022-08-01 09:38:54 +03:00
vq = vring_create_virtqueue ( index , size ,
2016-02-03 08:46:39 +03:00
VIRTIO_PCI_VRING_ALIGN , & vp_dev - > vdev ,
2017-03-06 19:32:29 +03:00
true , false , ctx ,
vp_notify , callback , name ) ;
2016-02-03 08:46:39 +03:00
if ( ! vq )
2014-12-07 19:41:16 +03:00
return ERR_PTR ( - ENOMEM ) ;
2022-08-01 09:38:21 +03:00
vq - > num_max = num ;
2018-07-18 12:18:45 +03:00
q_pfn = virtqueue_get_desc_addr ( vq ) > > VIRTIO_PCI_QUEUE_ADDR_SHIFT ;
if ( q_pfn > > 32 ) {
dev_err ( & vp_dev - > pci_dev - > dev ,
2021-12-09 06:29:25 +03:00
" platform bug: legacy virtio-pci must not be used with RAM above 0x%llxGB \n " ,
2018-07-18 12:18:45 +03:00
0x1ULL < < ( 32 + PAGE_SHIFT - 30 ) ) ;
err = - E2BIG ;
goto out_del_vq ;
}
2014-12-07 19:41:16 +03:00
/* activate the queue */
2021-10-29 12:14:42 +03:00
vp_legacy_set_queue_address ( & vp_dev - > ldev , index , q_pfn ) ;
2014-12-07 19:41:16 +03:00
2021-10-29 12:14:42 +03:00
vq - > priv = ( void __force * ) vp_dev - > ldev . ioaddr + VIRTIO_PCI_QUEUE_NOTIFY ;
2014-12-07 19:41:16 +03:00
if ( msix_vec ! = VIRTIO_MSI_NO_VECTOR ) {
2021-10-29 12:14:42 +03:00
msix_vec = vp_legacy_queue_vector ( & vp_dev - > ldev , index , msix_vec ) ;
2014-12-07 19:41:16 +03:00
if ( msix_vec = = VIRTIO_MSI_NO_VECTOR ) {
err = - EBUSY ;
2016-02-03 08:46:39 +03:00
goto out_deactivate ;
2014-12-07 19:41:16 +03:00
}
}
return vq ;
2016-02-03 08:46:39 +03:00
out_deactivate :
2021-10-29 12:14:42 +03:00
vp_legacy_set_queue_address ( & vp_dev - > ldev , index , 0 ) ;
2018-07-18 12:18:45 +03:00
out_del_vq :
2016-02-03 08:46:39 +03:00
vring_del_virtqueue ( vq ) ;
2014-12-07 19:41:16 +03:00
return ERR_PTR ( err ) ;
}
2017-04-04 21:44:44 +03:00
static void del_vq ( struct virtio_pci_vq_info * info )
2014-12-07 19:41:16 +03:00
{
2017-04-04 21:44:44 +03:00
struct virtqueue * vq = info - > vq ;
2014-12-07 19:41:16 +03:00
struct virtio_pci_device * vp_dev = to_vp_device ( vq - > vdev ) ;
2017-04-04 21:09:20 +03:00
if ( vp_dev - > msix_enabled ) {
2021-10-29 12:14:42 +03:00
vp_legacy_queue_vector ( & vp_dev - > ldev , vq - > index ,
VIRTIO_MSI_NO_VECTOR ) ;
2014-12-07 19:41:16 +03:00
/* Flush the write out to device */
2021-10-29 12:14:42 +03:00
ioread8 ( vp_dev - > ldev . ioaddr + VIRTIO_PCI_ISR ) ;
2014-12-07 19:41:16 +03:00
}
/* Select and deactivate the queue */
2021-10-29 12:14:42 +03:00
vp_legacy_set_queue_address ( & vp_dev - > ldev , vq - > index , 0 ) ;
2014-12-07 19:41:16 +03:00
2016-02-03 08:46:39 +03:00
vring_del_virtqueue ( vq ) ;
2014-12-07 19:41:16 +03:00
}
static const struct virtio_config_ops virtio_pci_config_ops = {
. get = vp_get ,
. set = vp_set ,
. get_status = vp_get_status ,
. set_status = vp_set_status ,
. reset = vp_reset ,
. find_vqs = vp_find_vqs ,
. del_vqs = vp_del_vqs ,
2022-05-27 09:01:15 +03:00
. synchronize_cbs = vp_synchronize_vectors ,
2014-12-07 19:41:16 +03:00
. get_features = vp_get_features ,
. finalize_features = vp_finalize_features ,
. bus_name = vp_bus_name ,
. set_vq_affinity = vp_set_vq_affinity ,
2017-02-05 20:15:23 +03:00
. get_vq_affinity = vp_get_vq_affinity ,
2014-12-07 19:41:16 +03:00
} ;
/* the PCI probing function */
2015-01-13 12:23:32 +03:00
int virtio_pci_legacy_probe ( struct virtio_pci_device * vp_dev )
2014-12-07 19:41:16 +03:00
{
2021-10-29 12:14:42 +03:00
struct virtio_pci_legacy_device * ldev = & vp_dev - > ldev ;
2015-01-13 12:23:32 +03:00
struct pci_dev * pci_dev = vp_dev - > pci_dev ;
2015-06-24 08:54:15 +03:00
int rc ;
2014-12-07 19:41:16 +03:00
2021-10-29 12:14:42 +03:00
ldev - > pci_dev = pci_dev ;
2016-02-03 08:46:39 +03:00
2021-10-29 12:14:42 +03:00
rc = vp_legacy_probe ( ldev ) ;
2015-06-24 08:54:15 +03:00
if ( rc )
return rc ;
2021-10-29 12:14:42 +03:00
vp_dev - > isr = ldev - > isr ;
vp_dev - > vdev . id = ldev - > id ;
2014-12-07 19:41:16 +03:00
2015-01-13 12:23:32 +03:00
vp_dev - > vdev . config = & virtio_pci_config_ops ;
2014-12-07 19:41:16 +03:00
vp_dev - > config_vector = vp_config_vector ;
vp_dev - > setup_vq = setup_vq ;
vp_dev - > del_vq = del_vq ;
return 0 ;
}
2015-01-13 12:23:32 +03:00
void virtio_pci_legacy_remove ( struct virtio_pci_device * vp_dev )
2014-12-07 19:41:16 +03:00
{
2021-10-29 12:14:42 +03:00
struct virtio_pci_legacy_device * ldev = & vp_dev - > ldev ;
2014-12-07 19:41:16 +03:00
2021-10-29 12:14:42 +03:00
vp_legacy_remove ( ldev ) ;
2014-12-07 19:41:16 +03:00
}