[v3,08/11] net/virtio: add in-order Rx/Tx into selection

Message ID 20180628215235.106069-9-yong.liu@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Maxime Coquelin
Headers
Series support in-order feature |

Checks

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

Commit Message

Marvin Liu June 28, 2018, 9:52 p.m. UTC
  After IN_ORDER Rx/Tx paths added, need to update Rx/Tx path selection
logic.

Rx path select logic: If IN_ORDER is disabled will select normal Rx
path. If IN_ORDER is enabled, Rx offload and merge-able are disabled
will select simple Rx path. Otherwise will select IN_ORDER Rx path.

Tx path select logic: If IN_ORDER is disabled will select normal Tx
path. If IN_ORDER is enabled and merge-able is disabled will select
simple Tx path. Otherwise will select IN_ORDER Tx path.

Signed-off-by: Marvin Liu <yong.liu@intel.com>
  

Comments

Maxime Coquelin June 28, 2018, 3:16 p.m. UTC | #1
On 06/28/2018 11:52 PM, Marvin Liu wrote:
> After IN_ORDER Rx/Tx paths added, need to update Rx/Tx path selection
> logic.
> 
> Rx path select logic: If IN_ORDER is disabled will select normal Rx
> path. If IN_ORDER is enabled, Rx offload and merge-able are disabled
> will select simple Rx path. Otherwise will select IN_ORDER Rx path.
> 
> Tx path select logic: If IN_ORDER is disabled will select normal Tx
> path. If IN_ORDER is enabled and merge-able is disabled will select
> simple Tx path. Otherwise will select IN_ORDER Tx path.
> 
> Signed-off-by: Marvin Liu <yong.liu@intel.com>
> 
> diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
> index df50a571a..2b3d65f80 100644
> --- a/drivers/net/virtio/virtio_ethdev.c
> +++ b/drivers/net/virtio/virtio_ethdev.c
> @@ -1320,6 +1320,11 @@ set_rxtx_funcs(struct rte_eth_dev *eth_dev)
>   		PMD_INIT_LOG(INFO, "virtio: using simple Rx path on port %u",
>   			eth_dev->data->port_id);
>   		eth_dev->rx_pkt_burst = virtio_recv_pkts_vec;
> +	} else if (hw->use_inorder_rx) {
> +		PMD_INIT_LOG(INFO,
> +			"virtio: using inorder mergeable buffer Rx path on port %u",
> +			eth_dev->data->port_id);
> +		eth_dev->rx_pkt_burst = &virtio_recv_mergeable_pkts_inorder;
>   	} else if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
>   		PMD_INIT_LOG(INFO,
>   			"virtio: using mergeable buffer Rx path on port %u",
> @@ -1335,6 +1340,10 @@ set_rxtx_funcs(struct rte_eth_dev *eth_dev)
>   		PMD_INIT_LOG(INFO, "virtio: using simple Tx path on port %u",
>   			eth_dev->data->port_id);
>   		eth_dev->tx_pkt_burst = virtio_xmit_pkts_simple;
> +	} else if (hw->use_inorder_tx) {
> +		PMD_INIT_LOG(INFO, "virtio: using inorder Tx path on port %u",
> +			eth_dev->data->port_id);
> +		eth_dev->tx_pkt_burst = virtio_xmit_pkts_inorder;
>   	} else {
>   		PMD_INIT_LOG(INFO, "virtio: using standard Tx path on port %u",
>   			eth_dev->data->port_id);
> @@ -1871,24 +1880,24 @@ virtio_dev_configure(struct rte_eth_dev *dev)
>   
>   	rte_spinlock_init(&hw->state_lock);
>   
> -	hw->use_simple_rx = 1;
> -	hw->use_simple_tx = 1;
> -
>   #if defined RTE_ARCH_ARM64 || defined RTE_ARCH_ARM
>   	if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) {
>   		hw->use_simple_rx = 0;
>   		hw->use_simple_tx = 0;
>   	}
>   #endif
> -	if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
> -		hw->use_simple_rx = 0;
> -		hw->use_simple_tx = 0;
> +	if (vtpci_with_feature(hw, VIRTIO_F_IN_ORDER)) {
> +		if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
> +			hw->use_inorder_rx = 1;
> +			hw->use_inorder_tx = 1;
> +		} else {
> +			hw->use_simple_tx = 1;
> +			if (!(rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
> +					     DEV_RX_OFFLOAD_TCP_CKSUM)))
> +				hw->use_simple_rx = 1;
> +		}

