drivers/net/dsa/mxl862xx/mxl862xx-host.c

Source file repositories/reference/linux-study-clean/drivers/net/dsa/mxl862xx/mxl862xx-host.c

File Facts

System
Linux kernel
Corpus path
drivers/net/dsa/mxl862xx/mxl862xx-host.c
Extension
.c
Size
14133 bytes
Lines
505
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 (i && off == 0) {
			/* Send command to set data when every
			 * MXL862XX_MMD_REG_DATA_MAX_SIZE of WORDs are written.
			  */
			ret = mxl862xx_set_data(priv, i);
			if (ret < 0)
				goto out;
		}

		if (i == max) {
			/* Even size: full CRC word.
			 * Odd size: only CRC high byte remains (low byte
			 * was packed into the previous word).
			 */
			val = (size & 1) ? crc >> 8 : crc;
		} else if ((i * 2 + 1) == size) {
			/* Special handling for last BYTE if it's not WORD
			 * aligned to avoid reading beyond the allocated data
			 * structure.  Pack the CRC low byte into the high
			 * byte of this word so it sits at byte offset 'size'
			 * in the firmware's contiguous buffer.
			 */
			val = *(u8 *)&data[i] | ((crc & 0xff) << 8);
		} else {
			val = le16_to_cpu(data[i]);
		}

		/* After RST_DATA, skip zero data words as the registers
		 * already contain zeros, but never skip the CRC word at the
		 * final word.
		 */
		if (use_rst && i < max && val == 0)
			continue;

		ret = mxl862xx_reg_write(priv,
					 MXL862XX_MMD_REG_DATA_FIRST + off,
					 val);
		if (ret < 0)
			goto out;
	}

	ret = mxl862xx_send_cmd(priv, cmd, size, quiet);
	if (ret < 0 || !read)
		goto out;

	/* store result of mxl862xx_send_cmd() */
	cmd_ret = ret;

	for (i = 0; i < max + 1; i++) {
		u16 off = i % MXL862XX_MMD_REG_DATA_MAX_SIZE;

		if (i && off == 0) {
			/* Send command to fetch next batch of data when every
			 * MXL862XX_MMD_REG_DATA_MAX_SIZE of WORDs are read.
			  */
			ret = mxl862xx_get_data(priv, i);
			if (ret < 0)
				goto out;
		}

		ret = mxl862xx_reg_read(priv, MXL862XX_MMD_REG_DATA_FIRST + off);
		if (ret < 0)
			goto out;

		if (i == max) {
			/* Even size: full CRC word.
			 * Odd size: only CRC high byte remains (low byte
			 * was in the previous word).
			 */
			if (size & 1)
				crc = (crc & 0x00ff) |
				      (((u16)ret & 0xff) << 8);
			else
				crc = (u16)ret;
		} else if ((i * 2 + 1) == size) {
			/* Special handling for last BYTE if it's not WORD
			 * aligned to avoid writing beyond the allocated data
			 * structure.  The high byte carries the CRC low byte.
			 */
			*(uint8_t *)&data[i] = ret & 0xff;
			crc = (ret >> 8) & 0xff;
		} else {
			data[i] = cpu_to_le16((u16)ret);
		}
	}

	if (crc16(0xffff, (const u8 *)data, size) != crc) {
		if (!test_and_set_bit(MXL862XX_FLAG_CRC_ERR, &priv->flags))
			schedule_work(&priv->crc_err_work);
		ret = -EIO;

Annotation

Implementation Notes