From d6115c91cfa4e3de72b87d3035b418d13b81e197 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 28 Jun 2011 10:19:23 +0100 Subject: [PATCH] [netdevice] Allow non-completion TX errors to be recorded Allow TX errors to be recorded against a network device even when the packet didn't make it as far as netdev_tx(). Inspired-by: Dominik Russenberger Signed-off-by: Michael Brown --- src/include/ipxe/netdevice.h | 2 ++ src/net/netdevice.c | 32 +++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h index e49191f4..64285984 100644 --- a/src/include/ipxe/netdevice.h +++ b/src/include/ipxe/netdevice.h @@ -586,6 +586,8 @@ netdev_rx_frozen ( struct net_device *netdev ) { extern void netdev_link_err ( struct net_device *netdev, int rc ); extern void netdev_link_down ( struct net_device *netdev ); extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ); +extern void netdev_tx_err ( struct net_device *netdev, + struct io_buffer *iobuf, int rc ); extern void netdev_tx_complete_err ( struct net_device *netdev, struct io_buffer *iobuf, int rc ); extern void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ); diff --git a/src/net/netdevice.c b/src/net/netdevice.c index 9a8a3aaf..54b41b3f 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -194,16 +194,17 @@ int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) { } /** - * Complete network transmission + * Discard transmitted packet * * @v netdev Network device - * @v iobuf I/O buffer + * @v iobuf I/O buffer, or NULL * @v rc Packet status code * - * The packet must currently be in the network device's TX queue. + * The packet is discarded and a TX error is recorded. This function + * takes ownership of the I/O buffer. */ -void netdev_tx_complete_err ( struct net_device *netdev, - struct io_buffer *iobuf, int rc ) { +void netdev_tx_err ( struct net_device *netdev, + struct io_buffer *iobuf, int rc ) { /* Update statistics counter */ netdev_record_stat ( &netdev->tx_stats, rc ); @@ -215,12 +216,28 @@ void netdev_tx_complete_err ( struct net_device *netdev, netdev->name, iobuf, strerror ( rc ) ); } + /* Discard packet */ + free_iob ( iobuf ); +} + +/** + * Complete network transmission + * + * @v netdev Network device + * @v iobuf I/O buffer + * @v rc Packet status code + * + * The packet must currently be in the network device's TX queue. + */ +void netdev_tx_complete_err ( struct net_device *netdev, + struct io_buffer *iobuf, int rc ) { + /* Catch data corruption as early as possible */ list_check_contains ( iobuf, &netdev->tx_queue, list ); /* Dequeue and free I/O buffer */ list_del ( &iobuf->list ); - free_iob ( iobuf ); + netdev_tx_err ( netdev, iobuf, rc ); } /** @@ -644,7 +661,8 @@ int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, /* Add link-layer header */ if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, ll_source, net_protocol->net_proto ) ) != 0 ) { - free_iob ( iobuf ); + /* Record error for diagnosis */ + netdev_tx_err ( netdev, iobuf, rc ); return rc; }