It seems to be wrong.
For example if IN_ORDER hasn't been negotiated, we might want to use the 
simple path if no rx offload have been requested by the application.

It was the case before the patch if I'm not mistaken.

Also, with ARM platform, we force not to use simple path, but in case
IN_ORDER has been negotiated but not MRG_RXBUF, it gets re-enabled.

>   	}
>   
> -	if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
> -			   DEV_RX_OFFLOAD_TCP_CKSUM))
> -		hw->use_simple_rx = 0;
> -
>   	return 0;
>   }
>   
>
  
Marvin Liu June 28, 2018, 3:39 p.m. UTC | #2
> -----Original Message-----
> From: Maxime Coquelin [mailto:maxime.coquelin@redhat.com]
> Sent: Thursday, June 28, 2018 11:16 PM
> To: Liu, Yong <yong.liu@intel.com>; Bie, Tiwei <tiwei.bie@intel.com>
> Cc: Wang, Zhihong <zhihong.wang@intel.com>; dev@dpdk.org
> Subject: Re: [PATCH v3 08/11] net/virtio: add in-order Rx/Tx into
> selection
> 
> 
> 
> On 06/28/2018 11:52 PM, Marvin Liu wrote:
> > After IN_ORDER Rx/Tx paths added, need to update Rx/Tx path selection
> > logic.
> >
> > Rx path select logic: If IN_ORDER is disabled will select normal Rx
> > path. If IN_ORDER is enabled, Rx offload and merge-able are disabled
> > will select simple Rx path. Otherwise will select IN_ORDER Rx path.
> >
> > Tx path select logic: If IN_ORDER is disabled will select normal Tx
> > path. If IN_ORDER is enabled and merge-able is disabled will select
> > simple Tx path. Otherwise will select IN_ORDER Tx path.
> >
> > Signed-off-by: Marvin Liu <yong.liu@intel.com>
> >
> > diff --git a/drivers/net/virtio/virtio_ethdev.c
> b/drivers/net/virtio/virtio_ethdev.c
> > index df50a571a..2b3d65f80 100644
> > --- a/drivers/net/virtio/virtio_ethdev.c
> > +++ b/drivers/net/virtio/virtio_ethdev.c
> > @@ -1320,6 +1320,11 @@ set_rxtx_funcs(struct rte_eth_dev *eth_dev)
> >   		PMD_INIT_LOG(INFO, "virtio: using simple Rx path on port %u",
> >   			eth_dev->data->port_id);
> >   		eth_dev->rx_pkt_burst = virtio_recv_pkts_vec;
> > +	} else if (hw->use_inorder_rx) {
> > +		PMD_INIT_LOG(INFO,
> > +			"virtio: using inorder mergeable buffer Rx path on
> port %u",
> > +			eth_dev->data->port_id);
> > +		eth_dev->rx_pkt_burst = &virtio_recv_mergeable_pkts_inorder;
> >   	} else if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
> >   		PMD_INIT_LOG(INFO,
> >   			"virtio: using mergeable buffer Rx path on port %u",
> > @@ -1335,6 +1340,10 @@ set_rxtx_funcs(struct rte_eth_dev *eth_dev)
> >   		PMD_INIT_LOG(INFO, "virtio: using simple Tx path on port %u",
> >   			eth_dev->data->port_id);
> >   		eth_dev->tx_pkt_burst = virtio_xmit_pkts_simple;
> > +	} else if (hw->use_inorder_tx) {
> > +		PMD_INIT_LOG(INFO, "virtio: using inorder Tx path on port %u",
> > +			eth_dev->data->port_id);
> > +		eth_dev->tx_pkt_burst = virtio_xmit_pkts_inorder;
> >   	} else {
> >   		PMD_INIT_LOG(INFO, "virtio: using standard Tx path on port %u",
> >   			eth_dev->data->port_id);
> > @@ -1871,24 +1880,24 @@ virtio_dev_configure(struct rte_eth_dev *dev)
> >
> >   	rte_spinlock_init(&hw->state_lock);
> >
> > -	hw->use_simple_rx = 1;
> > -	hw->use_simple_tx = 1;
> > -
> >   #if defined RTE_ARCH_ARM64 || defined RTE_ARCH_ARM
> >   	if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) {
> >   		hw->use_simple_rx = 0;
> >   		hw->use_simple_tx = 0;
> >   	}
> >   #endif
> > -	if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
> > -		hw->use_simple_rx = 0;
> > -		hw->use_simple_tx = 0;
> > +	if (vtpci_with_feature(hw, VIRTIO_F_IN_ORDER)) {
> > +		if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
> > +			hw->use_inorder_rx = 1;
> > +			hw->use_inorder_tx = 1;
> > +		} else {
> > +			hw->use_simple_tx = 1;
> > +			if (!(rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
> > +					     DEV_RX_OFFLOAD_TCP_CKSUM)))
> > +				hw->use_simple_rx = 1;
> > +		}
> 
> It seems to be wrong.
> For example if IN_ORDER hasn't been negotiated, we might want to use the
> simple path if no rx offload have been requested by the application.
> 
> It was the case before the patch if I'm not mistaken.

