However, the error handling logic was flawed:
1. Read Failure (err <= 0): The TX VQ completion
(vdpasim_net_complete(txq, 0)) was performed, but the unconditional
break that followed prevented theprocessing of subsequent pending work
items (other descriptors) in the queue in the same work function call.
2. Write Failure (write <= 0): If data could not be written to the RX VQ
descriptor (e.g., vringh_iov_push_iotlb failed), the flow would 'break'
before the TX VQ descriptor was completed. This led to a leak of TX VQ
descriptors, as the work was never notified that the TX buffer was
free to use again.
This commit refactors the control flow to ensure:
a) The TX VQ descriptor is completed back to the rx in all error and
success paths related to the current descriptor processing.
b) The unconditional break on read failure is removed, allowing the
function to continue processing remaining work items
until the loop naturally exits.
Fixes: 0899774cb360 ("vdpa_sim_net: vendor satistics")
---
Signed-off-by: Angus Chen <[email protected]>
---
drivers/vdpa/vdpa_sim/vdpa_sim_net.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c
b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c
index 6caf09a1907b..298bd6e8e0a0 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c
@@ -242,22 +242,22 @@ static void vdpasim_net_work(struct vdpasim *vdpasim)
if (err <= 0) {
++rx_overruns;
vdpasim_net_complete(txq, 0);
- break;
- }
-
- write = vringh_iov_push_iotlb(&rxq->vring, &rxq->in_iov,
- net->buffer, read);
- if (write <= 0) {
- ++rx_errors;
- break;
+ } else {
+
+ write = vringh_iov_push_iotlb(&rxq->vring, &rxq->in_iov,
+ net->buffer, read);
+ if (write <= 0) {
+ ++rx_errors;
+ vdpasim_net_complete(txq, 0);
+ break;
+ }
+
+ ++rx_pkts;
+ rx_bytes += write;
+ vdpasim_net_complete(txq, 0);
+ vdpasim_net_complete(rxq, write);
}
- ++rx_pkts;
- rx_bytes += write;
-
- vdpasim_net_complete(txq, 0);
- vdpasim_net_complete(rxq, write);
-
if (tx_pkts > 4) {
vdpasim_schedule_work(vdpasim);
goto out;
--
2.34.1