[dpdk-dev,v2,2/5] net/virtio: add interrupt configure for vdev

Message ID 1490689316-131625-3-git-send-email-jianfeng.tan@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Yuanhan Liu
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Jianfeng Tan March 28, 2017, 8:21 a.m. UTC
  For virtio PCI devices, interrupt should be configured before setting
VIRTIO_CONFIG_STATUS_DRIVER_OK so that QEMU can properly set eventfds
in the host.

For virtio virtual devices, VIRTIO_CONFIG_STATUS_DRIVER_OK should be
set firstly, so that intr_handle is initialized in
virtio_user_start_device().

To accommodate both requirements, we rearrange the sequence like this:
  a. set interrupt configure for PCI devices.
  b. set VIRTIO_CONFIG_STATUS_DRIVER_OK.
  c. set interrupt configure for virtual devices.

Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 57 ++++++++++++++++++++++++++++++++++----
 1 file changed, 51 insertions(+), 6 deletions(-)
  

Comments

Yuanhan Liu March 29, 2017, 6:27 a.m. UTC | #1
On Tue, Mar 28, 2017 at 08:21:53AM +0000, Jianfeng Tan wrote:
> For virtio PCI devices, interrupt should be configured before setting
> VIRTIO_CONFIG_STATUS_DRIVER_OK so that QEMU can properly set eventfds
> in the host.
> 
> For virtio virtual devices, VIRTIO_CONFIG_STATUS_DRIVER_OK should be
> set firstly, so that intr_handle is initialized in
> virtio_user_start_device().

I'm wondering why can't you let virtio-user follow virtio-pci?

	--yliu
> 
> To accommodate both requirements, we rearrange the sequence like this:
>   a. set interrupt configure for PCI devices.
>   b. set VIRTIO_CONFIG_STATUS_DRIVER_OK.
>   c. set interrupt configure for virtual devices.
> 
> Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
  
Jianfeng Tan March 29, 2017, 7:03 a.m. UTC | #2
On 3/29/2017 2:27 PM, Yuanhan Liu wrote:
> On Tue, Mar 28, 2017 at 08:21:53AM +0000, Jianfeng Tan wrote:
>> For virtio PCI devices, interrupt should be configured before setting
>> VIRTIO_CONFIG_STATUS_DRIVER_OK so that QEMU can properly set eventfds
>> in the host.
>>
>> For virtio virtual devices, VIRTIO_CONFIG_STATUS_DRIVER_OK should be
>> set firstly, so that intr_handle is initialized in
>> virtio_user_start_device().
> I'm wondering why can't you let virtio-user follow virtio-pci?

It's because that virtio-user not only counts on 
virtio_user_start_device() to allocate intr_handle, it also needs the 
information in this function to initialize this struct. For virtio-pci, 
similar information is from rte_intr_enable/rte_intr_efd_enable.

Or do you mean we can move calling virtio_user_start_device() ahead? I 
can hardly find other place instead of DRIVER_OK.

Thanks,
Jianfeng
  
Yuanhan Liu March 29, 2017, 7:09 a.m. UTC | #3
On Wed, Mar 29, 2017 at 03:03:16PM +0800, Tan, Jianfeng wrote:
> 
> 
> On 3/29/2017 2:27 PM, Yuanhan Liu wrote:
> >On Tue, Mar 28, 2017 at 08:21:53AM +0000, Jianfeng Tan wrote:
> >>For virtio PCI devices, interrupt should be configured before setting
> >>VIRTIO_CONFIG_STATUS_DRIVER_OK so that QEMU can properly set eventfds
> >>in the host.
> >>
> >>For virtio virtual devices, VIRTIO_CONFIG_STATUS_DRIVER_OK should be
> >>set firstly, so that intr_handle is initialized in
> >>virtio_user_start_device().
> >I'm wondering why can't you let virtio-user follow virtio-pci?
> 
> It's because that virtio-user not only counts on virtio_user_start_device()
> to allocate intr_handle, it also needs the information in this function to
> initialize this struct. For virtio-pci, similar information is from
> rte_intr_enable/rte_intr_efd_enable.
> 
> Or do you mean we can move calling virtio_user_start_device() ahead? I can
> hardly find other place instead of DRIVER_OK.

For example, virtio_user_dev_init()?

	--yliu
  
Jianfeng Tan March 29, 2017, 7:27 a.m. UTC | #4
On 3/29/2017 3:09 PM, Yuanhan Liu wrote:
> On Wed, Mar 29, 2017 at 03:03:16PM +0800, Tan, Jianfeng wrote:
>>
>> On 3/29/2017 2:27 PM, Yuanhan Liu wrote:
>>> On Tue, Mar 28, 2017 at 08:21:53AM +0000, Jianfeng Tan wrote:
>>>> For virtio PCI devices, interrupt should be configured before setting
>>>> VIRTIO_CONFIG_STATUS_DRIVER_OK so that QEMU can properly set eventfds
>>>> in the host.
>>>>
>>>> For virtio virtual devices, VIRTIO_CONFIG_STATUS_DRIVER_OK should be
>>>> set firstly, so that intr_handle is initialized in
>>>> virtio_user_start_device().
>>> I'm wondering why can't you let virtio-user follow virtio-pci?
>> It's because that virtio-user not only counts on virtio_user_start_device()
>> to allocate intr_handle, it also needs the information in this function to
>> initialize this struct. For virtio-pci, similar information is from
>> rte_intr_enable/rte_intr_efd_enable.
>>
>> Or do you mean we can move calling virtio_user_start_device() ahead? I can
>> hardly find other place instead of DRIVER_OK.
> For example, virtio_user_dev_init()?
>
>
But in that way, there is only one chance to negotiate features with the 
backend. What if we change the configuration through 
rte_eth_dev_configure()?

