1/*-
2 * Copyright (c) 2013-2017, Mellanox Technologies, Ltd.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#ifndef __MLX5_ESWITCH_H__
27#define __MLX5_ESWITCH_H__
28
29#include <linux/if_ether.h>
30#include <dev/mlx5/device.h>
31
32#define MLX5_MAX_UC_PER_VPORT(dev) \
33	(1 << MLX5_CAP_GEN(dev, log_max_current_uc_list))
34
35#define MLX5_MAX_MC_PER_VPORT(dev) \
36	(1 << MLX5_CAP_GEN(dev, log_max_current_mc_list))
37
38#define MLX5_L2_ADDR_HASH_SIZE (BIT(BITS_PER_BYTE))
39#define MLX5_L2_ADDR_HASH(addr) (addr[5])
40
41/* L2 -mac address based- hash helpers */
42struct l2addr_node {
43	struct hlist_node hlist;
44	u8                addr[ETH_ALEN];
45};
46
47#define for_each_l2hash_node(hn, tmp, hash, i) \
48	for (i = 0; i < MLX5_L2_ADDR_HASH_SIZE; i++) \
49		hlist_for_each_entry_safe(hn, tmp, &hash[i], hlist)
50
51#define l2addr_hash_find(hash, mac, type) ({                \
52	int ix = MLX5_L2_ADDR_HASH(mac);                    \
53	bool found = false;                                 \
54	type *ptr = NULL;                                   \
55							    \
56	hlist_for_each_entry(ptr, &hash[ix], node.hlist)    \
57		if (ether_addr_equal(ptr->node.addr, mac)) {\
58			found = true;                       \
59			break;                              \
60		}                                           \
61	if (!found)                                         \
62		ptr = NULL;                                 \
63	ptr;                                                \
64})
65
66#define l2addr_hash_add(hash, mac, type, gfp) ({            \
67	int ix = MLX5_L2_ADDR_HASH(mac);                    \
68	type *ptr = NULL;                                   \
69							    \
70	ptr = kzalloc(sizeof(type), gfp);                   \
71	if (ptr) {                                          \
72		ether_addr_copy(ptr->node.addr, mac);       \
73		hlist_add_head(&ptr->node.hlist, &hash[ix]);\
74	}                                                   \
75	ptr;                                                \
76})
77
78#define l2addr_hash_del(ptr) ({                             \
79	hlist_del(&ptr->node.hlist);                        \
80	kfree(ptr);                                         \
81})
82
83struct vport_ingress {
84	struct mlx5_flow_table *acl;
85	struct mlx5_flow_group *drop_grp;
86	struct mlx5_flow_rule  *drop_rule;
87};
88
89struct vport_egress {
90	struct mlx5_flow_table *acl;
91	struct mlx5_flow_group *allowed_vlans_grp;
92	struct mlx5_flow_group *drop_grp;
93	struct mlx5_flow_rule  *allowed_vlan;
94	struct mlx5_flow_rule  *drop_rule;
95};
96
97struct mlx5_vport {
98	struct mlx5_core_dev    *dev;
99	int                     vport;
100	struct hlist_head       uc_list[MLX5_L2_ADDR_HASH_SIZE];
101	struct hlist_head       mc_list[MLX5_L2_ADDR_HASH_SIZE];
102	struct work_struct      vport_change_handler;
103
104	struct vport_ingress    ingress;
105	struct vport_egress     egress;
106
107	u16                     vlan;
108	u8                      qos;
109	struct mutex	state_lock; /* protect dynamic state changes */
110	/* This spinlock protects access to vport data, between
111	 * "esw_vport_disable" and ongoing interrupt "mlx5_eswitch_vport_event"
112	 * once vport marked as disabled new interrupts are discarded.
113	 */
114	spinlock_t              lock; /* vport events sync */
115	bool                    enabled;
116	u16                     enabled_events;
117};
118
119struct mlx5_l2_table {
120	struct hlist_head l2_hash[MLX5_L2_ADDR_HASH_SIZE];
121	u32                  size;
122	unsigned long        *bitmap;
123};
124
125struct mlx5_eswitch_fdb {
126	void *fdb;
127	struct mlx5_flow_group *addr_grp;
128};
129
130struct mlx5_eswitch {
131	struct mlx5_core_dev    *dev;
132	struct mlx5_l2_table    l2_table;
133	struct mlx5_eswitch_fdb fdb_table;
134	struct hlist_head       mc_table[MLX5_L2_ADDR_HASH_SIZE];
135	struct workqueue_struct *work_queue;
136	struct mlx5_vport       *vports;
137	int                     total_vports;
138	int                     enabled_vports;
139};
140
141struct mlx5_esw_vport_info {
142	__u32 vf;
143	__u8 mac[32];
144	__u32 vlan;
145	__u32 qos;
146	__u32 spoofchk;
147	__u32 linkstate;
148	__u32 min_tx_rate;
149	__u32 max_tx_rate;
150};
151
152/* E-Switch API */
153int mlx5_eswitch_init(struct mlx5_core_dev *dev, int total_vports);
154void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw);
155void mlx5_eswitch_vport_event(struct mlx5_eswitch *esw, struct mlx5_eqe *eqe);
156int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs);
157void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw);
158int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
159			       int vport, u8 mac[ETH_ALEN]);
160int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
161				 int vport, int link_state);
162int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
163				int vport, u16 vlan, u8 qos);
164int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
165				  int vport, struct mlx5_esw_vport_info *evi);
166
167#endif /* __MLX5_ESWITCH_H__ */
168