--- e1000.orig/e1000_main.c 2004-08-14 04:55:10.000000000 -0600 +++ e1000/e1000_main.c 2004-08-26 12:38:30.602191640 -0600 @@ -143,7 +143,9 @@ #else static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter); #endif -static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter); +static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, + int from_irq); +static void e1000_alloc_task(struct e1000_adapter *adapter); static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); @@ -263,7 +265,7 @@ e1000_configure_tx(adapter); e1000_setup_rctl(adapter); e1000_configure_rx(adapter); - e1000_alloc_rx_buffers(adapter); + e1000_alloc_rx_buffers(adapter, 0); if((err = request_irq(adapter->pdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, @@ -286,6 +288,10 @@ del_timer_sync(&adapter->tx_fifo_stall_timer); del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->phy_info_timer); + while (adapter->alloc_scheduled) { + printk("waiting for e1000_alloc_task...\n"); + mdelay(5); + } adapter->link_speed = 0; adapter->link_duplex = 0; netif_carrier_off(netdev); @@ -530,6 +536,9 @@ adapter->phy_info_timer.function = &e1000_update_phy_info; adapter->phy_info_timer.data = (unsigned long) adapter; + INIT_WORK(&adapter->alloc_task, + (void (*)(void *))e1000_alloc_task, adapter); + INIT_WORK(&adapter->tx_timeout_task, (void (*)(void *))e1000_tx_timeout_task, netdev); @@ -1203,7 +1212,7 @@ if(netif_running(netdev)) { e1000_configure_rx(adapter); - e1000_alloc_rx_buffers(adapter); + e1000_alloc_rx_buffers(adapter, 0); } } @@ -2356,7 +2365,7 @@ rx_ring->next_to_clean = i; - e1000_alloc_rx_buffers(adapter); + e1000_alloc_rx_buffers(adapter, 1); return cleaned; } @@ -2364,10 +2373,11 @@ /** * e1000_alloc_rx_buffers - Replace used receive buffers * @adapter: address of board private structure + * @from_irq: 1 if called from an interrupt, 0 if not **/ static void -e1000_alloc_rx_buffers(struct e1000_adapter *adapter) +e1000_alloc_rx_buffers(struct e1000_adapter *adapter, int from_irq) { struct e1000_desc_ring *rx_ring = &adapter->rx_ring; struct net_device *netdev = adapter->netdev; @@ -2376,17 +2386,21 @@ struct e1000_buffer *buffer_info; struct sk_buff *skb; unsigned int i; + int need_alloc = 0; i = rx_ring->next_to_use; buffer_info = &rx_ring->buffer_info[i]; while(!buffer_info->skb) { rx_desc = E1000_RX_DESC(*rx_ring, i); - - skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN); - + skb = buffer_info->future_skb; + if(!skb && !from_irq) { + skb = alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN, + GFP_KERNEL); + } if(!skb) { - /* Better luck next round */ + /* Wait for the timer */ + need_alloc = 1; break; } @@ -2399,6 +2413,7 @@ skb->dev = netdev; buffer_info->skb = skb; + buffer_info->future_skb = NULL; buffer_info->length = adapter->rx_buffer_len; buffer_info->dma = pci_map_single(pdev, @@ -2423,9 +2438,47 @@ } rx_ring->next_to_use = i; + if (need_alloc && !adapter->alloc_scheduled) { + adapter->alloc_scheduled = 1; + schedule_work(&adapter->alloc_task); + } } /** + * e1000_alloc_task - Allocate skbs to be consumed by e1000_alloc_rx_buffers + * @adapter: address of board private structure + **/ + +static void e1000_alloc_task(struct e1000_adapter *adapter) { + struct e1000_desc_ring *rx_ring = &adapter->rx_ring; + struct e1000_buffer *buffer_info; + struct sk_buff *skb; + unsigned int i; + int count = 0; + + i = rx_ring->next_to_use; + buffer_info = &rx_ring->buffer_info[i]; + + while(!buffer_info->skb && !buffer_info->future_skb) { + skb = alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN, + GFP_KERNEL); + if(!skb) { + /* Better luck next round */ + break; + } + count++; + buffer_info->future_skb = skb; + if(++i == rx_ring->count) i = 0; + buffer_info = &rx_ring->buffer_info[i]; + } + if(count >= 10) + printk("e1000: allocated %d buffers\n", count); + adapter->alloc_scheduled = 0; +} + + + +/** * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers. * @adapter: **/ --- e1000.orig/e1000.h 2004-08-14 04:54:47.000000000 -0600 +++ e1000/e1000.h 2004-08-26 12:25:04.000000000 -0600 @@ -151,7 +151,7 @@ /* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer */ struct e1000_buffer { - struct sk_buff *skb; + struct sk_buff *skb, *future_skb; uint64_t dma; unsigned long length; unsigned long time_stamp; @@ -202,6 +202,8 @@ spinlock_t stats_lock; atomic_t irq_sem; struct work_struct tx_timeout_task; + struct work_struct alloc_task; + int alloc_scheduled; uint8_t fc_autoneg; struct timer_list blink_timer;