Skip to content

Commit 0d1ddfe

Browse files
committed
[gve] Cancel pending transmissions when closing device
We cancel any pending transmissions when (re)starting the device since any transmissions that were initiated before the admin queue reset will not complete. The network device core will also cancel any pending transmissions after the device is closed. If the device is closed with some transmissions still pending and is then reopened, this will therefore result in a stale I/O buffer being passed to netdev_tx_complete_err() when the device is restarted. This error has not been observed in practice since transmissions generally complete almost immediately and it is therefore unlikely that the device will ever be closed with transmissions still pending. With out-of-order queues, the device seems to delay transmit completions (with no upper time limit) until a complete batch is available to be written out as a block of 128 bytes. It is therefore very likely that the device will be closed with transmissions still pending. Fix by ensuring that we have dropped all references to transmit I/O buffers before returning from gve_close(). Signed-off-by: Michael Brown <[email protected]>
1 parent cf53497 commit 0d1ddfe

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

src/drivers/net/gve.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,18 +1073,14 @@ static void gve_free_queue ( struct gve_nic *gve, struct gve_queue *queue ) {
10731073
}
10741074

10751075
/**
1076-
* Start up device
1076+
* Cancel any pending transmissions
10771077
*
10781078
* @v gve GVE device
1079-
* @ret rc Return status code
10801079
*/
1081-
static int gve_start ( struct gve_nic *gve ) {
1080+
static void gve_cancel_tx ( struct gve_nic *gve ) {
10821081
struct net_device *netdev = gve->netdev;
1083-
struct gve_queue *tx = &gve->tx;
1084-
struct gve_queue *rx = &gve->rx;
10851082
struct io_buffer *iobuf;
10861083
unsigned int i;
1087-
int rc;
10881084

10891085
/* Cancel any pending transmissions */
10901086
for ( i = 0 ; i < ( sizeof ( gve->tx_iobuf ) /
@@ -1094,6 +1090,21 @@ static int gve_start ( struct gve_nic *gve ) {
10941090
if ( iobuf )
10951091
netdev_tx_complete_err ( netdev, iobuf, -ECANCELED );
10961092
}
1093+
}
1094+
1095+
/**
1096+
* Start up device
1097+
*
1098+
* @v gve GVE device
1099+
* @ret rc Return status code
1100+
*/
1101+
static int gve_start ( struct gve_nic *gve ) {
1102+
struct gve_queue *tx = &gve->tx;
1103+
struct gve_queue *rx = &gve->rx;
1104+
int rc;
1105+
1106+
/* Cancel any pending transmissions */
1107+
gve_cancel_tx ( gve );
10971108

10981109
/* Reset receive sequence */
10991110
gve->seq = gve_next ( 0 );
@@ -1307,6 +1318,9 @@ static void gve_close ( struct net_device *netdev ) {
13071318
gve_stop ( gve );
13081319
gve_reset ( gve );
13091320

1321+
/* Cancel any pending transmissions */
1322+
gve_cancel_tx ( gve );
1323+
13101324
/* Free queues */
13111325
gve_free_queue ( gve, rx );
13121326
gve_free_queue ( gve, tx );

0 commit comments

Comments
 (0)