Maxime,
IN_ORDER is the prerequisite for selection simple rx/tx path. So when IN_ORDER + mergeable off + no rx offload will chose simple rx path.

> 
> Also, with ARM platform, we force not to use simple path, but in case
> IN_ORDER has been negotiated but not MRG_RXBUF, it gets re-enabled.

Will move ARM force action behind normal selection, thus can satisfy ARM.

Thanks,
Marvin

> 
> >   	}
> >
> > -	if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
> > -			   DEV_RX_OFFLOAD_TCP_CKSUM))
> > -		hw->use_simple_rx = 0;
> > -
> >   	return 0;
> >   }
> >
> >
  
Maxime Coquelin June 29, 2018, 8:04 a.m. UTC | #3
On 06/28/2018 05:39 PM, Liu, Yong wrote:
> 
> 
>> -----Original Message-----
>> From: Maxime Coquelin [mailto:maxime.coquelin@redhat.com]
>> Sent: Thursday, June 28, 2018 11:16 PM
>> To: Liu, Yong <yong.liu@intel.com>; Bie, Tiwei <tiwei.bie@intel.com>
>> Cc: Wang, Zhihong <zhihong.wang@intel.com>; dev@dpdk.org
>> Subject: Re: [PATCH v3 08/11] net/virtio: add in-order Rx/Tx into
>> selection
>>
>>
>>
>> On 06/28/2018 11:52 PM, Marvin Liu wrote:
>>> After IN_ORDER Rx/Tx paths added, need to update Rx/Tx path selection
>>> logic.
>>>
>>> Rx path select logic: If IN_ORDER is disabled will select normal Rx
>>> path. If IN_ORDER is enabled, Rx offload and merge-able are disabled
>>> will select simple Rx path. Otherwise will select IN_ORDER Rx path.
>>>
>>> Tx path select logic: If IN_ORDER is disabled will select normal Tx
>>> path. If IN_ORDER is enabled and merge-able is disabled will select
>>> simple Tx path. Otherwise will select IN_ORDER Tx path.
>>>
>>> Signed-off-by: Marvin Liu <yong.liu@intel.com>
>>>
>>> diff --git a/drivers/net/virtio/virtio_ethdev.c
>> b/drivers/net/virtio/virtio_ethdev.c
>>> index df50a571a..2b3d65f80 100644
>>> --- a/drivers/net/virtio/virtio_ethdev.c
>>> +++ b/drivers/net/virtio/virtio_ethdev.c
>>> @@ -1320,6 +1320,11 @@ set_rxtx_funcs(struct rte_eth_dev *eth_dev)
>>>    		PMD_INIT_LOG(INFO, "virtio: using simple Rx path on port %u",
>>>    			eth_dev->data->port_id);
>>>    		eth_dev->rx_pkt_burst = virtio_recv_pkts_vec;
>>> +	} else if (hw->use_inorder_rx) {
>>> +		PMD_INIT_LOG(INFO,
>>> +			"virtio: using inorder mergeable buffer Rx path on
>> port %u",
>>> +			eth_dev->data->port_id);
>>> +		eth_dev->rx_pkt_burst = &virtio_recv_mergeable_pkts_inorder;
>>>    	} else if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
>>>    		PMD_INIT_LOG(INFO,
>>>    			"virtio: using mergeable buffer Rx path on port %u",
>>> @@ -1335,6 +1340,10 @@ set_rxtx_funcs(struct rte_eth_dev *eth_dev)
>>>    		PMD_INIT_LOG(INFO, "virtio: using simple Tx path on port %u",
>>>    			eth_dev->data->port_id);
>>>    		eth_dev->tx_pkt_burst = virtio_xmit_pkts_simple;
>>> +	} else if (hw->use_inorder_tx) {
>>> +		PMD_INIT_LOG(INFO, "virtio: using inorder Tx path on port %u",
>>> +			eth_dev->data->port_id);
>>> +		eth_dev->tx_pkt_burst = virtio_xmit_pkts_inorder;
>>>    	} else {
>>>    		PMD_INIT_LOG(INFO, "virtio: using standard Tx path on port %u",
>>>    			eth_dev->data->port_id);
>>> @@ -1871,24 +1880,24 @@ virtio_dev_configure(struct rte_eth_dev *dev)
>>>
>>>    	rte_spinlock_init(&hw->state_lock);
>>>
>>> -	hw->use_simple_rx = 1;
>>> -	hw->use_simple_tx = 1;
>>> -
>>>    #if defined RTE_ARCH_ARM64 || defined RTE_ARCH_ARM
>>>    	if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) {
>>>    		hw->use_simple_rx = 0;
>>>    		hw->use_simple_tx = 0;
>>>    	}
>>>    #endif
>>> -	if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
>>> -		hw->use_simple_rx = 0;
>>> -		hw->use_simple_tx = 0;
>>> +	if (vtpci_with_feature(hw, VIRTIO_F_IN_ORDER)) {
>>> +		if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
>>> +			hw->use_inorder_rx = 1;
>>> +			hw->use_inorder_tx = 1;
>>> +		} else {
>>> +			hw->use_simple_tx = 1;
>>> +			if (!(rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
>>> +					     DEV_RX_OFFLOAD_TCP_CKSUM)))
>>> +				hw->use_simple_rx = 1;
>>> +		}
>>
>> It seems to be wrong.
>> For example if IN_ORDER hasn't been negotiated, we might want to use the
>> simple path if no rx offload have been requested by the application.
>>
>> It was the case before the patch if I'm not mistaken.
> 
> Maxime,
> IN_ORDER is the prerequisite for selection simple rx/tx path. So when IN_ORDER + mergeable off + no rx offload will chose simple rx path.

