drivers/net/ethernet/meta/fbnic/fbnic_rpc.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/meta/fbnic/fbnic_rpc.c
Extension
.c
Size
36336 bytes
Lines
1246
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 (mac_addr->state != FBNIC_TCAM_S_VALID) {
			eth_zero_addr(mac_addr->value.addr8);
			eth_broadcast_addr(mac_addr->mask.addr8);
			mac_addr->value.addr8[0] ^= 1;
			mac_addr->mask.addr8[0] ^= 1;
			set_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam);
			mac_addr->state = FBNIC_TCAM_S_ADD;
		}
		if (enable_host)
			set_bit(FBNIC_MAC_ADDR_T_ALLMULTI,
				mac_addr->act_tcam);
		else
			clear_bit(FBNIC_MAC_ADDR_T_ALLMULTI,
				  mac_addr->act_tcam);
	} else {
		__fbnic_xc_unsync(mac_addr, FBNIC_MAC_ADDR_T_BMC);
		__fbnic_xc_unsync(mac_addr, FBNIC_MAC_ADDR_T_ALLMULTI);
	}

	/* We have to add a special handler for multicast as the
	 * BMC may have an all-multi rule already in place. As such
	 * adding a rule ourselves won't do any good so we will have
	 * to modify the rules for the ALL MULTI below if the BMC
	 * already has the rule in place.
	 */
	act_tcam = &fbd->act_tcam[FBNIC_RPC_ACT_TBL_BMC_ALL_MULTI_OFFSET];

	/* If we are not enabling the rule just delete it. We will fall
	 * back to the RSS rules that support the multicast addresses.
	 */
	if (!fbnic_bmc_present(fbd) || !fbd->fw_cap.all_multi || enable_host) {
		if (act_tcam->state == FBNIC_TCAM_S_VALID)
			act_tcam->state = FBNIC_TCAM_S_DELETE;
		return;
	}

	/* Rewrite TCAM rule 23 to handle BMC all-multi traffic */
	act_tcam->dest = FIELD_PREP(FBNIC_RPC_ACT_TBL0_DEST_MASK,
				    FBNIC_RPC_ACT_TBL0_DEST_BMC);
	act_tcam->mask.tcam[0] = 0xffff;

	/* MACDA 0 - 3 is reserved for the BMC MAC address */
	act_tcam->value.tcam[1] =
			FIELD_PREP(FBNIC_RPC_TCAM_ACT1_L2_MACDA_IDX,
				   fbd->mac_addr_boundary - 1) |
			FBNIC_RPC_TCAM_ACT1_L2_MACDA_VALID;
	act_tcam->mask.tcam[1] = 0xffff &
			 ~FBNIC_RPC_TCAM_ACT1_L2_MACDA_IDX &
			 ~FBNIC_RPC_TCAM_ACT1_L2_MACDA_VALID;

	for (j = 2; j < FBNIC_RPC_TCAM_ACT_WORD_LEN; j++)
		act_tcam->mask.tcam[j] = 0xffff;

	act_tcam->state = FBNIC_TCAM_S_UPDATE;
}

void fbnic_bmc_rpc_init(struct fbnic_dev *fbd)
{
	int i = FBNIC_RPC_TCAM_MACDA_BMC_ADDR_IDX;
	struct fbnic_act_tcam *act_tcam;
	struct fbnic_mac_addr *mac_addr;
	int j;

	/* Check if BMC is present */
	if (!fbnic_bmc_present(fbd))
		return;

	/* Fetch BMC MAC addresses from firmware capabilities */
	for (j = 0; j < 4; j++) {
		u8 *bmc_mac = fbd->fw_cap.bmc_mac_addr[j];

		/* Validate BMC MAC addresses */
		if (is_zero_ether_addr(bmc_mac))
			continue;

		if (is_multicast_ether_addr(bmc_mac))
			mac_addr = __fbnic_mc_sync(fbd, bmc_mac);
		else
			mac_addr = &fbd->mac_addr[i++];

		if (!mac_addr) {
			netdev_err(fbd->netdev,
				   "No slot for BMC MAC address[%d]\n", j);
			continue;
		}

		ether_addr_copy(mac_addr->value.addr8, bmc_mac);
		eth_zero_addr(mac_addr->mask.addr8);

		set_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam);

Annotation

Implementation Notes