/* Preferred number of descriptors to fill at once */ #define EFX_RX_PREFERRED_BATCH 8U
/* Maximum rx prefix used by any architecture. */ #define EFX_MAX_RX_PREFIX_SIZE 16
/* Size of buffer allocated for skb header area. */ #define EFX_SKB_HEADERS 128u
/* Each packet can consume up to ceil(max_frame_len / buffer_size) buffers */ #define EFX_RX_MAX_FRAGS DIV_ROUND_UP(EFX_MAX_FRAME_LEN(EFX_MAX_MTU), \
EFX_RX_USR_BUF_SIZE)
/* Discard packet, if instructed to do so. Process the *previousreceivefirst.
*/ if (unlikely(rx_buf->flags & EFX_RX_PKT_DISCARD)) {
efx_rx_flush_packet(channel);
efx_discard_rx_packet(channel, rx_buf, n_frags); return;
}
if (n_frags > 1) { /* Release/sync DMA mapping for additional fragments. *Fixlengthforlastfragment.
*/ unsignedint tail_frags = n_frags - 1;
for (;;) {
rx_buf = efx_rx_buf_next(rx_queue, rx_buf); if (--tail_frags == 0) break;
efx_sync_rx_buffer(efx, rx_buf, efx->rx_dma_len);
}
rx_buf->len = len - (n_frags - 1) * efx->rx_dma_len;
efx_sync_rx_buffer(efx, rx_buf, rx_buf->len);
}
/* All fragments have been DMA-synced, so recycle pages. */
rx_buf = efx_rx_buffer(rx_queue, index);
efx_recycle_rx_pages(channel, rx_buf, n_frags);
/* Pipeline receives so that we give time for packet headers to be *prefetchedintocache.
*/
efx_rx_flush_packet(channel);
channel->rx_pkt_n_frags = n_frags;
channel->rx_pkt_index = index;
}
/* Set the SKB flags */
skb_checksum_none_assert(skb); if (likely(rx_buf->flags & EFX_RX_PKT_CSUMMED)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->csum_level = !!(rx_buf->flags & EFX_RX_PKT_CSUM_LEVEL);
}
efx_rx_skb_attach_timestamp(channel, skb);
if (channel->type->receive_skb) if (channel->type->receive_skb(channel, skb)) return;
/* Pass the packet up */ if (channel->rx_list != NULL) /* Add to list, will pass up later */
list_add_tail(&skb->list, channel->rx_list); else /* No list, so pass it up now */
netif_receive_skb(skb);
}
xdp_prog = rcu_dereference_bh(efx->xdp_prog); if (!xdp_prog) returntrue;
rx_queue = efx_channel_get_rx_queue(channel);
if (unlikely(channel->rx_pkt_n_frags > 1)) { /* We can't do XDP on fragmented packets - drop. */
efx_free_rx_buffers(rx_queue, rx_buf,
channel->rx_pkt_n_frags); if (net_ratelimit())
netif_err(efx, rx_err, efx->net_dev, "XDP is not possible with multiple receive fragments (%d)\n",
channel->rx_pkt_n_frags);
channel->n_rx_xdp_bad_drops++; returnfalse;
}
/* Read length from the prefix if necessary. This already *excludesthelengthoftheprefixitself.
*/ if (rx_buf->flags & EFX_RX_PKT_PREFIX_LEN) {
rx_buf->len = le16_to_cpup((__le16 *)
(eh + efx->rx_packet_len_offset)); /* A known issue may prevent this being filled in; *ifthathappens,justdropthepacket. *Mustdothatinthedriversincepassingazero-length *packetuptothestackmaycauseacrash.
*/ if (unlikely(!rx_buf->len)) {
efx_free_rx_buffers(rx_queue, rx_buf,
channel->rx_pkt_n_frags);
channel->n_rx_frm_trunc++; goto out;
}
}
/* If we're in loopback test, then pass the packet directly to the *loopbacklayer,andfreetherx_bufhere
*/ if (unlikely(efx->loopback_selftest)) {
efx_loopback_rx_packet(efx, eh, rx_buf->len);
efx_free_rx_buffers(rx_queue, rx_buf,
channel->rx_pkt_n_frags); goto out;
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.14Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-01)
¤