Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / net / e1000e / netdev.c
index 3d57ca5..5d7a760 100644 (file)
@@ -450,13 +450,23 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
 
                length = le16_to_cpu(rx_desc->length);
 
-               /* !EOP means multiple descriptors were used to store a single
-                * packet, also make sure the frame isn't just CRC only */
-               if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) {
+               /*
+                * !EOP means multiple descriptors were used to store a single
+                * packet, if that's the case we need to toss it.  In fact, we
+                * need to toss every packet with the EOP bit clear and the
+                * next frame that _does_ have the EOP bit set, as it is by
+                * definition only a frame fragment
+                */
+               if (unlikely(!(status & E1000_RXD_STAT_EOP)))
+                       adapter->flags2 |= FLAG2_IS_DISCARDING;
+
+               if (adapter->flags2 & FLAG2_IS_DISCARDING) {
                        /* All receives must fit into a single buffer */
                        e_dbg("Receive packet consumed multiple buffers\n");
                        /* recycle */
                        buffer_info->skb = skb;
+                       if (status & E1000_RXD_STAT_EOP)
+                               adapter->flags2 &= ~FLAG2_IS_DISCARDING;
                        goto next_desc;
                }
 
@@ -745,10 +755,16 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
                                 PCI_DMA_FROMDEVICE);
                buffer_info->dma = 0;
 
-               if (!(staterr & E1000_RXD_STAT_EOP)) {
+               /* see !EOP comment in other rx routine */
+               if (!(staterr & E1000_RXD_STAT_EOP))
+                       adapter->flags2 |= FLAG2_IS_DISCARDING;
+
+               if (adapter->flags2 & FLAG2_IS_DISCARDING) {
                        e_dbg("Packet Split buffers didn't pick up the full "
                              "packet\n");
                        dev_kfree_skb_irq(skb);
+                       if (staterr & E1000_RXD_STAT_EOP)
+                               adapter->flags2 &= ~FLAG2_IS_DISCARDING;
                        goto next_desc;
                }
 
@@ -1118,6 +1134,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
 
        rx_ring->next_to_clean = 0;
        rx_ring->next_to_use = 0;
+       adapter->flags2 &= ~FLAG2_IS_DISCARDING;
 
        writel(0, adapter->hw.hw_addr + rx_ring->head);
        writel(0, adapter->hw.hw_addr + rx_ring->tail);
@@ -3952,13 +3969,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
 dma_error:
        dev_err(&pdev->dev, "TX DMA map failed\n");
        buffer_info->dma = 0;
-       count--;
-
-       while (count >= 0) {
+       if (count)
                count--;
-               i--;
-               if (i < 0)
+
+       while (count--) {
+               if (i==0)
                        i += tx_ring->count;
+               i--;
                buffer_info = &tx_ring->buffer_info[i];
                e1000_put_txbuf(adapter, buffer_info);;
        }