drivers/staging/octeon/ethernet-rx.c

Source file repositories/reference/linux-study-clean/drivers/staging/octeon/ethernet-rx.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/octeon/ethernet-rx.c
Extension
.c
Size
13496 bytes
Lines
543
Domain
Driver Families
Bucket
drivers/staging
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 (gmxx_rxx_frm_ctl.s.pre_chk == 0) {
			u8 *ptr =
			    cvmx_phys_to_ptr(work->packet_ptr.s.addr);
			int i = 0;

			while (i < work->word1.len - 1) {
				if (*ptr != 0x55)
					break;
				ptr++;
				i++;
			}

			if (*ptr == 0xd5) {
				/* Port received 0xd5 preamble */
				work->packet_ptr.s.addr += i + 1;
				work->word1.len -= i + 5;
				return 0;
			}

			if ((*ptr & 0xf) == 0xd) {
				/* Port received 0xd preamble */
				work->packet_ptr.s.addr += i;
				work->word1.len -= i + 4;
				for (i = 0; i < work->word1.len; i++) {
					*ptr =
					    ((*ptr & 0xf0) >> 4) |
					    ((*(ptr + 1) & 0xf) << 4);
					ptr++;
				}
				return 0;
			}

			printk_ratelimited("Port %d unknown preamble, packet dropped\n",
					   port);
			cvm_oct_free_work(work);
			return 1;
		}
	}

	printk_ratelimited("Port %d receive error code %d, packet dropped\n",
			   port, work->word2.snoip.err_code);
	cvm_oct_free_work(work);
	return 1;
}

static void copy_segments_to_skb(struct cvmx_wqe *work, struct sk_buff *skb)
{
	int segments = work->word2.s.bufs;
	union cvmx_buf_ptr segment_ptr = work->packet_ptr;
	int len = work->word1.len;
	int segment_size;

	while (segments--) {
		union cvmx_buf_ptr next_ptr;

		next_ptr = *(union cvmx_buf_ptr *)
			cvmx_phys_to_ptr(segment_ptr.s.addr - 8);

		/*
		 * Octeon Errata PKI-100: The segment size is wrong.
		 *
		 * Until it is fixed, calculate the segment size based on
		 * the packet pool buffer size.
		 * When it is fixed, the following line should be replaced
		 * with this one:
		 * int segment_size = segment_ptr.s.size;
		 */
		segment_size =
			CVMX_FPA_PACKET_POOL_SIZE -
			(segment_ptr.s.addr -
			 (((segment_ptr.s.addr >> 7) -
			   segment_ptr.s.back) << 7));

		/* Don't copy more than what is left in the packet */
		if (segment_size > len)
			segment_size = len;

		/* Copy the data into the packet */
		skb_put_data(skb, cvmx_phys_to_ptr(segment_ptr.s.addr),
			     segment_size);
		len -= segment_size;
		segment_ptr = next_ptr;
	}
}

static int cvm_oct_poll(struct oct_rx_group *rx_group, int budget)
{
	const int	coreid = cvmx_get_core_num();
	u64	old_group_mask;
	u64	old_scratch;

Annotation

Implementation Notes