drivers/net/ethernet/huawei/hinic3/hinic3_filter.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/huawei/hinic3/hinic3_filter.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/huawei/hinic3/hinic3_filter.c
Extension
.c
Size
11037 bytes
Lines
418
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

list_for_each_entry_safe(f, ftmp, del_list, list) {
			/* ignore errors when deleting mac */
			hinic3_filter_addr_unsync(netdev, f->addr);
			list_del(&f->list);
			kfree(f);
		}
	}

	if (!list_empty(add_list)) {
		list_for_each_entry_safe(f, ftmp, add_list, list) {
			if (f->state != HINIC3_MAC_HW_SYNCING)
				continue;

			err = hinic3_filter_addr_sync(netdev, f->addr);
			if (err) {
				netdev_err(netdev, "Failed to add mac\n");
				return err;
			}

			f->state = HINIC3_MAC_HW_SYNCED;
			(*add_count)++;
		}
	}

	return 0;
}

static int hinic3_mac_filter_sync(struct net_device *netdev,
				  struct list_head *mac_filter_list, bool uc)
{
	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
	struct list_head tmp_del_list, tmp_add_list;
	struct hinic3_mac_filter *fclone;
	struct hinic3_mac_filter *ftmp;
	struct hinic3_mac_filter *f;
	int err = 0, add_count = 0;

	INIT_LIST_HEAD(&tmp_del_list);
	INIT_LIST_HEAD(&tmp_add_list);

	list_for_each_entry_safe(f, ftmp, mac_filter_list, list) {
		if (f->state != HINIC3_MAC_WAIT_HW_UNSYNC)
			continue;

		f->state = HINIC3_MAC_HW_UNSYNCED;
		list_move_tail(&f->list, &tmp_del_list);
	}

	list_for_each_entry_safe(f, ftmp, mac_filter_list, list) {
		if (f->state != HINIC3_MAC_WAIT_HW_SYNC)
			continue;

		fclone = hinic3_mac_filter_entry_clone(f);
		if (!fclone) {
			hinic3_undo_del_filter_entries(mac_filter_list,
						       &tmp_del_list);
			hinic3_undo_add_filter_entries(mac_filter_list,
						       &tmp_add_list);

			netdev_err(netdev,
				   "Failed to clone mac_filter_entry\n");
			err = -ENOMEM;
			goto cleanup_tmp_filter_list;
		}

		f->state = HINIC3_MAC_HW_SYNCING;
		list_add_tail(&fclone->list, &tmp_add_list);
	}

	err = hinic3_mac_filter_sync_hw(netdev, &tmp_del_list,
					&tmp_add_list, &add_count);
	if (err) {
		/* there were errors, delete all mac in hw */
		hinic3_undo_add_filter_entries(mac_filter_list, &tmp_add_list);
		add_count = 0;
		/* VF does not support promiscuous mode,
		 * don't delete any other uc mac.
		 */
		if (!HINIC3_IS_VF(nic_dev->hwdev) || !uc) {
			list_for_each_entry_safe(f, ftmp, mac_filter_list,
						 list) {
				if (f->state != HINIC3_MAC_HW_SYNCED)
					continue;

				fclone = hinic3_mac_filter_entry_clone(f);
				if (!fclone)
					break;

				f->state = HINIC3_MAC_WAIT_HW_SYNC;
				list_add_tail(&fclone->list, &tmp_del_list);

Annotation

Implementation Notes