Yes, we can just put callfd/kickfd creation and intr_handle 
initialization into virtio_user_dev_init(), and its destructor into 
virtio_user_dev_uninit(). It sounds like a feasible way to go.

Thanks,
Jianfeng
  
Yuanhan Liu March 29, 2017, 7:30 a.m. UTC | #5
On Wed, Mar 29, 2017 at 03:27:28PM +0800, Tan, Jianfeng wrote:
> 
> 
> On 3/29/2017 3:09 PM, Yuanhan Liu wrote:
> >On Wed, Mar 29, 2017 at 03:03:16PM +0800, Tan, Jianfeng wrote:
> >>
> >>On 3/29/2017 2:27 PM, Yuanhan Liu wrote:
> >>>On Tue, Mar 28, 2017 at 08:21:53AM +0000, Jianfeng Tan wrote:
> >>>>For virtio PCI devices, interrupt should be configured before setting
> >>>>VIRTIO_CONFIG_STATUS_DRIVER_OK so that QEMU can properly set eventfds
> >>>>in the host.
> >>>>
> >>>>For virtio virtual devices, VIRTIO_CONFIG_STATUS_DRIVER_OK should be
> >>>>set firstly, so that intr_handle is initialized in
> >>>>virtio_user_start_device().
> >>>I'm wondering why can't you let virtio-user follow virtio-pci?
> >>It's because that virtio-user not only counts on virtio_user_start_device()
> >>to allocate intr_handle, it also needs the information in this function to
> >>initialize this struct. For virtio-pci, similar information is from
> >>rte_intr_enable/rte_intr_efd_enable.
> >>
> >>Or do you mean we can move calling virtio_user_start_device() ahead? I can
> >>hardly find other place instead of DRIVER_OK.
> >For example, virtio_user_dev_init()?
> >
> >
> But in that way, there is only one chance to negotiate features with the
> backend. What if we change the configuration through
> rte_eth_dev_configure()?

Then there will be a reset; everything should be reset properly in the
device.

	--yliu
> 
> Yes, we can just put callfd/kickfd creation and intr_handle initialization
> into virtio_user_dev_init(), and its destructor into
> virtio_user_dev_uninit(). It sounds like a feasible way to go.
> 
> Thanks,
> Jianfeng
  

Patch

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index d9986ab..f0213ba 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1275,7 +1275,7 @@  virtio_queues_unbind_intr(struct rte_eth_dev *dev)
 }
 
 static int
-virtio_configure_intr(struct rte_eth_dev *dev)
+virtio_configure_intr_pci(struct rte_eth_dev *dev)
 {
 	struct virtio_hw *hw = dev->data->dev_private;
 
@@ -1327,6 +1327,37 @@  virtio_configure_intr(struct rte_eth_dev *dev)
 	return 0;
 }
 
+static int
+virtio_configure_intr_vdev(struct rte_eth_dev *dev)
+{
+	struct virtio_hw *hw = dev->data->dev_private;
+
+	if (!dev->intr_handle->intr_vec) {
+		dev->intr_handle->intr_vec =
+			rte_zmalloc("intr_vec",
+				    hw->max_queue_pairs * sizeof(int), 0);
+		if (!dev->intr_handle->intr_vec) {
+			PMD_INIT_LOG(ERR, "Failed to allocate %u rxq vectors",
+				     hw->max_queue_pairs);
+			return -ENOMEM;
+		}
+	}
+
+	/* Re-register callback to update max_intr */
+	rte_intr_callback_unregister(dev->intr_handle,
+				     virtio_interrupt_handler,
+				     dev);
+	rte_intr_callback_register(dev->intr_handle,
+				   virtio_interrupt_handler,
+				   dev);
+
+	if (virtio_queues_bind_intr(dev) < 0) {
+		PMD_INIT_LOG(ERR, "Failed to bind queue/interrupt");
+		return -1;
+	}
+
+	return 0;
+}
 /* reset device and renegotiate features if needed */
 static int
 virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features)
@@ -1450,15 +1481,29 @@  virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features)
 	if (ret < 0)
 		return ret;
 
-	if (eth_dev->data->dev_conf.intr_conf.rxq) {
-		if (virtio_configure_intr(eth_dev) < 0) {
-			PMD_INIT_LOG(ERR, "failed to configure interrupt");
-			return -1;
-		}
+	/* For virtio PCI devices, setup interrupt configuration before
+	 * setting VIRTIO_CONFIG_STATUS_DRIVER_OK, required by QEMU.
+	 */
+	if (pci_dev &&
+	    eth_dev->data->dev_conf.intr_conf.rxq &&
+	    virtio_configure_intr_pci(eth_dev) < 0) {
+		PMD_INIT_LOG(ERR, "failed to configure interrupt");
+		return -1;
 	}
 
 	vtpci_reinit_complete(hw);
 
+	/* For virtio vdev, setup interrupt configuration after
+	 * setting VIRTIO_CONFIG_STATUS_DRIVER_OK, so that intr_handle
+	 * is initialized in virtio_user_start_device().
+	 */
+	if (!pci_dev &&
+	    eth_dev->data->dev_conf.intr_conf.rxq &&
+	    virtio_configure_intr_vdev(eth_dev) < 0) {
+		PMD_INIT_LOG(ERR, "failed to configure interrupt");
+		return -1;
+	}
+
 	if (pci_dev)
 		PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x",
 			eth_dev->data->port_id, pci_dev->id.vendor_id,