|
@@ -910,6 +910,44 @@ static inline void ixgbevf_irq_enable_queues(struct ixgbevf_adapter *adapter,
|
|
IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, qmask);
|
|
IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, qmask);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static struct sk_buff *ixgbevf_build_skb(struct ixgbevf_ring *rx_ring,
|
|
|
|
+ struct ixgbevf_rx_buffer *rx_buffer,
|
|
|
|
+ union ixgbe_adv_rx_desc *rx_desc,
|
|
|
|
+ unsigned int size)
|
|
|
|
+{
|
|
|
|
+ void *va = page_address(rx_buffer->page) + rx_buffer->page_offset;
|
|
|
|
+#if (PAGE_SIZE < 8192)
|
|
|
|
+ unsigned int truesize = ixgbevf_rx_pg_size(rx_ring) / 2;
|
|
|
|
+#else
|
|
|
|
+ unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
|
|
|
|
+ SKB_DATA_ALIGN(IXGBEVF_SKB_PAD + size);
|
|
|
|
+#endif
|
|
|
|
+ struct sk_buff *skb;
|
|
|
|
+
|
|
|
|
+ /* prefetch first cache line of first page */
|
|
|
|
+ prefetch(va);
|
|
|
|
+#if L1_CACHE_BYTES < 128
|
|
|
|
+ prefetch(va + L1_CACHE_BYTES);
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ /* build an skb to around the page buffer */
|
|
|
|
+ skb = build_skb(va - IXGBEVF_SKB_PAD, truesize);
|
|
|
|
+ if (unlikely(!skb))
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ /* update pointers within the skb to store the data */
|
|
|
|
+ skb_reserve(skb, IXGBEVF_SKB_PAD);
|
|
|
|
+ __skb_put(skb, size);
|
|
|
|
+
|
|
|
|
+ /* update buffer offset */
|
|
|
|
+#if (PAGE_SIZE < 8192)
|
|
|
|
+ rx_buffer->page_offset ^= truesize;
|
|
|
|
+#else
|
|
|
|
+ rx_buffer->page_offset += truesize;
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ return skb;
|
|
|
|
+}
|
|
static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
|
|
static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
|
|
struct ixgbevf_ring *rx_ring,
|
|
struct ixgbevf_ring *rx_ring,
|
|
int budget)
|
|
int budget)
|
|
@@ -945,6 +983,9 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
|
|
/* retrieve a buffer from the ring */
|
|
/* retrieve a buffer from the ring */
|
|
if (skb)
|
|
if (skb)
|
|
ixgbevf_add_rx_frag(rx_ring, rx_buffer, skb, size);
|
|
ixgbevf_add_rx_frag(rx_ring, rx_buffer, skb, size);
|
|
|
|
+ else if (ring_uses_build_skb(rx_ring))
|
|
|
|
+ skb = ixgbevf_build_skb(rx_ring, rx_buffer,
|
|
|
|
+ rx_desc, size);
|
|
else
|
|
else
|
|
skb = ixgbevf_construct_skb(rx_ring, rx_buffer,
|
|
skb = ixgbevf_construct_skb(rx_ring, rx_buffer,
|
|
rx_desc, size);
|
|
rx_desc, size);
|