drivers/scsi/qedf/qedf_fip.c

Source file repositories/reference/linux-study-clean/drivers/scsi/qedf/qedf_fip.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/qedf/qedf_fip.c
Extension
.c
Size
8576 bytes
Lines
302
Domain
Driver Families
Bucket
drivers/scsi
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

switch (desc->fip_dtype) {
		case FIP_DT_VLAN:
			vid = ntohs(((struct fip_vlan_desc *)desc)->fd_vlan);
			break;
		}
		desc = (struct fip_desc *)((char *)desc + dlen);
		rlen -= dlen;
	}

	if (atomic_read(&qedf->link_state) == QEDF_LINK_DOWN) {
		QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
			  "Dropping VLAN response as link is down.\n");
		return;
	}

	QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "VLAN response, "
		   "vid=0x%x.\n", vid);

	if (vid > 0 && qedf->vlan_id != vid) {
		qedf_set_vlan_id(qedf, vid);

		/* Inform waiter that it's ok to call fcoe_ctlr_link up() */
		if (!completion_done(&qedf->fipvlan_compl))
			complete(&qedf->fipvlan_compl);
	}
}

void qedf_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
	struct qedf_ctx *qedf = container_of(fip, struct qedf_ctx, ctlr);
	struct ethhdr *eth_hdr;
	struct fip_header *fiph;
	u16 op, vlan_tci = 0;
	u8 sub;
	int rc = -1;

	if (!test_bit(QEDF_LL2_STARTED, &qedf->flags)) {
		QEDF_WARN(&(qedf->dbg_ctx), "LL2 not started\n");
		kfree_skb(skb);
		return;
	}

	fiph = (struct fip_header *) ((void *)skb->data + 2 * ETH_ALEN + 2);
	eth_hdr = (struct ethhdr *)skb_mac_header(skb);
	op = ntohs(fiph->fip_op);
	sub = fiph->fip_subcode;

	/*
	 * Add VLAN tag to non-offload FIP frame based on current stored VLAN
	 * for FIP/FCoE traffic.
	 */
	__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), qedf->vlan_id);

	/* Get VLAN ID from skb for printing purposes */
	__vlan_hwaccel_get_tag(skb, &vlan_tci);

	QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, "FIP frame send: "
	    "dest=%pM op=%x sub=%x vlan=%04x.", eth_hdr->h_dest, op, sub,
	    vlan_tci);
	if (qedf_dump_frames)
		print_hex_dump(KERN_WARNING, "fip ", DUMP_PREFIX_OFFSET, 16, 1,
		    skb->data, skb->len, false);

	rc = qed_ops->ll2->start_xmit(qedf->cdev, skb, 0);
	if (rc) {
		QEDF_ERR(&qedf->dbg_ctx, "start_xmit failed rc = %d.\n", rc);
		kfree_skb(skb);
		return;
	}
}

static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS;

/* Process incoming FIP frames. */
void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb)
{
	struct ethhdr *eth_hdr;
	struct fip_header *fiph;
	struct fip_desc *desc;
	struct fip_mac_desc *mp;
	struct fip_wwn_desc *wp;
	struct fip_vn_desc *vp;
	size_t rlen, dlen;
	u16 op;
	u8 sub;
	bool fcf_valid = false;
	/* Default is to handle CVL regardless of fabric id descriptor */
	bool fabric_id_valid = true;
	bool fc_wwpn_valid = false;
	u64 switch_name;

Annotation

Implementation Notes