Ok, I wonder in that case if I could just remove the simple Tx path in
my series as it is not compliant with IN_ORDER.
Tiwei, what's your take on this?

Also, I wonder if it would make sense to backport the vhost patch that 
advertize IN_ORDER features to the LTS, as no functional changes, except
that it prevents using "simple/inorder" path with dequeue zero copy,
which is a good thing.

Any thoughts?

>>
>> Also, with ARM platform, we force not to use simple path, but in case
>> IN_ORDER has been negotiated but not MRG_RXBUF, it gets re-enabled.
> 
> Will move ARM force action behind normal selection, thus can satisfy ARM.

I can change when applying.

Thanks,
Maxime

> Thanks,
> Marvin
> 
>>
>>>    	}
>>>
>>> -	if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
>>> -			   DEV_RX_OFFLOAD_TCP_CKSUM))
>>> -		hw->use_simple_rx = 0;
>>> -
>>>    	return 0;
>>>    }
>>>
>>>
  
Tiwei Bie June 30, 2018, 2:42 a.m. UTC | #4
On Fri, Jun 29, 2018 at 10:04:23AM +0200, Maxime Coquelin wrote:
> On 06/28/2018 05:39 PM, Liu, Yong wrote:
> > 
> > 
> > > -----Original Message-----
> > > From: Maxime Coquelin [mailto:maxime.coquelin@redhat.com]
> > > Sent: Thursday, June 28, 2018 11:16 PM
> > > To: Liu, Yong <yong.liu@intel.com>; Bie, Tiwei <tiwei.bie@intel.com>
> > > Cc: Wang, Zhihong <zhihong.wang@intel.com>; dev@dpdk.org
> > > Subject: Re: [PATCH v3 08/11] net/virtio: add in-order Rx/Tx into
> > > selection
> > > 
> > > 
> > > 
> > > On 06/28/2018 11:52 PM, Marvin Liu wrote:
> > > > After IN_ORDER Rx/Tx paths added, need to update Rx/Tx path selection
> > > > logic.
> > > > 
> > > > Rx path select logic: If IN_ORDER is disabled will select normal Rx
> > > > path. If IN_ORDER is enabled, Rx offload and merge-able are disabled
> > > > will select simple Rx path. Otherwise will select IN_ORDER Rx path.
> > > > 
> > > > Tx path select logic: If IN_ORDER is disabled will select normal Tx
> > > > path. If IN_ORDER is enabled and merge-able is disabled will select
> > > > simple Tx path. Otherwise will select IN_ORDER Tx path.
> > > > 
> > > > Signed-off-by: Marvin Liu <yong.liu@intel.com>
> > > > 
> > > > diff --git a/drivers/net/virtio/virtio_ethdev.c
> > > b/drivers/net/virtio/virtio_ethdev.c
> > > > index df50a571a..2b3d65f80 100644
> > > > --- a/drivers/net/virtio/virtio_ethdev.c
> > > > +++ b/drivers/net/virtio/virtio_ethdev.c
> > > > @@ -1320,6 +1320,11 @@ set_rxtx_funcs(struct rte_eth_dev *eth_dev)
> > > >    		PMD_INIT_LOG(INFO, "virtio: using simple Rx path on port %u",
> > > >    			eth_dev->data->port_id);
> > > >    		eth_dev->rx_pkt_burst = virtio_recv_pkts_vec;
> > > > +	} else if (hw->use_inorder_rx) {
> > > > +		PMD_INIT_LOG(INFO,
> > > > +			"virtio: using inorder mergeable buffer Rx path on
> > > port %u",
> > > > +			eth_dev->data->port_id);
> > > > +		eth_dev->rx_pkt_burst = &virtio_recv_mergeable_pkts_inorder;
> > > >    	} else if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
> > > >    		PMD_INIT_LOG(INFO,
> > > >    			"virtio: using mergeable buffer Rx path on port %u",
> > > > @@ -1335,6 +1340,10 @@ set_rxtx_funcs(struct rte_eth_dev *eth_dev)
> > > >    		PMD_INIT_LOG(INFO, "virtio: using simple Tx path on port %u",
> > > >    			eth_dev->data->port_id);
> > > >    		eth_dev->tx_pkt_burst = virtio_xmit_pkts_simple;
> > > > +	} else if (hw->use_inorder_tx) {
> > > > +		PMD_INIT_LOG(INFO, "virtio: using inorder Tx path on port %u",
> > > > +			eth_dev->data->port_id);
> > > > +		eth_dev->tx_pkt_burst = virtio_xmit_pkts_inorder;
> > > >    	} else {
> > > >    		PMD_INIT_LOG(INFO, "virtio: using standard Tx path on port %u",
> > > >    			eth_dev->data->port_id);
> > > > @@ -1871,24 +1880,24 @@ virtio_dev_configure(struct rte_eth_dev *dev)
> > > > 
> > > >    	rte_spinlock_init(&hw->state_lock);
> > > > 
> > > > -	hw->use_simple_rx = 1;
> > > > -	hw->use_simple_tx = 1;
> > > > -
> > > >    #if defined RTE_ARCH_ARM64 || defined RTE_ARCH_ARM
> > > >    	if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) {
> > > >    		hw->use_simple_rx = 0;
> > > >    		hw->use_simple_tx = 0;
> > > >    	}
> > > >    #endif
> > > > -	if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
> > > > -		hw->use_simple_rx = 0;
> > > > -		hw->use_simple_tx = 0;
> > > > +	if (vtpci_with_feature(hw, VIRTIO_F_IN_ORDER)) {
> > > > +		if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
> > > > +			hw->use_inorder_rx = 1;
> > > > +			hw->use_inorder_tx = 1;
> > > > +		} else {
> > > > +			hw->use_simple_tx = 1;
> > > > +			if (!(rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
> > > > +					     DEV_RX_OFFLOAD_TCP_CKSUM)))
> > > > +				hw->use_simple_rx = 1;
> > > > +		}
> > > 
> > > It seems to be wrong.
> > > For example if IN_ORDER hasn't been negotiated, we might want to use the
> > > simple path if no rx offload have been requested by the application.
> > > 
> > > It was the case before the patch if I'm not mistaken.
> > 
> > Maxime,
> > IN_ORDER is the prerequisite for selection simple rx/tx path. So when IN_ORDER + mergeable off + no rx offload will chose simple rx path.
> 
> Ok, I wonder in that case if I could just remove the simple Tx path in
> my series as it is not compliant with IN_ORDER.
> Tiwei, what's your take on this?
> 
> Also, I wonder if it would make sense to backport the vhost patch that
> advertize IN_ORDER features to the LTS, as no functional changes, except
> that it prevents using "simple/inorder" path with dequeue zero copy,
> which is a good thing.
> 
> Any thoughts?

