drivers/scsi/fcoe/fcoe.c

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

File Facts

System
Linux kernel
Corpus path
drivers/scsi/fcoe/fcoe.c
Extension
.c
Size
75031 bytes
Lines
2807
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

const struct net_device_ops *ops;

	fcoe->netdev = netdev;

	/* Let LLD initialize for FCoE */
	ops = netdev->netdev_ops;
	if (ops->ndo_fcoe_enable) {
		if (ops->ndo_fcoe_enable(netdev))
			FCOE_NETDEV_DBG(netdev, "Failed to enable FCoE"
					" specific feature for LLD.\n");
	}

	/* Do not support for bonding device */
	if (netif_is_bond_master(netdev)) {
		FCOE_NETDEV_DBG(netdev, "Bonded interfaces not supported\n");
		return -EOPNOTSUPP;
	}

	/* look for SAN MAC address, if multiple SAN MACs exist, only
	 * use the first one for SPMA */
	real_dev = is_vlan_dev(netdev) ? vlan_dev_real_dev(netdev) : netdev;
	fcoe->realdev = real_dev;
	rcu_read_lock();
	for_each_dev_addr(real_dev, ha) {
		if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
		    (is_valid_ether_addr(ha->addr))) {
			memcpy(fip->ctl_src_addr, ha->addr, ETH_ALEN);
			fip->spma = 1;
			break;
		}
	}
	rcu_read_unlock();

	/* setup Source Mac Address */
	if (!fip->spma)
		memcpy(fip->ctl_src_addr, netdev->dev_addr, netdev->addr_len);

	/*
	 * Add FCoE MAC address as second unicast MAC address
	 * or enter promiscuous mode if not capable of listening
	 * for multiple unicast MACs.
	 */
	dev_uc_add(netdev, flogi_maddr);
	if (fip->spma)
		dev_uc_add(netdev, fip->ctl_src_addr);
	if (fip->mode == FIP_MODE_VN2VN) {
		dev_mc_add(netdev, FIP_ALL_VN2VN_MACS);
		dev_mc_add(netdev, FIP_ALL_P2P_MACS);
	} else
		dev_mc_add(netdev, FIP_ALL_ENODE_MACS);

	/*
	 * setup the receive function from ethernet driver
	 * on the ethertype for the given device
	 */
	fcoe->fcoe_packet_type.func = fcoe_rcv;
	fcoe->fcoe_packet_type.type = htons(ETH_P_FCOE);
	fcoe->fcoe_packet_type.dev = netdev;
	dev_add_pack(&fcoe->fcoe_packet_type);

	fcoe->fip_packet_type.func = fcoe_fip_recv;
	fcoe->fip_packet_type.type = htons(ETH_P_FIP);
	fcoe->fip_packet_type.dev = netdev;
	dev_add_pack(&fcoe->fip_packet_type);

	if (netdev != real_dev) {
		fcoe->fip_vlan_packet_type.func = fcoe_fip_vlan_recv;
		fcoe->fip_vlan_packet_type.type = htons(ETH_P_FIP);
		fcoe->fip_vlan_packet_type.dev = real_dev;
		dev_add_pack(&fcoe->fip_vlan_packet_type);
	}
	return 0;
}

/**
 * fcoe_interface_create() - Create a FCoE interface on a net device
 * @netdev: The net device to create the FCoE interface on
 * @fip_mode: The mode to use for FIP
 *
 * Returns: pointer to a struct fcoe_interface or NULL on error
 */
static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev,
						    enum fip_mode fip_mode)
{
	struct fcoe_ctlr_device *ctlr_dev;
	struct fcoe_ctlr *ctlr;
	struct fcoe_interface *fcoe;
	int size;
	int err;

Annotation

Implementation Notes