From e822bc2a90016f206b051cce1287a655e66b6b9b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 9 Jan 2007 21:01:55 +0000 Subject: [PATCH] Autopadding was sometimes overwriting the struct list_head at the end of the packet buffer. Although pkbuffs are guaranteed to be at least PKB_ZLEN bytes long, there's no guarantee that the data starts at the start of the packet buffer. Since we have to align data for rtl8139 anyway, and since the start of the packet buffer is guaranteed to be aligned to PKB_ALIGN, we may as well just shuffle the packet down so that it starts at the start of the packet buffer. This simultaneously aligns the packet and ensures that there is enough room for the zero-padding. --- src/drivers/net/rtl8139.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/drivers/net/rtl8139.c b/src/drivers/net/rtl8139.c index 5e37f9c1..4981329c 100644 --- a/src/drivers/net/rtl8139.c +++ b/src/drivers/net/rtl8139.c @@ -367,8 +367,10 @@ static void rtl_close ( struct net_device *netdev ) { */ static int rtl_transmit ( struct net_device *netdev, struct pk_buff *pkb ) { struct rtl8139_nic *rtl = netdev->priv; - int align; - int pad_len; + void *data; + size_t len; + size_t headroom; + signed int pad_len; /* Check for space in TX ring */ if ( rtl->tx.pkb[rtl->tx.next] != NULL ) { @@ -376,11 +378,18 @@ static int rtl_transmit ( struct net_device *netdev, struct pk_buff *pkb ) { return -ENOBUFS; } - /* Align packet data */ - align = ( virt_to_bus ( pkb->data ) & 0x3 ); - pkb_push ( pkb, align ); - memmove ( pkb->data, pkb->data + align, pkb_len ( pkb ) - align ); - pkb_unput ( pkb, align ); + /* Move packet data to start of packet buffer. This will both + * align the data (since packet buffers are aligned to + * PKB_ALIGN) and give us sufficient space for the + * zero-padding + */ + data = pkb->data; + len = pkb_len ( pkb ); + headroom = pkb_headroom ( pkb ); + pkb_push ( pkb, headroom ); + memmove ( pkb->data, data, len ); + pkb_unput ( pkb, headroom ); + assert ( ( virt_to_bus ( pkb->data ) & 0x3 ) == 0 ); /* Pad to minimum packet length */ pad_len = ( ETH_ZLEN - pkb_len ( pkb ) );