summaryrefslogtreecommitdiffstats
path: root/src/net/netdevice.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/netdevice.c')
-rw-r--r--src/net/netdevice.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 3b02e64bd..6e685630c 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -307,6 +307,12 @@ int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
if ( ( rc = inject_fault ( NETDEV_DISCARD_RATE ) ) != 0 )
goto err;
+ /* Map for DMA, if required */
+ if ( netdev->dma && ( ! dma_mapped ( &iobuf->map ) ) ) {
+ if ( ( rc = iob_map_tx ( iobuf, netdev->dma ) ) != 0 )
+ goto err;
+ }
+
/* Transmit packet */
if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
goto err;
@@ -340,6 +346,9 @@ int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
* Failure to do this will cause the retransmitted packet to be
* immediately redeferred (which will result in out-of-order
* transmissions and other nastiness).
+ *
+ * I/O buffers that have been mapped for DMA will remain mapped while
+ * present in the deferred transmit queue.
*/
void netdev_tx_defer ( struct net_device *netdev, struct io_buffer *iobuf ) {
@@ -365,6 +374,9 @@ void netdev_tx_defer ( struct net_device *netdev, struct io_buffer *iobuf ) {
*
* The packet is discarded and a TX error is recorded. This function
* takes ownership of the I/O buffer.
+ *
+ * The I/O buffer will be automatically unmapped for DMA, if
+ * applicable.
*/
void netdev_tx_err ( struct net_device *netdev,
struct io_buffer *iobuf, int rc ) {
@@ -379,6 +391,10 @@ void netdev_tx_err ( struct net_device *netdev,
netdev->name, iobuf, strerror ( rc ) );
}
+ /* Unmap I/O buffer, if required */
+ if ( iobuf && dma_mapped ( &iobuf->map ) )
+ iob_unmap ( iobuf );
+
/* Discard packet */
free_iob ( iobuf );
}
@@ -462,10 +478,13 @@ static void netdev_tx_flush ( struct net_device *netdev ) {
* Add packet to receive queue
*
* @v netdev Network device
- * @v iobuf I/O buffer, or NULL
+ * @v iobuf I/O buffer
*
* The packet is added to the network device's RX queue. This
* function takes ownership of the I/O buffer.
+ *
+ * The I/O buffer will be automatically unmapped for DMA, if
+ * applicable.
*/
void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
int rc;
@@ -479,6 +498,10 @@ void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
return;
}
+ /* Unmap I/O buffer, if required */
+ if ( dma_mapped ( &iobuf->map ) )
+ iob_unmap ( iobuf );
+
/* Enqueue packet */
list_add_tail ( &iobuf->list, &netdev->rx_queue );
@@ -497,6 +520,9 @@ void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
* takes ownership of the I/O buffer. @c iobuf may be NULL if, for
* example, the net device wishes to report an error due to being
* unable to allocate an I/O buffer.
+ *
+ * The I/O buffer will be automatically unmapped for DMA, if
+ * applicable.
*/
void netdev_rx_err ( struct net_device *netdev,
struct io_buffer *iobuf, int rc ) {
@@ -504,6 +530,10 @@ void netdev_rx_err ( struct net_device *netdev,
DBGC ( netdev, "NETDEV %s failed to receive %p: %s\n",
netdev->name, iobuf, strerror ( rc ) );
+ /* Unmap I/O buffer, if required */
+ if ( iobuf && dma_mapped ( &iobuf->map ) )
+ iob_unmap ( iobuf );
+
/* Discard packet */
free_iob ( iobuf );
@@ -1178,6 +1208,8 @@ static unsigned int net_discard ( void ) {
/* Discard first deferred packet */
list_del ( &iobuf->list );
+ if ( dma_mapped ( &iobuf->map ) )
+ iob_unmap ( iobuf );
free_iob ( iobuf );
/* Report discard */