drivers/net/ethernet/sfc/ef100_rx.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sfc/ef100_rx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sfc/ef100_rx.c
Extension
.c
Size
6453 bytes
Lines
223
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (efv) {
			if (efv->net_dev->flags & IFF_UP)
				efx_ef100_rep_rx_packet(efv, rx_buf);
			rcu_read_unlock();
			/* Representor Rx doesn't care about PF Rx buffer
			 * ownership, it just makes a copy. So, we are done
			 * with the Rx buffer from PF point of view and should
			 * free it.
			 */
			goto free_rx_buffer;
		}
		rcu_read_unlock();
#endif
		if (net_ratelimit())
			netif_warn(efx, drv, efx->net_dev,
				   "Unrecognised ing_port %04x (base %04x), dropping\n",
				   ing_port, nic_data->base_mport);
		channel->n_rx_mport_bad++;
		goto free_rx_buffer;
	}

	if (likely(efx->net_dev->features & NETIF_F_RXCSUM)) {
		if (PREFIX_FIELD(prefix, NT_OR_INNER_L3_CLASS) == 1) {
			++channel->n_rx_ip_hdr_chksum_err;
		} else {
			u16 sum = be16_to_cpu((__force __be16)PREFIX_FIELD(prefix, CSUM_FRAME));

			csum = (__force __wsum) sum;
		}
	}

	if (channel->type->receive_skb) {
		/* no support for special channels yet, so just discard */
		WARN_ON_ONCE(1);
		goto free_rx_buffer;
	}

	++rx_queue->rx_packets;
	rx_queue->rx_bytes += rx_buf->len;

	efx_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh, csum);
	goto out;

free_rx_buffer:
	efx_free_rx_buffers(rx_queue, rx_buf, 1);
out:
	channel->rx_pkt_n_frags = 0;
}

static void ef100_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index)
{
	struct efx_rx_buffer *rx_buf = efx_rx_buffer(rx_queue, index);
	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
	struct efx_nic *efx = rx_queue->efx;

	netif_vdbg(efx, rx_status, efx->net_dev,
		   "RX queue %d received id %x\n",
		   efx_rx_queue_index(rx_queue), index);

	efx_sync_rx_buffer(efx, rx_buf, efx->rx_dma_len);

	prefetch(efx_rx_buf_va(rx_buf));

	rx_buf->page_offset += efx->rx_prefix_size;

	efx_recycle_rx_pages(channel, rx_buf, 1);

	efx_rx_flush_packet(channel);
	channel->rx_pkt_n_frags = 1;
	channel->rx_pkt_index = index;
}

void efx_ef100_ev_rx(struct efx_channel *channel, const efx_qword_t *p_event)
{
	struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel);
	unsigned int n_packets =
		EFX_QWORD_FIELD(*p_event, ESF_GZ_EV_RXPKTS_NUM_PKT);
	int i;

	WARN_ON_ONCE(!n_packets);
	if (n_packets > 1)
		++channel->n_rx_merge_events;

	channel->irq_mod_score += 2 * n_packets;

	for (i = 0; i < n_packets; ++i) {
		ef100_rx_packet(rx_queue,
				rx_queue->removed_count & rx_queue->ptr_mask);
		++rx_queue->removed_count;
	}

Annotation

Implementation Notes