Signed-off-by: Edward Cree <ec...@solarflare.com>
---
 drivers/net/ethernet/sfc/efx.c        | 11 +++++++++--
 drivers/net/ethernet/sfc/net_driver.h |  1 +
 drivers/net/ethernet/sfc/rx.c         | 16 +++++++++++++---
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 330233286e78..dba13a28014c 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -263,9 +263,9 @@ static int efx_check_disabled(struct efx_nic *efx)
  */
 static int efx_process_channel(struct efx_channel *channel, int budget)
 {
+       struct list_head rx_list, gro_list;
        struct efx_tx_queue *tx_queue;
-       struct list_head rx_list;
-       int spent;
+       int spent, gro_count;
 
        if (unlikely(!channel->enabled))
                return 0;
@@ -275,6 +275,10 @@ static int efx_process_channel(struct efx_channel 
*channel, int budget)
        INIT_LIST_HEAD(&rx_list);
        channel->rx_list = &rx_list;
 
+       EFX_WARN_ON_PARANOID(channel->gro_list != NULL);
+       INIT_LIST_HEAD(&gro_list);
+       channel->gro_list = &gro_list;
+
        efx_for_each_channel_tx_queue(tx_queue, channel) {
                tx_queue->pkts_compl = 0;
                tx_queue->bytes_compl = 0;
@@ -300,6 +304,9 @@ static int efx_process_channel(struct efx_channel *channel, 
int budget)
        /* Receive any packets we queued up */
        netif_receive_skb_list(channel->rx_list);
        channel->rx_list = NULL;
+       gro_count = napi_gro_receive_list(&channel->napi_str, 
channel->gro_list);
+       channel->irq_mod_score += gro_count * 2;
+       channel->gro_list = NULL;
 
        return spent;
 }
diff --git a/drivers/net/ethernet/sfc/net_driver.h 
b/drivers/net/ethernet/sfc/net_driver.h
index 961b92979640..72addac7a84a 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -502,6 +502,7 @@ struct efx_channel {
        unsigned int rx_pkt_index;
 
        struct list_head *rx_list;
+       struct list_head *gro_list;
 
        struct efx_rx_queue rx_queue;
        struct efx_tx_queue tx_queue[EFX_TXQ_TYPES];
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 396ff01298cd..0534a54048c6 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -453,9 +453,19 @@ efx_rx_packet_gro(struct efx_channel *channel, struct 
efx_rx_buffer *rx_buf,
 
        skb_record_rx_queue(skb, channel->rx_queue.core_index);
 
-       gro_result = napi_gro_frags(napi);
-       if (gro_result != GRO_DROP)
-               channel->irq_mod_score += 2;
+       /* Pass the packet up */
+       if (channel->gro_list != NULL) {
+               /* Clear napi->skb and prepare skb for GRO */
+               skb = napi_frags_skb(napi);
+               if (skb)
+                       /* Add to list, will pass up later */
+                       list_add_tail(&skb->list, channel->gro_list);
+       } else {
+               /* No list, so pass it up now */
+               gro_result = napi_gro_frags(napi);
+               if (gro_result != GRO_DROP)
+                       channel->irq_mod_score += 2;
+       }
 }
 
 /* Allocate and construct an SKB around page fragments */

Reply via email to