IMO it's not right to choose the current simple Tx path
when IN_ORDER is negotiated. Because in split ring, IN_ORDER
requires the driver to use the descriptors in ring order
which is not the case in the current simple Tx path, and
things will go wrong when device wants to make full use
of the IN_ORDER feature.

Best regards,
Tiwei Bie


> 
> > > 
> > > Also, with ARM platform, we force not to use simple path, but in case
> > > IN_ORDER has been negotiated but not MRG_RXBUF, it gets re-enabled.
> > 
> > Will move ARM force action behind normal selection, thus can satisfy ARM.
> 
> I can change when applying.
> 
> Thanks,
> Maxime
> 
> > Thanks,
> > Marvin
> > 
> > > 
> > > >    	}
> > > > 
> > > > -	if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
> > > > -			   DEV_RX_OFFLOAD_TCP_CKSUM))
> > > > -		hw->use_simple_rx = 0;
> > > > -
> > > >    	return 0;
> > > >    }
> > > > 
> > > >
  

Patch

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index df50a571a..2b3d65f80 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1320,6 +1320,11 @@  set_rxtx_funcs(struct rte_eth_dev *eth_dev)
 		PMD_INIT_LOG(INFO, "virtio: using simple Rx path on port %u",
 			eth_dev->data->port_id);
 		eth_dev->rx_pkt_burst = virtio_recv_pkts_vec;
