drivers/net/xen-netback/hash.c

Source file repositories/reference/linux-study-clean/drivers/net/xen-netback/hash.c

File Facts

System
Linux kernel
Corpus path
drivers/net/xen-netback/hash.c
Extension
.c
Size
11896 bytes
Lines
468
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

lockdep_is_held(&vif->hash.cache.lock)) {
		/* Make sure we don't add duplicate entries */
		if (entry->len == len &&
		    memcmp(entry->tag, tag, len) == 0)
			found = true;
		if (!oldest || entry->seq < oldest->seq)
			oldest = entry;
	}

	if (!found) {
		new->seq = atomic_inc_return(&vif->hash.cache.seq);
		list_add_rcu(&new->link, &vif->hash.cache.list);

		if (++vif->hash.cache.count > xenvif_hash_cache_size) {
			list_del_rcu(&oldest->link);
			vif->hash.cache.count--;
			kfree_rcu(oldest, rcu);
		}
	}

	spin_unlock_irqrestore(&vif->hash.cache.lock, flags);

	if (found)
		kfree(new);
}

static u32 xenvif_new_hash(struct xenvif *vif, const u8 *data,
			   unsigned int len)
{
	u32 val;

	val = xen_netif_toeplitz_hash(vif->hash.key,
				      sizeof(vif->hash.key),
				      data, len);

	if (xenvif_hash_cache_size != 0)
		xenvif_add_hash(vif, data, len, val);

	return val;
}

static void xenvif_flush_hash(struct xenvif *vif)
{
	struct xenvif_hash_cache_entry *entry, *n;
	unsigned long flags;

	if (xenvif_hash_cache_size == 0)
		return;

	spin_lock_irqsave(&vif->hash.cache.lock, flags);

	list_for_each_entry_safe(entry, n, &vif->hash.cache.list, link) {
		list_del_rcu(&entry->link);
		vif->hash.cache.count--;
		kfree_rcu(entry, rcu);
	}

	spin_unlock_irqrestore(&vif->hash.cache.lock, flags);
}

static u32 xenvif_find_hash(struct xenvif *vif, const u8 *data,
			    unsigned int len)
{
	struct xenvif_hash_cache_entry *entry;
	u32 val;
	bool found;

	if (len >= XEN_NETBK_HASH_TAG_SIZE)
		return 0;

	if (xenvif_hash_cache_size == 0)
		return xenvif_new_hash(vif, data, len);

	rcu_read_lock();

	found = false;

	list_for_each_entry_rcu(entry, &vif->hash.cache.list, link) {
		if (entry->len == len &&
		    memcmp(entry->tag, data, len) == 0) {
			val = entry->val;
			entry->seq = atomic_inc_return(&vif->hash.cache.seq);
			found = true;
			break;
		}
	}

	rcu_read_unlock();

	if (!found)

Annotation

Implementation Notes