138061Smsmith/*
238061Smsmith * Copyright (c) 2016 Citrix Systems Inc.
338061Smsmith *
438061Smsmith * This program is free software; you can redistribute it and/or
538061Smsmith * modify it under the terms of the GNU General Public License version 2
638061Smsmith * as published by the Free Softare Foundation; or, when distributed
738061Smsmith * separately from the Linux kernel or incorporated into other
838061Smsmith * software packages, subject to the following license:
938061Smsmith *
1038061Smsmith * Permission is hereby granted, free of charge, to any person obtaining a copy
1138061Smsmith * of this source file (the "Software"), to deal in the Software without
1238061Smsmith * restriction, including without limitation the rights to use, copy, modify,
1338061Smsmith * merge, publish, distribute, sublicense, and/or sell copies of the Software,
1438061Smsmith * and to permit persons to whom the Software is furnished to do so, subject to
1538061Smsmith * the following conditions:
1638061Smsmith *
1738061Smsmith * The above copyright notice and this permission notice shall be included in
1838061Smsmith * all copies or substantial portions of the Software.
1938061Smsmith *
2038061Smsmith * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2138061Smsmith * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2238061Smsmith * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2338061Smsmith * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2438061Smsmith * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2538061Smsmith * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2638061Smsmith * IN THE SOFTWARE.
2738061Smsmith */
2838061Smsmith
29119418Sobrien#define XEN_NETIF_DEFINE_TOEPLITZ
30119418Sobrien
31119418Sobrien#include "common.h"
3238061Smsmith#include <linux/vmalloc.h>
3338061Smsmith#include <linux/rculist.h>
3438061Smsmith
3538061Smsmithstatic void xenvif_add_hash(struct xenvif *vif, const u8 *tag,
3638061Smsmith			    unsigned int len, u32 val)
3738061Smsmith{
3838061Smsmith	struct xenvif_hash_cache_entry *new, *entry, *oldest;
3938061Smsmith	unsigned long flags;
40108470Sschweikh	bool found;
4138061Smsmith
4238061Smsmith	new = kmalloc(sizeof(*entry), GFP_ATOMIC);
4338061Smsmith	if (!new)
4438061Smsmith		return;
4538061Smsmith
4638061Smsmith	memcpy(new->tag, tag, len);
4738061Smsmith	new->len = len;
4838061Smsmith	new->val = val;
4938061Smsmith
5038061Smsmith	spin_lock_irqsave(&vif->hash.cache.lock, flags);
5138061Smsmith
5238061Smsmith	found = false;
5338061Smsmith	oldest = NULL;
5438061Smsmith	list_for_each_entry_rcu(entry, &vif->hash.cache.list, link,
5538061Smsmith				lockdep_is_held(&vif->hash.cache.lock)) {
5638061Smsmith		/* Make sure we don't add duplicate entries */
5738061Smsmith		if (entry->len == len &&
5838061Smsmith		    memcmp(entry->tag, tag, len) == 0)
5938061Smsmith			found = true;
6038061Smsmith		if (!oldest || entry->seq < oldest->seq)
6138061Smsmith			oldest = entry;
6238061Smsmith	}
6338061Smsmith
6438061Smsmith	if (!found) {
6538061Smsmith		new->seq = atomic_inc_return(&vif->hash.cache.seq);
6638061Smsmith		list_add_rcu(&new->link, &vif->hash.cache.list);
6738061Smsmith
6838061Smsmith		if (++vif->hash.cache.count > xenvif_hash_cache_size) {
6938061Smsmith			list_del_rcu(&oldest->link);
7038061Smsmith			vif->hash.cache.count--;
7138061Smsmith			kfree_rcu(oldest, rcu);
7238061Smsmith		}
7338061Smsmith	}
7438061Smsmith
7538061Smsmith	spin_unlock_irqrestore(&vif->hash.cache.lock, flags);
7638061Smsmith
7738061Smsmith	if (found)
7838061Smsmith		kfree(new);
7938061Smsmith}
8038061Smsmith
8138061Smsmithstatic u32 xenvif_new_hash(struct xenvif *vif, const u8 *data,
8238061Smsmith			   unsigned int len)
8355939Snsouch{
8455939Snsouch	u32 val;
8538061Smsmith
8638061Smsmith	val = xen_netif_toeplitz_hash(vif->hash.key,
8755939Snsouch				      sizeof(vif->hash.key),
8855939Snsouch				      data, len);
8938061Smsmith
9038061Smsmith	if (xenvif_hash_cache_size != 0)
9138061Smsmith		xenvif_add_hash(vif, data, len, val);
9238061Smsmith
9338061Smsmith	return val;
9438061Smsmith}
9555939Snsouch
9655939Snsouchstatic void xenvif_flush_hash(struct xenvif *vif)
9755939Snsouch{
9855939Snsouch	struct xenvif_hash_cache_entry *entry;
9938061Smsmith	unsigned long flags;
10038061Smsmith
10138061Smsmith	if (xenvif_hash_cache_size == 0)
10238061Smsmith		return;
10338061Smsmith
10438061Smsmith	spin_lock_irqsave(&vif->hash.cache.lock, flags);
10538061Smsmith
10638061Smsmith	list_for_each_entry_rcu(entry, &vif->hash.cache.list, link,
10738061Smsmith				lockdep_is_held(&vif->hash.cache.lock)) {
10838061Smsmith		list_del_rcu(&entry->link);
10955939Snsouch		vif->hash.cache.count--;
11055939Snsouch		kfree_rcu(entry, rcu);
11138061Smsmith	}
11238061Smsmith
11338061Smsmith	spin_unlock_irqrestore(&vif->hash.cache.lock, flags);
11438061Smsmith}
11538061Smsmith
11638061Smsmithstatic u32 xenvif_find_hash(struct xenvif *vif, const u8 *data,
11738061Smsmith			    unsigned int len)
11838061Smsmith{
11938061Smsmith	struct xenvif_hash_cache_entry *entry;
12038061Smsmith	u32 val;
12138061Smsmith	bool found;
12238061Smsmith
12338061Smsmith	if (len >= XEN_NETBK_HASH_TAG_SIZE)
12438061Smsmith		return 0;
12538061Smsmith
12638061Smsmith	if (xenvif_hash_cache_size == 0)
12738061Smsmith		return xenvif_new_hash(vif, data, len);
12838061Smsmith
12938061Smsmith	rcu_read_lock();
13038061Smsmith
13138061Smsmith	found = false;
13238061Smsmith
13338061Smsmith	list_for_each_entry_rcu(entry, &vif->hash.cache.list, link) {
13438061Smsmith		if (entry->len == len &&
13538061Smsmith		    memcmp(entry->tag, data, len) == 0) {
13638061Smsmith			val = entry->val;
13738061Smsmith			entry->seq = atomic_inc_return(&vif->hash.cache.seq);
13838061Smsmith			found = true;
13938061Smsmith			break;
14038061Smsmith		}
14143433Snsouch	}
14243433Snsouch
14338061Smsmith	rcu_read_unlock();
14443433Snsouch
14543433Snsouch	if (!found)
14638061Smsmith		val = xenvif_new_hash(vif, data, len);
14738061Smsmith
14855939Snsouch	return val;
14938061Smsmith}
15038061Smsmith
15138061Smsmithvoid xenvif_set_skb_hash(struct xenvif *vif, struct sk_buff *skb)
15255939Snsouch{
15355939Snsouch	struct flow_keys flow;
15438061Smsmith	u32 hash = 0;
15538061Smsmith	enum pkt_hash_types type = PKT_HASH_TYPE_NONE;
15638061Smsmith	u32 flags = vif->hash.flags;
15738061Smsmith	bool has_tcp_hdr;
15838061Smsmith
15938061Smsmith	/* Quick rejection test: If the network protocol doesn't
16038061Smsmith	 * correspond to any enabled hash type then there's no point
16138061Smsmith	 * in parsing the packet header.
16238061Smsmith	 */
16338061Smsmith	switch (skb->protocol) {
16438061Smsmith	case htons(ETH_P_IP):
16538061Smsmith		if (flags & (XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP |
16638061Smsmith			     XEN_NETIF_CTRL_HASH_TYPE_IPV4))
16738061Smsmith			break;
16838061Smsmith
16938061Smsmith		goto done;
17038061Smsmith
17138061Smsmith	case htons(ETH_P_IPV6):
17255939Snsouch		if (flags & (XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP |
17338061Smsmith			     XEN_NETIF_CTRL_HASH_TYPE_IPV6))
17455939Snsouch			break;
17555939Snsouch
17655939Snsouch		goto done;
17755939Snsouch
17855939Snsouch	default:
17955939Snsouch		goto done;
18038061Smsmith	}
18155939Snsouch
18255939Snsouch	memset(&flow, 0, sizeof(flow));
18356455Speter	if (!skb_flow_dissect_flow_keys(skb, &flow, 0))
18456455Speter		goto done;
18556455Speter
18655939Snsouch	has_tcp_hdr = (flow.basic.ip_proto == IPPROTO_TCP) &&
18794154Sticso		      !(flow.control.flags & FLOW_DIS_IS_FRAGMENT);
18856455Speter
18938061Smsmith	switch (skb->protocol) {
19038061Smsmith	case htons(ETH_P_IP):
19138061Smsmith		if (has_tcp_hdr &&
19255939Snsouch		    (flags & XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP)) {
19355939Snsouch			u8 data[12];
19438061Smsmith
19555939Snsouch			memcpy(&data[0], &flow.addrs.v4addrs.src, 4);
19655939Snsouch			memcpy(&data[4], &flow.addrs.v4addrs.dst, 4);
19756618Sdfr			memcpy(&data[8], &flow.ports.src, 2);
19857177Speter			memcpy(&data[10], &flow.ports.dst, 2);
19938061Smsmith
20055939Snsouch			hash = xenvif_find_hash(vif, data, sizeof(data));
20155939Snsouch			type = PKT_HASH_TYPE_L4;
20255939Snsouch		} else if (flags & XEN_NETIF_CTRL_HASH_TYPE_IPV4) {
20355939Snsouch			u8 data[8];
20455939Snsouch
20555939Snsouch			memcpy(&data[0], &flow.addrs.v4addrs.src, 4);
20638061Smsmith			memcpy(&data[4], &flow.addrs.v4addrs.dst, 4);
20755939Snsouch
20855939Snsouch			hash = xenvif_find_hash(vif, data, sizeof(data));
20955939Snsouch			type = PKT_HASH_TYPE_L3;
21043989Snsouch		}
21138061Smsmith
21255939Snsouch		break;
21355939Snsouch
21455939Snsouch	case htons(ETH_P_IPV6):
21555939Snsouch		if (has_tcp_hdr &&
21655939Snsouch		    (flags & XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP)) {
21755939Snsouch			u8 data[36];
21838061Smsmith
21938061Smsmith			memcpy(&data[0], &flow.addrs.v6addrs.src, 16);
22038061Smsmith			memcpy(&data[16], &flow.addrs.v6addrs.dst, 16);
22138061Smsmith			memcpy(&data[32], &flow.ports.src, 2);
22238061Smsmith			memcpy(&data[34], &flow.ports.dst, 2);
22338061Smsmith
22455939Snsouch			hash = xenvif_find_hash(vif, data, sizeof(data));
22538061Smsmith			type = PKT_HASH_TYPE_L4;
22655939Snsouch		} else if (flags & XEN_NETIF_CTRL_HASH_TYPE_IPV6) {
22738061Smsmith			u8 data[32];
22838061Smsmith
22938061Smsmith			memcpy(&data[0], &flow.addrs.v6addrs.src, 16);
23055939Snsouch			memcpy(&data[16], &flow.addrs.v6addrs.dst, 16);
23138061Smsmith
23255939Snsouch			hash = xenvif_find_hash(vif, data, sizeof(data));
23355939Snsouch			type = PKT_HASH_TYPE_L3;
23438061Smsmith		}
23555939Snsouch
236121816Sbrooks		break;
23738061Smsmith	}
23838061Smsmith
23938061Smsmithdone:
24038061Smsmith	if (type == PKT_HASH_TYPE_NONE)
24138061Smsmith		skb_clear_hash(skb);
24238061Smsmith	else
24338061Smsmith		__skb_set_sw_hash(skb, hash, type == PKT_HASH_TYPE_L4);
24438061Smsmith}
24538061Smsmith
24638061Smsmithu32 xenvif_set_hash_alg(struct xenvif *vif, u32 alg)
24743773Sdes{
24838061Smsmith	switch (alg) {
24955939Snsouch	case XEN_NETIF_CTRL_HASH_ALGORITHM_NONE:
25038061Smsmith	case XEN_NETIF_CTRL_HASH_ALGORITHM_TOEPLITZ:
25138061Smsmith		break;
25238061Smsmith
25338061Smsmith	default:
25438061Smsmith		return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
25538061Smsmith	}
25638061Smsmith
25738061Smsmith	vif->hash.alg = alg;
25838061Smsmith
25938061Smsmith	return XEN_NETIF_CTRL_STATUS_SUCCESS;
26038061Smsmith}
26138061Smsmith
26238061Smsmithu32 xenvif_get_hash_flags(struct xenvif *vif, u32 *flags)
26338061Smsmith{
26438061Smsmith	if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE)
26538061Smsmith		return XEN_NETIF_CTRL_STATUS_NOT_SUPPORTED;
26638061Smsmith
26738061Smsmith	*flags = XEN_NETIF_CTRL_HASH_TYPE_IPV4 |
26838061Smsmith		 XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP |
26938061Smsmith		 XEN_NETIF_CTRL_HASH_TYPE_IPV6 |
27038061Smsmith		 XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP;
27138061Smsmith
27238061Smsmith	return XEN_NETIF_CTRL_STATUS_SUCCESS;
27338061Smsmith}
27438061Smsmith
27538061Smsmithu32 xenvif_set_hash_flags(struct xenvif *vif, u32 flags)
27638061Smsmith{
27738061Smsmith	if (flags & ~(XEN_NETIF_CTRL_HASH_TYPE_IPV4 |
27838061Smsmith		      XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP |
27938061Smsmith		      XEN_NETIF_CTRL_HASH_TYPE_IPV6 |
28038061Smsmith		      XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP))
28138061Smsmith		return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
28238061Smsmith
28338061Smsmith	if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE)
28438061Smsmith		return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
28538061Smsmith
28638061Smsmith	vif->hash.flags = flags;
28738061Smsmith
28838061Smsmith	return XEN_NETIF_CTRL_STATUS_SUCCESS;
28938061Smsmith}
29038061Smsmith
29138061Smsmithu32 xenvif_set_hash_key(struct xenvif *vif, u32 gref, u32 len)
29238061Smsmith{
29338061Smsmith	u8 *key = vif->hash.key;
29438061Smsmith	struct gnttab_copy copy_op = {
29538061Smsmith		.source.u.ref = gref,
29638061Smsmith		.source.domid = vif->domid,
297121816Sbrooks		.dest.u.gmfn = virt_to_gfn(key),
29855939Snsouch		.dest.domid = DOMID_SELF,
29955939Snsouch		.dest.offset = xen_offset_in_page(key),
30038061Smsmith		.len = len,
30138061Smsmith		.flags = GNTCOPY_source_gref
30238061Smsmith	};
30355939Snsouch
30438061Smsmith	if (len > XEN_NETBK_MAX_HASH_KEY_SIZE)
30538061Smsmith		return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
30638061Smsmith
30738061Smsmith	if (copy_op.len != 0) {
30838061Smsmith		gnttab_batch_copy(&copy_op, 1);
30938061Smsmith
31038061Smsmith		if (copy_op.status != GNTST_okay)
31138061Smsmith			return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
31238061Smsmith	}
31338061Smsmith
31438061Smsmith	/* Clear any remaining key octets */
31538061Smsmith	if (len < XEN_NETBK_MAX_HASH_KEY_SIZE)
31638061Smsmith		memset(key + len, 0, XEN_NETBK_MAX_HASH_KEY_SIZE - len);
31738061Smsmith
31838061Smsmith	xenvif_flush_hash(vif);
31955939Snsouch
32038061Smsmith	return XEN_NETIF_CTRL_STATUS_SUCCESS;
32138061Smsmith}
32238061Smsmith
32355939Snsouchu32 xenvif_set_hash_mapping_size(struct xenvif *vif, u32 size)
32438061Smsmith{
32538061Smsmith	if (size > XEN_NETBK_MAX_HASH_MAPPING_SIZE)
32638061Smsmith		return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
32738061Smsmith
32842443Snsouch	vif->hash.size = size;
32938061Smsmith	memset(vif->hash.mapping[vif->hash.mapping_sel], 0,
33038061Smsmith	       sizeof(u32) * size);
33155939Snsouch
33238061Smsmith	return XEN_NETIF_CTRL_STATUS_SUCCESS;
33338061Smsmith}
33442443Snsouch
33542443Snsouchu32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len,
33655939Snsouch			    u32 off)
33742443Snsouch{
33838061Smsmith	u32 *mapping = vif->hash.mapping[!vif->hash.mapping_sel];
33955939Snsouch	unsigned int nr = 1;
34038061Smsmith	struct gnttab_copy copy_op[2] = {{
34138061Smsmith		.source.u.ref = gref,
34238061Smsmith		.source.domid = vif->domid,
34338061Smsmith		.dest.domid = DOMID_SELF,
344111119Simp		.len = len * sizeof(*mapping),
34538061Smsmith		.flags = GNTCOPY_source_gref
34655939Snsouch	}};
34738061Smsmith
34838061Smsmith	if ((off + len < off) || (off + len > vif->hash.size) ||
34938061Smsmith	    len > XEN_PAGE_SIZE / sizeof(*mapping))
35055939Snsouch		return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
35155939Snsouch
35255939Snsouch	copy_op[0].dest.u.gmfn = virt_to_gfn(mapping + off);
35355939Snsouch	copy_op[0].dest.offset = xen_offset_in_page(mapping + off);
35455939Snsouch	if (copy_op[0].dest.offset + copy_op[0].len > XEN_PAGE_SIZE) {
35555939Snsouch		copy_op[1] = copy_op[0];
35655939Snsouch		copy_op[1].source.offset = XEN_PAGE_SIZE - copy_op[0].dest.offset;
35755939Snsouch		copy_op[1].dest.u.gmfn = virt_to_gfn(mapping + off + len);
35838061Smsmith		copy_op[1].dest.offset = 0;
35938061Smsmith		copy_op[1].len = copy_op[0].len - copy_op[1].source.offset;
36038061Smsmith		copy_op[0].len = copy_op[1].source.offset;
36138061Smsmith		nr = 2;
36238061Smsmith	}
36338061Smsmith
36438061Smsmith	memcpy(mapping, vif->hash.mapping[vif->hash.mapping_sel],
36538061Smsmith	       vif->hash.size * sizeof(*mapping));
36638061Smsmith
36738061Smsmith	if (copy_op[0].len != 0) {
36838061Smsmith		gnttab_batch_copy(copy_op, nr);
36938061Smsmith
37038061Smsmith		if (copy_op[0].status != GNTST_okay ||
37138061Smsmith		    copy_op[nr - 1].status != GNTST_okay)
37238061Smsmith			return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
37338061Smsmith	}
37438061Smsmith
37538061Smsmith	while (len-- != 0)
37638061Smsmith		if (mapping[off++] >= vif->num_queues)
37738061Smsmith			return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER;
37838061Smsmith
37938061Smsmith	vif->hash.mapping_sel = !vif->hash.mapping_sel;
38038061Smsmith
38138061Smsmith	return XEN_NETIF_CTRL_STATUS_SUCCESS;
38238061Smsmith}
38338061Smsmith
38438061Smsmith#ifdef CONFIG_DEBUG_FS
38538061Smsmithvoid xenvif_dump_hash_info(struct xenvif *vif, struct seq_file *m)
38638061Smsmith{
38738061Smsmith	unsigned int i;
38838061Smsmith
38938061Smsmith	switch (vif->hash.alg) {
39038061Smsmith	case XEN_NETIF_CTRL_HASH_ALGORITHM_TOEPLITZ:
39138061Smsmith		seq_puts(m, "Hash Algorithm: TOEPLITZ\n");
39238061Smsmith		break;
39340626Smsmith
39440626Smsmith	case XEN_NETIF_CTRL_HASH_ALGORITHM_NONE:
39540626Smsmith		seq_puts(m, "Hash Algorithm: NONE\n");
39640626Smsmith		fallthrough;
39740626Smsmith	default:
39840626Smsmith		return;
39940626Smsmith	}
40038061Smsmith
40138373Sbde	if (vif->hash.flags) {
40238061Smsmith		seq_puts(m, "\nHash Flags:\n");
40338061Smsmith
40438061Smsmith		if (vif->hash.flags & XEN_NETIF_CTRL_HASH_TYPE_IPV4)
40538061Smsmith			seq_puts(m, "- IPv4\n");
40638061Smsmith		if (vif->hash.flags & XEN_NETIF_CTRL_HASH_TYPE_IPV4_TCP)
40738061Smsmith			seq_puts(m, "- IPv4 + TCP\n");
40855939Snsouch		if (vif->hash.flags & XEN_NETIF_CTRL_HASH_TYPE_IPV6)
40938061Smsmith			seq_puts(m, "- IPv6\n");
41055939Snsouch		if (vif->hash.flags & XEN_NETIF_CTRL_HASH_TYPE_IPV6_TCP)
41155939Snsouch			seq_puts(m, "- IPv6 + TCP\n");
41238061Smsmith	}
41338061Smsmith
41438061Smsmith	seq_puts(m, "\nHash Key:\n");
41555939Snsouch
41655939Snsouch	for (i = 0; i < XEN_NETBK_MAX_HASH_KEY_SIZE; ) {
41738061Smsmith		unsigned int j, n;
41838061Smsmith
41938061Smsmith		n = 8;
42038061Smsmith		if (i + n >= XEN_NETBK_MAX_HASH_KEY_SIZE)
42138061Smsmith			n = XEN_NETBK_MAX_HASH_KEY_SIZE - i;
42238061Smsmith
42338061Smsmith		seq_printf(m, "[%2u - %2u]: ", i, i + n - 1);
42455939Snsouch
42538061Smsmith		for (j = 0; j < n; j++, i++)
42642443Snsouch			seq_printf(m, "%02x ", vif->hash.key[i]);
42738061Smsmith
42855939Snsouch		seq_puts(m, "\n");
42938061Smsmith	}
43038061Smsmith
43138061Smsmith	if (vif->hash.size != 0) {
43255939Snsouch		const u32 *mapping = vif->hash.mapping[vif->hash.mapping_sel];
43355939Snsouch
43438061Smsmith		seq_puts(m, "\nHash Mapping:\n");
43555939Snsouch
43638061Smsmith		for (i = 0; i < vif->hash.size; ) {
43738061Smsmith			unsigned int j, n;
43838061Smsmith
43955939Snsouch			n = 8;
44055939Snsouch			if (i + n >= vif->hash.size)
44138061Smsmith				n = vif->hash.size - i;
44238061Smsmith
44338061Smsmith			seq_printf(m, "[%4u - %4u]: ", i, i + n - 1);
44438061Smsmith
44538061Smsmith			for (j = 0; j < n; j++, i++)
44643773Sdes				seq_printf(m, "%4u ", mapping[i]);
44743773Sdes
44843773Sdes			seq_puts(m, "\n");
44943773Sdes		}
45043773Sdes	}
45143773Sdes}
45243773Sdes#endif /* CONFIG_DEBUG_FS */
45343773Sdes
45443773Sdesvoid xenvif_init_hash(struct xenvif *vif)
45543773Sdes{
45643773Sdes	if (xenvif_hash_cache_size == 0)
45743773Sdes		return;
45843773Sdes
45943773Sdes	BUG_ON(vif->hash.cache.count);
460106937Ssam
46143773Sdes	spin_lock_init(&vif->hash.cache.lock);
46243773Sdes	INIT_LIST_HEAD(&vif->hash.cache.list);
46343773Sdes}
46455939Snsouch
46538061Smsmithvoid xenvif_deinit_hash(struct xenvif *vif)
46655939Snsouch{
46755939Snsouch	xenvif_flush_hash(vif);
46855939Snsouch}
46938061Smsmith