drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
Extension
.c
Size
28277 bytes
Lines
1048
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

while (len) {
			/* max number of buffers allowed in one DDP context */
			if (j >= IXGBE_BUFFCNT_MAX) {
				ddp_pool->noddp++;
				goto out_noddp_free;
			}

			/* get the offset of length of current buffer */
			thisoff = addr & ((dma_addr_t)bufflen - 1);
			thislen = min((bufflen - thisoff), len);
			/*
			 * all but the 1st buffer (j == 0)
			 * must be aligned on bufflen
			 */
			if ((j != 0) && (thisoff))
				goto out_noddp_free;
			/*
			 * all but the last buffer
			 * ((i == (dmacount - 1)) && (thislen == len))
			 * must end at bufflen
			 */
			if (((i != (dmacount - 1)) || (thislen != len))
			    && ((thislen + thisoff) != bufflen))
				goto out_noddp_free;

			ddp->udl[j] = (u64)(addr - thisoff);
			/* only the first buffer may have none-zero offset */
			if (j == 0)
				firstoff = thisoff;
			len -= thislen;
			addr += thislen;
			j++;
		}
	}
	/* only the last buffer may have non-full bufflen */
	lastsize = thisoff + thislen;

	/*
	 * lastsize can not be buffer len.
	 * If it is then adding another buffer with lastsize = 1.
	 */
	if (lastsize == bufflen) {
		if (j >= IXGBE_BUFFCNT_MAX) {
			ddp_pool->noddp_ext_buff++;
			goto out_noddp_free;
		}

		ddp->udl[j] = (u64)(fcoe->extra_ddp_buffer_dma);
		j++;
		lastsize = 1;
	}
	put_cpu();

	fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT);
	fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT);
	fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT);
	/* Set WRCONTX bit to allow DDP for target */
	if (target_mode)
		fcbuff |= (IXGBE_FCBUFF_WRCONTX);
	fcbuff |= (IXGBE_FCBUFF_VALID);

	fcdmarw = xid;
	fcdmarw |= IXGBE_FCDMARW_WE;
	fcdmarw |= (lastsize << IXGBE_FCDMARW_LASTSIZE_SHIFT);

	fcfltrw = xid;
	fcfltrw |= IXGBE_FCFLTRW_WE;

	/* program DMA context */
	hw = &adapter->hw;

	/* turn on last frame indication for target mode as FCP_RSPtarget is
	 * supposed to send FCP_RSP when it is done. */
	if (target_mode && !test_bit(__IXGBE_FCOE_TARGET, &fcoe->mode)) {
		set_bit(__IXGBE_FCOE_TARGET, &fcoe->mode);
		fcrxctl = IXGBE_READ_REG(hw, IXGBE_FCRXCTRL);
		fcrxctl |= IXGBE_FCRXCTRL_LASTSEQH;
		IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL, fcrxctl);
	}

	if (hw->mac.type == ixgbe_mac_X550) {
		/* X550 does not require DDP lock */

		IXGBE_WRITE_REG(hw, IXGBE_FCDDC(0, xid),
				ddp->udp & DMA_BIT_MASK(32));
		IXGBE_WRITE_REG(hw, IXGBE_FCDDC(1, xid), (u64)ddp->udp >> 32);
		IXGBE_WRITE_REG(hw, IXGBE_FCDDC(2, xid), fcbuff);
		IXGBE_WRITE_REG(hw, IXGBE_FCDDC(3, xid), fcdmarw);
		/* program filter context */
		IXGBE_WRITE_REG(hw, IXGBE_FCDFC(0, xid), IXGBE_FCFLT_VALID);

Annotation

Implementation Notes