ixgbevf: Add fix to VF to handle multi-descriptor buffers
authorAlexander Duyck <alexander.h.duyck@intel.com>
Sat, 1 Sep 2012 05:12:38 +0000 (05:12 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Mon, 24 Sep 2012 08:50:35 +0000 (01:50 -0700)
This change fixes the ixgbevf driver so that it can correctly drop a frame
should it receive a jumbo frame.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c

index eb26fda..383b4e1 100644 (file)
@@ -261,6 +261,11 @@ enum ixbgevf_state_t {
        __IXGBEVF_DOWN
 };
 
+struct ixgbevf_cb {
+       struct sk_buff *prev;
+};
+#define IXGBE_CB(skb) ((struct ixgbevf_cb *)(skb)->cb)
+
 enum ixgbevf_boards {
        board_82599_vf,
        board_X540_vf,
index 37bbd86..2ba15ae 100644 (file)
@@ -433,11 +433,21 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
 
                if (!(staterr & IXGBE_RXD_STAT_EOP)) {
                        skb->next = next_buffer->skb;
-                       skb->next->prev = skb;
+                       IXGBE_CB(skb->next)->prev = skb;
                        adapter->non_eop_descs++;
                        goto next_desc;
                }
 
+               /* we should not be chaining buffers, if we did drop the skb */
+               if (IXGBE_CB(skb)->prev) {
+                       do {
+                               struct sk_buff *this = skb;
+                               skb = IXGBE_CB(skb)->prev;
+                               dev_kfree_skb(this);
+                       } while (skb);
+                       goto next_desc;
+               }
+
                /* ERR_MASK will only have valid bits if EOP set */
                if (unlikely(staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)) {
                        dev_kfree_skb_irq(skb);
@@ -1439,7 +1449,7 @@ static void ixgbevf_clean_rx_ring(struct ixgbevf_adapter *adapter,
                        rx_buffer_info->skb = NULL;
                        do {
                                struct sk_buff *this = skb;
-                               skb = skb->prev;
+                               skb = IXGBE_CB(skb)->prev;
                                dev_kfree_skb(this);
                        } while (skb);
                }