drivers/net/ethernet/intel/ice/ice_eswitch_br.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/intel/ice/ice_eswitch_br.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/intel/ice/ice_eswitch_br.c
Extension
.c
Size
32433 bytes
Lines
1356
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 (IS_ERR(vlan)) {
			dev_err(dev, "Failed to find vlan lookup, err: %ld\n",
				PTR_ERR(vlan));
			return;
		}
	}

	fdb_entry = ice_eswitch_br_fdb_find(bridge, mac, vid);
	if (fdb_entry)
		ice_eswitch_br_fdb_entry_notify_and_cleanup(bridge, fdb_entry);

	fdb_entry = kzalloc_obj(*fdb_entry);
	if (!fdb_entry) {
		err = -ENOMEM;
		goto err_exit;
	}

	flow = ice_eswitch_br_flow_create(dev, hw, br_port->vsi_idx,
					  br_port->type, mac, vid);
	if (IS_ERR(flow)) {
		err = PTR_ERR(flow);
		goto err_add_flow;
	}

	ether_addr_copy(fdb_entry->data.addr, mac);
	fdb_entry->data.vid = vid;
	fdb_entry->br_port = br_port;
	fdb_entry->flow = flow;
	fdb_entry->dev = netdev;
	fdb_entry->last_use = jiffies;
	event = SWITCHDEV_FDB_ADD_TO_BRIDGE;

	if (added_by_user) {
		fdb_entry->flags |= ICE_ESWITCH_BR_FDB_ADDED_BY_USER;
		event = SWITCHDEV_FDB_OFFLOADED;
	}

	err = rhashtable_insert_fast(&bridge->fdb_ht, &fdb_entry->ht_node,
				     ice_fdb_ht_params);
	if (err)
		goto err_fdb_insert;

	list_add(&fdb_entry->list, &bridge->fdb_list);
	trace_ice_eswitch_br_fdb_entry_create(fdb_entry);

	ice_eswitch_br_fdb_offload_notify(netdev, mac, vid, event);

	return;

err_fdb_insert:
	ice_eswitch_br_flow_delete(pf, flow);
err_add_flow:
	kfree(fdb_entry);
err_exit:
	dev_err(dev, "Failed to create fdb entry, err: %d\n", err);
}

static void
ice_eswitch_br_fdb_work_dealloc(struct ice_esw_br_fdb_work *fdb_work)
{
	kfree(fdb_work->fdb_info.addr);
	kfree(fdb_work);
}

static void
ice_eswitch_br_fdb_event_work(struct work_struct *work)
{
	struct ice_esw_br_fdb_work *fdb_work = ice_work_to_fdb_work(work);
	bool added_by_user = fdb_work->fdb_info.added_by_user;
	const unsigned char *mac = fdb_work->fdb_info.addr;
	u16 vid = fdb_work->fdb_info.vid;
	struct ice_esw_br_port *br_port;

	rtnl_lock();

	br_port = ice_eswitch_br_netdev_to_port(fdb_work->dev);
	if (!br_port)
		goto err_exit;

	switch (fdb_work->event) {
	case SWITCHDEV_FDB_ADD_TO_DEVICE:
		ice_eswitch_br_fdb_entry_create(fdb_work->dev, br_port,
						added_by_user, mac, vid);
		break;
	case SWITCHDEV_FDB_DEL_TO_DEVICE:
		ice_eswitch_br_fdb_entry_find_and_delete(br_port->bridge,
							 mac, vid);
		break;
	default:
		goto err_exit;

Annotation

Implementation Notes