static void efx_rx_deliver(struct efx_channel *channel, u8 *eh, struct efx_rx_buffer *rx_buf, unsigned int n_frags) { struct sk_buff *skb; u16 hdr_len = min_t(u16, rx_buf->len, EFX_SKB_HEADERS); skb = efx_rx_mk_skb(channel, rx_buf, n_frags, eh, hdr_len); if (unlikely(skb == NULL)) { efx_free_rx_buffer(rx_buf); return; } skb_record_rx_queue(skb, channel->rx_queue.core_index); /* Set the SKB flags */ skb_checksum_none_assert(skb); if (likely(rx_buf->flags & EFX_RX_PKT_CSUMMED)) skb->ip_summed = CHECKSUM_UNNECESSARY; if (channel->type->receive_skb) if (channel->type->receive_skb(channel, skb)) return; /* Pass the packet up */ netif_receive_skb(skb); }
/* Handle a received packet. Second half: Touches packet payload. */ void __efx_rx_packet(struct efx_channel *channel) { struct efx_nic *efx = channel->efx; struct efx_rx_buffer *rx_buf = efx_rx_buffer(&channel->rx_queue, channel->rx_pkt_index); u8 *eh = efx_rx_buf_va(rx_buf); /* If we're in loopback test, then pass the packet directly to the * loopback layer, and free the rx_buf here */ if (unlikely(efx->loopback_selftest)) { efx_loopback_rx_packet(efx, eh, rx_buf->len); efx_free_rx_buffer(rx_buf); goto out; } if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM))) rx_buf->flags &= ~EFX_RX_PKT_CSUMMED; if ((rx_buf->flags & EFX_RX_PKT_TCP) && !channel->type->receive_skb) efx_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh); else efx_rx_deliver(channel, eh, rx_buf, channel->rx_pkt_n_frags); out: channel->rx_pkt_n_frags = 0; }
/* Handle a received packet. Second half: Touches packet payload. */ void __efx_rx_packet(struct efx_channel *channel, struct efx_rx_buffer *rx_buf, bool checksummed) { struct efx_nic *efx = channel->efx; struct sk_buff *skb; /* If we're in loopback test, then pass the packet directly to the * loopback layer, and free the rx_buf here */ if (unlikely(efx->loopback_selftest)) { efx_loopback_rx_packet(efx, rx_buf->data, rx_buf->len); efx_free_rx_buffer(efx, rx_buf); goto done; } if (rx_buf->skb) { prefetch(skb_shinfo(rx_buf->skb)); skb_put(rx_buf->skb, rx_buf->len); /* Move past the ethernet header. rx_buf->data still points * at the ethernet header */ rx_buf->skb->protocol = eth_type_trans(rx_buf->skb, efx->net_dev); } if (likely(checksummed || rx_buf->page)) { efx_rx_packet_lro(channel, rx_buf); goto done; } /* We now own the SKB */ skb = rx_buf->skb; rx_buf->skb = NULL; EFX_BUG_ON_PARANOID(rx_buf->page); EFX_BUG_ON_PARANOID(rx_buf->skb); EFX_BUG_ON_PARANOID(!skb); /* Set the SKB flags */ skb->ip_summed = CHECKSUM_NONE; skb_record_rx_queue(skb, channel->channel); /* Pass the packet up */ netif_receive_skb(skb); /* Update allocation strategy method */ channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; done: ; }
static void efx_discard_rx_packet(struct efx_channel *channel, struct efx_rx_buffer *rx_buf, unsigned int n_frags) { struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel); efx_recycle_rx_pages(channel, rx_buf, n_frags); do { efx_free_rx_buffer(rx_buf); rx_buf = efx_rx_buf_next(rx_queue, rx_buf); } while (--n_frags); }
static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, struct efx_rx_buffer *rx_buf) { /* Release the page reference we hold for the buffer. */ if (rx_buf->page) put_page(rx_buf->page); /* If this is the last buffer in a page, unmap and free it. */ if (rx_buf->flags & EFX_RX_BUF_LAST_IN_PAGE) { efx_unmap_rx_buffer(rx_queue->efx, rx_buf); efx_free_rx_buffer(rx_buf); } rx_buf->page = NULL; }
static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, struct efx_rx_buffer *rx_buf) { efx_unmap_rx_buffer(rx_queue->efx, rx_buf); efx_free_rx_buffer(rx_queue->efx, rx_buf); }
/* Handle a received packet. Second half: Touches packet payload. */ void __efx_rx_packet(struct efx_channel *channel, struct efx_rx_buffer *rx_buf, bool checksummed) { struct efx_nic *efx = channel->efx; struct sk_buff *skb; bool lro = !!(efx->net_dev->features & NETIF_F_LRO); /* If we're in loopback test, then pass the packet directly to the * loopback layer, and free the rx_buf here */ if (unlikely(efx->loopback_selftest)) { efx_loopback_rx_packet(efx, rx_buf->data, rx_buf->len); efx_free_rx_buffer(efx, rx_buf); goto done; } if (rx_buf->skb) { prefetch(skb_shinfo(rx_buf->skb)); skb_put(rx_buf->skb, rx_buf->len); /* Move past the ethernet header. rx_buf->data still points * at the ethernet header */ rx_buf->skb->protocol = eth_type_trans(rx_buf->skb, efx->net_dev); } /* Both our generic-LRO and SFC-SSR support skb and page based * allocation, but neither support switching from one to the * other on the fly. If we spot that the allocation mode has * changed, then flush the LRO state. */ if (unlikely(channel->rx_alloc_pop_pages != (rx_buf->page != NULL))) { efx_flush_lro(channel); channel->rx_alloc_pop_pages = (rx_buf->page != NULL); } if (likely(checksummed && lro)) { efx_rx_packet_lro(channel, rx_buf); goto done; } /* Form an skb if required */ if (rx_buf->page) { int hdr_len = min(rx_buf->len, EFX_SKB_HEADERS); skb = efx_rx_mk_skb(rx_buf, efx, hdr_len); if (unlikely(skb == NULL)) { efx_free_rx_buffer(efx, rx_buf); goto done; } } else { /* We now own the SKB */ skb = rx_buf->skb; rx_buf->skb = NULL; } EFX_BUG_ON_PARANOID(rx_buf->page); EFX_BUG_ON_PARANOID(rx_buf->skb); EFX_BUG_ON_PARANOID(!skb); /* Set the SKB flags */ if (unlikely(!checksummed || !efx->rx_checksum_enabled)) skb->ip_summed = CHECKSUM_NONE; /* Pass the packet up */ netif_receive_skb(skb); /* Update allocation strategy method */ channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; done: ; }