+	} else if (hw->use_inorder_rx) {
+		PMD_INIT_LOG(INFO,
+			"virtio: using inorder mergeable buffer Rx path on port %u",
+			eth_dev->data->port_id);
+		eth_dev->rx_pkt_burst = &virtio_recv_mergeable_pkts_inorder;
 	} else if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
 		PMD_INIT_LOG(INFO,
 			"virtio: using mergeable buffer Rx path on port %u",
@@ -1335,6 +1340,10 @@  set_rxtx_funcs(struct rte_eth_dev *eth_dev)
 		PMD_INIT_LOG(INFO, "virtio: using simple Tx path on port %u",
 			eth_dev->data->port_id);
 		eth_dev->tx_pkt_burst = virtio_xmit_pkts_simple;
+	} else if (hw->use_inorder_tx) {
+		PMD_INIT_LOG(INFO, "virtio: using inorder Tx path on port %u",
+			eth_dev->data->port_id);
+		eth_dev->tx_pkt_burst = virtio_xmit_pkts_inorder;
 	} else {
 		PMD_INIT_LOG(INFO, "virtio: using standard Tx path on port %u",
 			eth_dev->data->port_id);
@@ -1871,24 +1880,24 @@  virtio_dev_configure(struct rte_eth_dev *dev)
 
 	rte_spinlock_init(&hw->state_lock);
 
-	hw->use_simple_rx = 1;
-	hw->use_simple_tx = 1;
-
 #if defined RTE_ARCH_ARM64 || defined RTE_ARCH_ARM
 	if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) {
 		hw->use_simple_rx = 0;
 		hw->use_simple_tx = 0;
 	}
 #endif
-	if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
-		hw->use_simple_rx = 0;
-		hw->use_simple_tx = 0;
+	if (vtpci_with_feature(hw, VIRTIO_F_IN_ORDER)) {
+		if (vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
+			hw->use_inorder_rx = 1;
+			hw->use_inorder_tx = 1;
+		} else {
+			hw->use_simple_tx = 1;
+			if (!(rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
+					     DEV_RX_OFFLOAD_TCP_CKSUM)))
+				hw->use_simple_rx = 1;
+		}
 	}
 
-	if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
-			   DEV_RX_OFFLOAD_TCP_CKSUM))
-		hw->use_simple_rx = 0;
-
 	return 0;
 }