2020-03-26 22:01:25 +08:00
// SPDX-License-Identifier: GPL-2.0-only
/*
* Intel IFC VF NIC driver for virtio dataplane offloading
*
* Copyright ( C ) 2020 Intel Corporation .
*
* Author : Zhu Lingshan < lingshan . zhu @ intel . com >
*
*/
# include <linux/interrupt.h>
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/sysfs.h>
# include "ifcvf_base.h"
# define DRIVER_AUTHOR "Intel Corporation"
# define IFCVF_DRIVER_NAME "ifcvf"
2020-06-05 18:27:15 +08:00
static irqreturn_t ifcvf_config_changed ( int irq , void * arg )
{
struct ifcvf_hw * vf = arg ;
if ( vf - > config_cb . callback )
return vf - > config_cb . callback ( vf - > config_cb . private ) ;
return IRQ_HANDLED ;
}
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
static irqreturn_t ifcvf_vq_intr_handler ( int irq , void * arg )
2020-03-26 22:01:25 +08:00
{
struct vring_info * vring = arg ;
if ( vring - > cb . callback )
return vring - > cb . callback ( vring - > cb . private ) ;
return IRQ_HANDLED ;
}
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
static irqreturn_t ifcvf_vqs_reused_intr_handler ( int irq , void * arg )
{
struct ifcvf_hw * vf = arg ;
struct vring_info * vring ;
int i ;
for ( i = 0 ; i < vf - > nr_vring ; i + + ) {
vring = & vf - > vring [ i ] ;
if ( vring - > cb . callback )
vring - > cb . callback ( vring - > cb . private ) ;
}
return IRQ_HANDLED ;
}
static irqreturn_t ifcvf_dev_intr_handler ( int irq , void * arg )
{
struct ifcvf_hw * vf = arg ;
u8 isr ;
isr = vp_ioread8 ( vf - > isr ) ;
if ( isr & VIRTIO_PCI_ISR_CONFIG )
ifcvf_config_changed ( irq , arg ) ;
return ifcvf_vqs_reused_intr_handler ( irq , arg ) ;
}
2020-05-12 16:00:44 +08:00
static void ifcvf_free_irq_vectors ( void * data )
{
pci_free_irq_vectors ( data ) ;
}
2022-11-25 22:57:16 +08:00
static void ifcvf_free_per_vq_irq ( struct ifcvf_hw * vf )
2020-05-12 16:00:44 +08:00
{
2022-11-25 22:57:16 +08:00
struct pci_dev * pdev = vf - > pdev ;
2020-05-12 16:00:44 +08:00
int i ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
for ( i = 0 ; i < vf - > nr_vring ; i + + ) {
if ( vf - > vring [ i ] . irq ! = - EINVAL ) {
devm_free_irq ( & pdev - > dev , vf - > vring [ i ] . irq , & vf - > vring [ i ] ) ;
vf - > vring [ i ] . irq = - EINVAL ;
}
}
}
2022-11-25 22:57:16 +08:00
static void ifcvf_free_vqs_reused_irq ( struct ifcvf_hw * vf )
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
{
2022-11-25 22:57:16 +08:00
struct pci_dev * pdev = vf - > pdev ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
if ( vf - > vqs_reused_irq ! = - EINVAL ) {
devm_free_irq ( & pdev - > dev , vf - > vqs_reused_irq , vf ) ;
vf - > vqs_reused_irq = - EINVAL ;
}
2020-05-12 16:00:44 +08:00
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
}
2022-11-25 22:57:16 +08:00
static void ifcvf_free_vq_irq ( struct ifcvf_hw * vf )
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
{
if ( vf - > msix_vector_status = = MSIX_VECTOR_PER_VQ_AND_CONFIG )
2022-11-25 22:57:16 +08:00
ifcvf_free_per_vq_irq ( vf ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
else
2022-11-25 22:57:16 +08:00
ifcvf_free_vqs_reused_irq ( vf ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
}
2022-11-25 22:57:17 +08:00
static void ifcvf_free_config_irq ( struct ifcvf_hw * vf )
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
{
2022-11-25 22:57:17 +08:00
struct pci_dev * pdev = vf - > pdev ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
if ( vf - > config_irq = = - EINVAL )
return ;
/* If the irq is shared by all vqs and the config interrupt,
* it is already freed in ifcvf_free_vq_irq , so here only
* need to free config irq when msix_vector_status ! = MSIX_VECTOR_DEV_SHARED
*/
if ( vf - > msix_vector_status ! = MSIX_VECTOR_DEV_SHARED ) {
devm_free_irq ( & pdev - > dev , vf - > config_irq , vf ) ;
vf - > config_irq = - EINVAL ;
2020-07-31 14:55:32 +08:00
}
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
}
2022-11-25 22:57:17 +08:00
static void ifcvf_free_irq ( struct ifcvf_hw * vf )
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
{
2022-11-25 22:57:17 +08:00
struct pci_dev * pdev = vf - > pdev ;
2020-05-12 16:00:44 +08:00
2022-11-25 22:57:16 +08:00
ifcvf_free_vq_irq ( vf ) ;
2022-11-25 22:57:17 +08:00
ifcvf_free_config_irq ( vf ) ;
2020-05-12 16:00:44 +08:00
ifcvf_free_irq_vectors ( pdev ) ;
2023-05-26 22:52:53 +08:00
vf - > num_msix_vectors = 0 ;
2020-05-12 16:00:44 +08:00
}
2022-02-22 19:54:26 +08:00
/* ifcvf MSIX vectors allocator, this helper tries to allocate
* vectors for all virtqueues and the config interrupt .
* It returns the number of allocated vectors , negative
* return value when fails .
*/
2022-11-25 22:57:19 +08:00
static int ifcvf_alloc_vectors ( struct ifcvf_hw * vf )
2020-05-12 16:00:44 +08:00
{
2022-11-25 22:57:19 +08:00
struct pci_dev * pdev = vf - > pdev ;
2022-02-22 19:54:26 +08:00
int max_intr , ret ;
2020-05-12 16:00:44 +08:00
2021-08-18 17:57:13 +08:00
/* all queues and config interrupt */
max_intr = vf - > nr_vring + 1 ;
2022-02-22 19:54:26 +08:00
ret = pci_alloc_irq_vectors ( pdev , 1 , max_intr , PCI_IRQ_MSIX | PCI_IRQ_AFFINITY ) ;
2021-08-18 17:57:13 +08:00
2020-05-12 16:00:44 +08:00
if ( ret < 0 ) {
IFCVF_ERR ( pdev , " Failed to alloc IRQ vectors \n " ) ;
return ret ;
}
2022-02-22 19:54:26 +08:00
if ( ret < max_intr )
IFCVF_INFO ( pdev ,
" Requested %u vectors, however only %u allocated, lower performance \n " ,
max_intr , ret ) ;
return ret ;
}
2022-11-25 22:57:18 +08:00
static int ifcvf_request_per_vq_irq ( struct ifcvf_hw * vf )
2022-02-22 19:54:26 +08:00
{
2022-11-25 22:57:18 +08:00
struct pci_dev * pdev = vf - > pdev ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
int i , vector , ret , irq ;
2022-02-22 19:54:26 +08:00
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
vf - > vqs_reused_irq = - EINVAL ;
for ( i = 0 ; i < vf - > nr_vring ; i + + ) {
snprintf ( vf - > vring [ i ] . msix_name , 256 , " ifcvf[%s]-%d \n " , pci_name ( pdev ) , i ) ;
vector = i ;
irq = pci_irq_vector ( pdev , vector ) ;
ret = devm_request_irq ( & pdev - > dev , irq ,
ifcvf_vq_intr_handler , 0 ,
vf - > vring [ i ] . msix_name ,
& vf - > vring [ i ] ) ;
if ( ret ) {
IFCVF_ERR ( pdev , " Failed to request irq for vq %d \n " , i ) ;
goto err ;
}
vf - > vring [ i ] . irq = irq ;
ret = ifcvf_set_vq_vector ( vf , i , vector ) ;
if ( ret = = VIRTIO_MSI_NO_VECTOR ) {
IFCVF_ERR ( pdev , " No msix vector for vq %u \n " , i ) ;
goto err ;
}
}
return 0 ;
err :
2022-11-25 22:57:17 +08:00
ifcvf_free_irq ( vf ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
return - EFAULT ;
}
2022-11-25 22:57:18 +08:00
static int ifcvf_request_vqs_reused_irq ( struct ifcvf_hw * vf )
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
{
2022-11-25 22:57:18 +08:00
struct pci_dev * pdev = vf - > pdev ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
int i , vector , ret , irq ;
vector = 0 ;
snprintf ( vf - > vring [ 0 ] . msix_name , 256 , " ifcvf[%s]-vqs-reused-irq \n " , pci_name ( pdev ) ) ;
irq = pci_irq_vector ( pdev , vector ) ;
ret = devm_request_irq ( & pdev - > dev , irq ,
ifcvf_vqs_reused_intr_handler , 0 ,
vf - > vring [ 0 ] . msix_name , vf ) ;
if ( ret ) {
IFCVF_ERR ( pdev , " Failed to request reused irq for the device \n " ) ;
goto err ;
}
vf - > vqs_reused_irq = irq ;
for ( i = 0 ; i < vf - > nr_vring ; i + + ) {
vf - > vring [ i ] . irq = - EINVAL ;
ret = ifcvf_set_vq_vector ( vf , i , vector ) ;
if ( ret = = VIRTIO_MSI_NO_VECTOR ) {
IFCVF_ERR ( pdev , " No msix vector for vq %u \n " , i ) ;
goto err ;
}
}
return 0 ;
err :
2022-11-25 22:57:17 +08:00
ifcvf_free_irq ( vf ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
return - EFAULT ;
}
2022-11-25 22:57:19 +08:00
static int ifcvf_request_dev_irq ( struct ifcvf_hw * vf )
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
{
2022-11-25 22:57:19 +08:00
struct pci_dev * pdev = vf - > pdev ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
int i , vector , ret , irq ;
vector = 0 ;
snprintf ( vf - > vring [ 0 ] . msix_name , 256 , " ifcvf[%s]-dev-irq \n " , pci_name ( pdev ) ) ;
irq = pci_irq_vector ( pdev , vector ) ;
ret = devm_request_irq ( & pdev - > dev , irq ,
ifcvf_dev_intr_handler , 0 ,
vf - > vring [ 0 ] . msix_name , vf ) ;
if ( ret ) {
IFCVF_ERR ( pdev , " Failed to request irq for the device \n " ) ;
goto err ;
}
vf - > vqs_reused_irq = irq ;
for ( i = 0 ; i < vf - > nr_vring ; i + + ) {
vf - > vring [ i ] . irq = - EINVAL ;
ret = ifcvf_set_vq_vector ( vf , i , vector ) ;
if ( ret = = VIRTIO_MSI_NO_VECTOR ) {
IFCVF_ERR ( pdev , " No msix vector for vq %u \n " , i ) ;
goto err ;
}
}
vf - > config_irq = irq ;
ret = ifcvf_set_config_vector ( vf , vector ) ;
if ( ret = = VIRTIO_MSI_NO_VECTOR ) {
IFCVF_ERR ( pdev , " No msix vector for device config \n " ) ;
goto err ;
}
return 0 ;
err :
2022-11-25 22:57:17 +08:00
ifcvf_free_irq ( vf ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
return - EFAULT ;
}
2022-11-25 22:57:18 +08:00
static int ifcvf_request_vq_irq ( struct ifcvf_hw * vf )
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
{
int ret ;
if ( vf - > msix_vector_status = = MSIX_VECTOR_PER_VQ_AND_CONFIG )
2022-11-25 22:57:18 +08:00
ret = ifcvf_request_per_vq_irq ( vf ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
else
2022-11-25 22:57:18 +08:00
ret = ifcvf_request_vqs_reused_irq ( vf ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
return ret ;
}
2022-11-25 22:57:19 +08:00
static int ifcvf_request_config_irq ( struct ifcvf_hw * vf )
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
{
2022-11-25 22:57:19 +08:00
struct pci_dev * pdev = vf - > pdev ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
int config_vector , ret ;
if ( vf - > msix_vector_status = = MSIX_VECTOR_PER_VQ_AND_CONFIG )
config_vector = vf - > nr_vring ;
2022-04-24 15:28:06 +08:00
else if ( vf - > msix_vector_status = = MSIX_VECTOR_SHARED_VQ_AND_CONFIG )
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
/* vector 0 for vqs and 1 for config interrupt */
config_vector = 1 ;
2022-04-24 15:28:06 +08:00
else if ( vf - > msix_vector_status = = MSIX_VECTOR_DEV_SHARED )
/* re-use the vqs vector */
return 0 ;
else
return - EINVAL ;
2022-02-22 19:54:26 +08:00
2020-06-05 18:27:15 +08:00
snprintf ( vf - > config_msix_name , 256 , " ifcvf[%s]-config \n " ,
pci_name ( pdev ) ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
vf - > config_irq = pci_irq_vector ( pdev , config_vector ) ;
2020-07-23 17:12:54 +08:00
ret = devm_request_irq ( & pdev - > dev , vf - > config_irq ,
2020-06-05 18:27:15 +08:00
ifcvf_config_changed , 0 ,
vf - > config_msix_name , vf ) ;
2020-07-23 17:12:53 +08:00
if ( ret ) {
IFCVF_ERR ( pdev , " Failed to request config irq \n " ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
goto err ;
2020-07-23 17:12:53 +08:00
}
2020-06-05 18:27:15 +08:00
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
ret = ifcvf_set_config_vector ( vf , config_vector ) ;
if ( ret = = VIRTIO_MSI_NO_VECTOR ) {
IFCVF_ERR ( pdev , " No msix vector for device config \n " ) ;
goto err ;
}
2020-05-12 16:00:44 +08:00
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
return 0 ;
err :
2022-11-25 22:57:17 +08:00
ifcvf_free_irq ( vf ) ;
2020-05-12 16:00:44 +08:00
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
return - EFAULT ;
}
2022-11-25 22:57:20 +08:00
static int ifcvf_request_irq ( struct ifcvf_hw * vf )
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
{
int nvectors , ret , max_intr ;
2022-11-25 22:57:19 +08:00
nvectors = ifcvf_alloc_vectors ( vf ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
if ( nvectors < = 0 )
return - EFAULT ;
vf - > msix_vector_status = MSIX_VECTOR_PER_VQ_AND_CONFIG ;
max_intr = vf - > nr_vring + 1 ;
if ( nvectors < max_intr )
vf - > msix_vector_status = MSIX_VECTOR_SHARED_VQ_AND_CONFIG ;
if ( nvectors = = 1 ) {
vf - > msix_vector_status = MSIX_VECTOR_DEV_SHARED ;
2022-11-25 22:57:19 +08:00
ret = ifcvf_request_dev_irq ( vf ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
return ret ;
2020-05-12 16:00:44 +08:00
}
2022-11-25 22:57:18 +08:00
ret = ifcvf_request_vq_irq ( vf ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
if ( ret )
return ret ;
2022-11-25 22:57:19 +08:00
ret = ifcvf_request_config_irq ( vf ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
if ( ret )
return ret ;
2023-05-26 22:52:53 +08:00
vf - > num_msix_vectors = nvectors ;
2020-03-26 22:01:25 +08:00
return 0 ;
}
static struct ifcvf_adapter * vdpa_to_adapter ( struct vdpa_device * vdpa_dev )
{
return container_of ( vdpa_dev , struct ifcvf_adapter , vdpa ) ;
}
static struct ifcvf_hw * vdpa_to_vf ( struct vdpa_device * vdpa_dev )
{
struct ifcvf_adapter * adapter = vdpa_to_adapter ( vdpa_dev ) ;
2022-11-25 22:57:21 +08:00
return adapter - > vf ;
2020-03-26 22:01:25 +08:00
}
2022-01-05 13:46:33 +02:00
static u64 ifcvf_vdpa_get_device_features ( struct vdpa_device * vdpa_dev )
2020-03-26 22:01:25 +08:00
{
2021-04-19 14:33:25 +08:00
struct ifcvf_adapter * adapter = vdpa_to_adapter ( vdpa_dev ) ;
2020-03-26 22:01:25 +08:00
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2021-04-19 14:33:25 +08:00
struct pci_dev * pdev = adapter - > pdev ;
2021-08-18 17:57:14 +08:00
u32 type = vf - > dev_type ;
2020-03-26 22:01:25 +08:00
u64 features ;
2021-08-18 17:57:14 +08:00
if ( type = = VIRTIO_ID_NET | | type = = VIRTIO_ID_BLOCK )
2023-05-26 22:52:51 +08:00
features = ifcvf_get_dev_features ( vf ) ;
2021-08-18 17:57:14 +08:00
else {
2021-04-19 14:33:25 +08:00
features = 0 ;
IFCVF_ERR ( pdev , " VIRTIO ID %u not supported \n " , vf - > dev_type ) ;
}
2020-03-26 22:01:25 +08:00
return features ;
}
2022-01-05 13:46:33 +02:00
static int ifcvf_vdpa_set_driver_features ( struct vdpa_device * vdpa_dev , u64 features )
2020-03-26 22:01:25 +08:00
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2021-03-17 17:49:32 +08:00
int ret ;
ret = ifcvf_verify_min_features ( vf , features ) ;
if ( ret )
return ret ;
2020-03-26 22:01:25 +08:00
2023-05-26 22:52:51 +08:00
ifcvf_set_driver_features ( vf , features ) ;
2020-03-26 22:01:25 +08:00
return 0 ;
}
2022-01-05 13:46:33 +02:00
static u64 ifcvf_vdpa_get_driver_features ( struct vdpa_device * vdpa_dev )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2023-05-26 22:52:51 +08:00
u64 features ;
features = ifcvf_get_driver_features ( vf ) ;
2022-01-05 13:46:33 +02:00
2023-05-26 22:52:51 +08:00
return features ;
2022-01-05 13:46:33 +02:00
}
2020-03-26 22:01:25 +08:00
static u8 ifcvf_vdpa_get_status ( struct vdpa_device * vdpa_dev )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
return ifcvf_get_status ( vf ) ;
}
static void ifcvf_vdpa_set_status ( struct vdpa_device * vdpa_dev , u8 status )
{
struct ifcvf_hw * vf ;
2020-05-12 16:00:44 +08:00
u8 status_old ;
int ret ;
2020-03-26 22:01:25 +08:00
vf = vdpa_to_vf ( vdpa_dev ) ;
2020-05-12 16:00:44 +08:00
status_old = ifcvf_get_status ( vf ) ;
2020-03-26 22:01:25 +08:00
2020-06-05 18:27:12 +08:00
if ( status_old = = status )
return ;
2020-05-12 16:00:44 +08:00
if ( ( status & VIRTIO_CONFIG_S_DRIVER_OK ) & &
! ( status_old & VIRTIO_CONFIG_S_DRIVER_OK ) ) {
2022-11-25 22:57:20 +08:00
ret = ifcvf_request_irq ( vf ) ;
2020-05-12 16:00:44 +08:00
if ( ret ) {
2023-05-26 22:52:54 +08:00
IFCVF_ERR ( vf - > pdev , " failed to request irq with error %d \n " , ret ) ;
2020-05-12 16:00:44 +08:00
return ;
}
2020-03-26 22:01:25 +08:00
}
ifcvf_set_status ( vf , status ) ;
}
2021-08-31 18:36:26 +08:00
static int ifcvf_vdpa_reset ( struct vdpa_device * vdpa_dev )
{
2023-05-26 22:52:53 +08:00
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
u8 status = ifcvf_get_status ( vf ) ;
2021-08-31 18:36:26 +08:00
2023-05-26 22:52:53 +08:00
ifcvf_stop ( vf ) ;
2021-08-31 18:36:26 +08:00
2023-05-26 22:52:53 +08:00
if ( status & VIRTIO_CONFIG_S_DRIVER_OK )
2022-11-25 22:57:17 +08:00
ifcvf_free_irq ( vf ) ;
2021-08-31 18:36:26 +08:00
2023-05-26 22:52:53 +08:00
ifcvf_reset ( vf ) ;
2021-08-31 18:36:26 +08:00
return 0 ;
}
2020-03-26 22:01:25 +08:00
static u16 ifcvf_vdpa_get_vq_num_max ( struct vdpa_device * vdpa_dev )
{
2023-06-12 23:14:19 +08:00
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
return ifcvf_get_max_vq_size ( vf ) ;
2020-03-26 22:01:25 +08:00
}
2020-08-04 19:20:44 +03:00
static int ifcvf_vdpa_get_vq_state ( struct vdpa_device * vdpa_dev , u16 qid ,
struct vdpa_vq_state * state )
2020-03-26 22:01:25 +08:00
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2021-06-02 10:15:33 +08:00
state - > split . avail_index = ifcvf_get_vq_state ( vf , qid ) ;
2020-08-04 19:20:44 +03:00
return 0 ;
2020-03-26 22:01:25 +08:00
}
static int ifcvf_vdpa_set_vq_state ( struct vdpa_device * vdpa_dev , u16 qid ,
2020-08-04 19:20:43 +03:00
const struct vdpa_vq_state * state )
2020-03-26 22:01:25 +08:00
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2021-06-02 10:15:33 +08:00
return ifcvf_set_vq_state ( vf , qid , state - > split . avail_index ) ;
2020-03-26 22:01:25 +08:00
}
static void ifcvf_vdpa_set_vq_cb ( struct vdpa_device * vdpa_dev , u16 qid ,
struct vdpa_callback * cb )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
vf - > vring [ qid ] . cb = * cb ;
}
static void ifcvf_vdpa_set_vq_ready ( struct vdpa_device * vdpa_dev ,
u16 qid , bool ready )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2023-05-26 22:52:50 +08:00
ifcvf_set_vq_ready ( vf , qid , ready ) ;
2020-03-26 22:01:25 +08:00
}
static bool ifcvf_vdpa_get_vq_ready ( struct vdpa_device * vdpa_dev , u16 qid )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2023-05-26 22:52:50 +08:00
return ifcvf_get_vq_ready ( vf , qid ) ;
2020-03-26 22:01:25 +08:00
}
static void ifcvf_vdpa_set_vq_num ( struct vdpa_device * vdpa_dev , u16 qid ,
u32 num )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2023-05-26 22:52:50 +08:00
ifcvf_set_vq_num ( vf , qid , num ) ;
2020-03-26 22:01:25 +08:00
}
static int ifcvf_vdpa_set_vq_address ( struct vdpa_device * vdpa_dev , u16 qid ,
u64 desc_area , u64 driver_area ,
u64 device_area )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2023-05-26 22:52:50 +08:00
return ifcvf_set_vq_address ( vf , qid , desc_area , driver_area , device_area ) ;
2020-03-26 22:01:25 +08:00
}
static void ifcvf_vdpa_kick_vq ( struct vdpa_device * vdpa_dev , u16 qid )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
ifcvf_notify_queue ( vf , qid ) ;
}
static u32 ifcvf_vdpa_get_generation ( struct vdpa_device * vdpa_dev )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2022-02-22 19:54:24 +08:00
return vp_ioread8 ( & vf - > common_cfg - > config_generation ) ;
2020-03-26 22:01:25 +08:00
}
static u32 ifcvf_vdpa_get_device_id ( struct vdpa_device * vdpa_dev )
{
2021-04-19 14:33:24 +08:00
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2021-03-17 17:49:33 +08:00
2021-04-19 14:33:24 +08:00
return vf - > dev_type ;
2020-03-26 22:01:25 +08:00
}
static u32 ifcvf_vdpa_get_vendor_id ( struct vdpa_device * vdpa_dev )
{
2021-03-17 17:49:27 +08:00
struct ifcvf_adapter * adapter = vdpa_to_adapter ( vdpa_dev ) ;
struct pci_dev * pdev = adapter - > pdev ;
return pdev - > subsystem_vendor ;
2020-03-26 22:01:25 +08:00
}
2020-04-09 16:26:21 -04:00
static u32 ifcvf_vdpa_get_vq_align ( struct vdpa_device * vdpa_dev )
2020-03-26 22:01:25 +08:00
{
return IFCVF_QUEUE_ALIGNMENT ;
}
2021-03-15 17:34:44 +01:00
static size_t ifcvf_vdpa_get_config_size ( struct vdpa_device * vdpa_dev )
{
2021-04-19 14:33:26 +08:00
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2021-12-01 16:12:55 +08:00
return vf - > config_size ;
2021-03-15 17:34:44 +01:00
}
2022-03-30 23:33:45 +05:30
static u32 ifcvf_vdpa_get_vq_group ( struct vdpa_device * vdpa , u16 idx )
{
return 0 ;
}
2020-03-26 22:01:25 +08:00
static void ifcvf_vdpa_get_config ( struct vdpa_device * vdpa_dev ,
unsigned int offset ,
void * buf , unsigned int len )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2021-12-01 16:12:55 +08:00
ifcvf_read_dev_config ( vf , offset , buf , len ) ;
2020-03-26 22:01:25 +08:00
}
static void ifcvf_vdpa_set_config ( struct vdpa_device * vdpa_dev ,
unsigned int offset , const void * buf ,
unsigned int len )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
2021-12-01 16:12:55 +08:00
ifcvf_write_dev_config ( vf , offset , buf , len ) ;
2020-03-26 22:01:25 +08:00
}
static void ifcvf_vdpa_set_config_cb ( struct vdpa_device * vdpa_dev ,
struct vdpa_callback * cb )
{
2020-06-05 18:27:15 +08:00
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
vf - > config_cb . callback = cb - > callback ;
vf - > config_cb . private = cb - > private ;
2020-03-26 22:01:25 +08:00
}
2020-07-31 14:55:32 +08:00
static int ifcvf_vdpa_get_vq_irq ( struct vdpa_device * vdpa_dev ,
u16 qid )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
vDPA/ifcvf: implement shared IRQ feature
On some platforms/devices, there may not be enough MSI vectors
allocated for the virtqueues and config changes. In such a case,
the interrupt sources(virtqueues, config changes) must share
an IRQ/vector, to avoid initialization failures, keep
the device functional.
This commit handles three cases:
(1) number of the allocated vectors == the number of virtqueues + 1
(config changes), every virtqueue and the config interrupt has
a separated vector/IRQ, the best and the most likely case.
(2) number of the allocated vectors is less than the best case, but
greater than 1. In this case, all virtqueues share a vector/IRQ,
the config interrupt has a separated vector/IRQ
(3) only one vector is allocated, in this case, the virtqueues and
the config interrupt share a vector/IRQ. The worst and most
unlikely case.
Otherwise, it needs to fail.
This commit introduces some helper functions:
ifcvf_set_vq_vector() and ifcvf_set_config_vector() sets virtqueue
vector and config vector in the device config space, so that
the device can send interrupt DMA.
Signed-off-by: Zhu Lingshan <lingshan.zhu@intel.com>
Link: https://lore.kernel.org/r/20220222115428.998334-5-lingshan.zhu@intel.com
Signed-off-by: Tom Rix <trix@redhat.com>
Link: https://lore.kernel.org/r/20220315124130.1710030-1-trix@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2022-02-22 19:54:27 +08:00
if ( vf - > vqs_reused_irq < 0 )
return vf - > vring [ qid ] . irq ;
else
return - EINVAL ;
2020-07-31 14:55:32 +08:00
}
2021-06-02 16:45:50 +08:00
static struct vdpa_notification_area ifcvf_get_vq_notification ( struct vdpa_device * vdpa_dev ,
u16 idx )
{
struct ifcvf_hw * vf = vdpa_to_vf ( vdpa_dev ) ;
struct vdpa_notification_area area ;
area . addr = vf - > vring [ idx ] . notify_pa ;
if ( ! vf - > notify_off_multiplier )
area . size = PAGE_SIZE ;
else
area . size = vf - > notify_off_multiplier ;
return area ;
}
2020-03-26 22:01:25 +08:00
/*
2022-07-04 10:41:04 +08:00
* IFCVF currently doesn ' t have on - chip IOMMU , so not
2020-03-26 22:01:25 +08:00
* implemented set_map ( ) / dma_map ( ) / dma_unmap ( )
*/
static const struct vdpa_config_ops ifc_vdpa_ops = {
2022-01-05 13:46:33 +02:00
. get_device_features = ifcvf_vdpa_get_device_features ,
. set_driver_features = ifcvf_vdpa_set_driver_features ,
. get_driver_features = ifcvf_vdpa_get_driver_features ,
2020-03-26 22:01:25 +08:00
. get_status = ifcvf_vdpa_get_status ,
. set_status = ifcvf_vdpa_set_status ,
2021-08-31 18:36:26 +08:00
. reset = ifcvf_vdpa_reset ,
2020-03-26 22:01:25 +08:00
. get_vq_num_max = ifcvf_vdpa_get_vq_num_max ,
. get_vq_state = ifcvf_vdpa_get_vq_state ,
. set_vq_state = ifcvf_vdpa_set_vq_state ,
. set_vq_cb = ifcvf_vdpa_set_vq_cb ,
. set_vq_ready = ifcvf_vdpa_set_vq_ready ,
. get_vq_ready = ifcvf_vdpa_get_vq_ready ,
. set_vq_num = ifcvf_vdpa_set_vq_num ,
. set_vq_address = ifcvf_vdpa_set_vq_address ,
2020-07-31 14:55:32 +08:00
. get_vq_irq = ifcvf_vdpa_get_vq_irq ,
2020-03-26 22:01:25 +08:00
. kick_vq = ifcvf_vdpa_kick_vq ,
. get_generation = ifcvf_vdpa_get_generation ,
. get_device_id = ifcvf_vdpa_get_device_id ,
. get_vendor_id = ifcvf_vdpa_get_vendor_id ,
. get_vq_align = ifcvf_vdpa_get_vq_align ,
2022-03-30 23:33:45 +05:30
. get_vq_group = ifcvf_vdpa_get_vq_group ,
2021-03-15 17:34:44 +01:00
. get_config_size = ifcvf_vdpa_get_config_size ,
2020-03-26 22:01:25 +08:00
. get_config = ifcvf_vdpa_get_config ,
. set_config = ifcvf_vdpa_set_config ,
. set_config_cb = ifcvf_vdpa_set_config_cb ,
2021-06-02 16:45:50 +08:00
. get_vq_notification = ifcvf_get_vq_notification ,
2020-03-26 22:01:25 +08:00
} ;
2021-08-12 11:24:54 +08:00
static struct virtio_device_id id_table_net [ ] = {
{ VIRTIO_ID_NET , VIRTIO_DEV_ANY_ID } ,
{ 0 } ,
} ;
static struct virtio_device_id id_table_blk [ ] = {
{ VIRTIO_ID_BLOCK , VIRTIO_DEV_ANY_ID } ,
{ 0 } ,
} ;
2021-08-12 11:24:53 +08:00
static u32 get_dev_type ( struct pci_dev * pdev )
{
u32 dev_type ;
/* This drirver drives both modern virtio devices and transitional
* devices in modern mode .
* vDPA requires feature bit VIRTIO_F_ACCESS_PLATFORM ,
* so legacy devices and transitional devices in legacy
* mode will not work for vDPA , this driver will not
* drive devices with legacy interface .
*/
if ( pdev - > device < 0x1040 )
dev_type = pdev - > subsystem_device ;
else
dev_type = pdev - > device - 0x1040 ;
return dev_type ;
}
2021-10-26 20:55:15 +03:00
static int ifcvf_vdpa_dev_add ( struct vdpa_mgmt_dev * mdev , const char * name ,
const struct vdpa_dev_set_config * config )
2020-03-26 22:01:25 +08:00
{
2021-08-12 11:24:54 +08:00
struct ifcvf_vdpa_mgmt_dev * ifcvf_mgmt_dev ;
2020-03-26 22:01:25 +08:00
struct ifcvf_adapter * adapter ;
2022-07-22 19:53:05 +08:00
struct vdpa_device * vdpa_dev ;
2021-08-12 11:24:54 +08:00
struct pci_dev * pdev ;
2020-03-26 22:01:25 +08:00
struct ifcvf_hw * vf ;
2022-11-25 22:57:24 +08:00
u64 device_features ;
2022-07-22 19:53:05 +08:00
int ret ;
2020-03-26 22:01:25 +08:00
2021-08-12 11:24:54 +08:00
ifcvf_mgmt_dev = container_of ( mdev , struct ifcvf_vdpa_mgmt_dev , mdev ) ;
2022-11-25 22:57:22 +08:00
vf = & ifcvf_mgmt_dev - > vf ;
pdev = vf - > pdev ;
adapter = vdpa_alloc_device ( struct ifcvf_adapter , vdpa ,
& pdev - > dev , & ifc_vdpa_ops , 1 , 1 , NULL , false ) ;
if ( IS_ERR ( adapter ) ) {
IFCVF_ERR ( pdev , " Failed to allocate vDPA structure " ) ;
return PTR_ERR ( adapter ) ;
}
2020-03-26 22:01:25 +08:00
2022-11-25 22:57:22 +08:00
ifcvf_mgmt_dev - > adapter = adapter ;
adapter - > pdev = pdev ;
adapter - > vdpa . dma_dev = & pdev - > dev ;
adapter - > vdpa . mdev = mdev ;
adapter - > vf = vf ;
2022-07-22 19:53:05 +08:00
vdpa_dev = & adapter - > vdpa ;
2020-03-26 22:01:25 +08:00
2022-11-25 22:57:24 +08:00
device_features = vf - > hw_features ;
if ( config - > mask & BIT_ULL ( VDPA_ATTR_DEV_FEATURES ) ) {
if ( config - > device_features & ~ device_features ) {
IFCVF_ERR ( pdev , " The provisioned features 0x%llx are not supported by this device with features 0x%llx \n " ,
config - > device_features , device_features ) ;
return - EINVAL ;
}
device_features & = config - > device_features ;
}
vf - > dev_features = device_features ;
2022-07-22 19:53:05 +08:00
if ( name )
ret = dev_set_name ( & vdpa_dev - > dev , " %s " , name ) ;
else
ret = dev_set_name ( & vdpa_dev - > dev , " vdpa%u " , vdpa_dev - > index ) ;
2021-03-17 17:49:31 +08:00
2021-08-18 17:57:13 +08:00
ret = _vdpa_register_device ( & adapter - > vdpa , vf - > nr_vring ) ;
2020-03-26 22:01:25 +08:00
if ( ret ) {
2022-07-22 19:53:05 +08:00
put_device ( & adapter - > vdpa . dev ) ;
2021-08-12 11:24:54 +08:00
IFCVF_ERR ( pdev , " Failed to register to vDPA bus " ) ;
2022-07-22 19:53:05 +08:00
return ret ;
2020-03-26 22:01:25 +08:00
}
return 0 ;
}
2021-08-12 11:24:54 +08:00
static void ifcvf_vdpa_dev_del ( struct vdpa_mgmt_dev * mdev , struct vdpa_device * dev )
{
struct ifcvf_vdpa_mgmt_dev * ifcvf_mgmt_dev ;
ifcvf_mgmt_dev = container_of ( mdev , struct ifcvf_vdpa_mgmt_dev , mdev ) ;
_vdpa_unregister_device ( dev ) ;
ifcvf_mgmt_dev - > adapter = NULL ;
}
static const struct vdpa_mgmtdev_ops ifcvf_vdpa_mgmt_dev_ops = {
. dev_add = ifcvf_vdpa_dev_add ,
. dev_del = ifcvf_vdpa_dev_del
} ;
static int ifcvf_probe ( struct pci_dev * pdev , const struct pci_device_id * id )
{
struct ifcvf_vdpa_mgmt_dev * ifcvf_mgmt_dev ;
struct device * dev = & pdev - > dev ;
2022-07-22 19:53:05 +08:00
struct ifcvf_hw * vf ;
2021-08-12 11:24:54 +08:00
u32 dev_type ;
2022-07-22 19:53:05 +08:00
int ret , i ;
2021-08-12 11:24:54 +08:00
ret = pcim_enable_device ( pdev ) ;
if ( ret ) {
IFCVF_ERR ( pdev , " Failed to enable device \n " ) ;
2022-07-22 19:53:05 +08:00
return ret ;
2021-08-12 11:24:54 +08:00
}
ret = pcim_iomap_regions ( pdev , BIT ( 0 ) | BIT ( 2 ) | BIT ( 4 ) ,
IFCVF_DRIVER_NAME ) ;
if ( ret ) {
IFCVF_ERR ( pdev , " Failed to request MMIO region \n " ) ;
2022-07-22 19:53:05 +08:00
return ret ;
2021-08-12 11:24:54 +08:00
}
ret = dma_set_mask_and_coherent ( dev , DMA_BIT_MASK ( 64 ) ) ;
if ( ret ) {
IFCVF_ERR ( pdev , " No usable DMA configuration \n " ) ;
2022-07-22 19:53:05 +08:00
return ret ;
2021-08-12 11:24:54 +08:00
}
ret = devm_add_action_or_reset ( dev , ifcvf_free_irq_vectors , pdev ) ;
if ( ret ) {
IFCVF_ERR ( pdev ,
" Failed for adding devres for freeing irq vectors \n " ) ;
2022-07-22 19:53:05 +08:00
return ret ;
2021-08-12 11:24:54 +08:00
}
pci_set_master ( pdev ) ;
2022-11-25 22:57:15 +08:00
ifcvf_mgmt_dev = kzalloc ( sizeof ( struct ifcvf_vdpa_mgmt_dev ) , GFP_KERNEL ) ;
if ( ! ifcvf_mgmt_dev ) {
IFCVF_ERR ( pdev , " Failed to alloc memory for the vDPA management device \n " ) ;
return - ENOMEM ;
}
2021-08-12 11:24:54 +08:00
2022-11-25 22:57:21 +08:00
vf = & ifcvf_mgmt_dev - > vf ;
2022-07-22 19:53:05 +08:00
vf - > dev_type = get_dev_type ( pdev ) ;
vf - > base = pcim_iomap_table ( pdev ) ;
2022-11-25 22:57:13 +08:00
vf - > pdev = pdev ;
2022-07-22 19:53:05 +08:00
ret = ifcvf_init_hw ( vf , pdev ) ;
if ( ret ) {
IFCVF_ERR ( pdev , " Failed to init IFCVF hw \n " ) ;
2022-12-27 22:02:16 +01:00
goto err ;
2022-07-22 19:53:05 +08:00
}
for ( i = 0 ; i < vf - > nr_vring ; i + + )
vf - > vring [ i ] . irq = - EINVAL ;
vf - > hw_features = ifcvf_get_hw_features ( vf ) ;
vf - > config_size = ifcvf_get_config_size ( vf ) ;
dev_type = get_dev_type ( pdev ) ;
switch ( dev_type ) {
case VIRTIO_ID_NET :
ifcvf_mgmt_dev - > mdev . id_table = id_table_net ;
break ;
case VIRTIO_ID_BLOCK :
ifcvf_mgmt_dev - > mdev . id_table = id_table_blk ;
break ;
default :
IFCVF_ERR ( pdev , " VIRTIO ID %u not supported \n " , dev_type ) ;
ret = - EOPNOTSUPP ;
goto err ;
}
2022-11-25 22:57:15 +08:00
ifcvf_mgmt_dev - > mdev . ops = & ifcvf_vdpa_mgmt_dev_ops ;
ifcvf_mgmt_dev - > mdev . device = dev ;
2022-07-22 19:53:05 +08:00
ifcvf_mgmt_dev - > mdev . max_supported_vqs = vf - > nr_vring ;
ifcvf_mgmt_dev - > mdev . supported_features = vf - > hw_features ;
2022-11-25 22:57:24 +08:00
ifcvf_mgmt_dev - > mdev . config_attr_mask = ( 1 < < VDPA_ATTR_DEV_FEATURES ) ;
2022-07-22 19:53:05 +08:00
2021-08-12 11:24:54 +08:00
ret = vdpa_mgmtdev_register ( & ifcvf_mgmt_dev - > mdev ) ;
if ( ret ) {
IFCVF_ERR ( pdev ,
" Failed to initialize the management interfaces \n " ) ;
goto err ;
}
2022-05-24 13:55:57 +08:00
pci_set_drvdata ( pdev , ifcvf_mgmt_dev ) ;
2021-08-12 11:24:54 +08:00
return 0 ;
err :
2023-06-12 23:14:18 +08:00
kfree ( ifcvf_mgmt_dev - > vf . vring ) ;
2021-08-12 11:24:54 +08:00
kfree ( ifcvf_mgmt_dev ) ;
return ret ;
}
2020-03-26 22:01:25 +08:00
static void ifcvf_remove ( struct pci_dev * pdev )
{
2021-08-12 11:24:54 +08:00
struct ifcvf_vdpa_mgmt_dev * ifcvf_mgmt_dev ;
2020-03-26 22:01:25 +08:00
2021-08-12 11:24:54 +08:00
ifcvf_mgmt_dev = pci_get_drvdata ( pdev ) ;
vdpa_mgmtdev_unregister ( & ifcvf_mgmt_dev - > mdev ) ;
2023-06-12 23:14:18 +08:00
kfree ( ifcvf_mgmt_dev - > vf . vring ) ;
2021-08-12 11:24:54 +08:00
kfree ( ifcvf_mgmt_dev ) ;
2020-03-26 22:01:25 +08:00
}
static struct pci_device_id ifcvf_pci_ids [ ] = {
2021-05-10 16:10:15 +08:00
/* N3000 network device */
{ PCI_DEVICE_SUB ( PCI_VENDOR_ID_REDHAT_QUMRANET ,
2021-03-17 17:49:29 +08:00
N3000_DEVICE_ID ,
2021-05-10 16:10:15 +08:00
PCI_VENDOR_ID_INTEL ,
2021-03-17 17:49:29 +08:00
N3000_SUBSYS_DEVICE_ID ) } ,
2021-05-10 16:10:15 +08:00
/* C5000X-PL network device */
{ PCI_DEVICE_SUB ( PCI_VENDOR_ID_REDHAT_QUMRANET ,
VIRTIO_TRANS_ID_NET ,
PCI_VENDOR_ID_INTEL ,
VIRTIO_ID_NET ) } ,
/* C5000X-PL block device */
{ PCI_DEVICE_SUB ( PCI_VENDOR_ID_REDHAT_QUMRANET ,
VIRTIO_TRANS_ID_BLOCK ,
PCI_VENDOR_ID_INTEL ,
VIRTIO_ID_BLOCK ) } ,
2021-03-17 17:49:28 +08:00
2020-03-26 22:01:25 +08:00
{ 0 } ,
} ;
MODULE_DEVICE_TABLE ( pci , ifcvf_pci_ids ) ;
static struct pci_driver ifcvf_driver = {
. name = IFCVF_DRIVER_NAME ,
. id_table = ifcvf_pci_ids ,
. probe = ifcvf_probe ,
. remove = ifcvf_remove ,
} ;
module_pci_driver ( ifcvf_driver ) ;
MODULE_LICENSE ( " GPL v2 " ) ;