Skip to content

Commit 2a2336f

Browse files
Yevgeny PetrilinRoland Dreier
authored andcommitted
mlx4_core: Ethernet MAC/VLAN management
Add support for managing MAC and VLAN filters for each port. Signed-off-by: Yevgeny Petrilin <[email protected]> Signed-off-by: Oren Duer <[email protected]> Signed-off-by: Roland Dreier <[email protected]>
1 parent b79acb4 commit 2a2336f

File tree

6 files changed

+328
-1
lines changed

6 files changed

+328
-1
lines changed

drivers/net/mlx4/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
obj-$(CONFIG_MLX4_CORE) += mlx4_core.o
22

33
mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \
4-
mr.o pd.o profile.o qp.o reset.o srq.o
4+
mr.o pd.o port.o profile.o qp.o reset.o srq.o

drivers/net/mlx4/main.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,11 +780,22 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
780780
priv->eq_table.eq[i].irq = dev->pdev->irq;
781781
}
782782

783+
static void mlx4_init_port_info(struct mlx4_dev *dev, int port)
784+
{
785+
struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
786+
787+
info->dev = dev;
788+
info->port = port;
789+
mlx4_init_mac_table(dev, &info->mac_table);
790+
mlx4_init_vlan_table(dev, &info->vlan_table);
791+
}
792+
783793
static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
784794
{
785795
struct mlx4_priv *priv;
786796
struct mlx4_dev *dev;
787797
int err;
798+
int port;
788799

789800
printk(KERN_INFO PFX "Initializing %s\n",
790801
pci_name(pdev));
@@ -894,6 +905,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
894905
if (err)
895906
goto err_close;
896907

908+
for (port = 1; port <= dev->caps.num_ports; port++)
909+
mlx4_init_port_info(dev, port);
910+
897911
err = mlx4_register_device(dev);
898912
if (err)
899913
goto err_cleanup;

drivers/net/mlx4/mlx4.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,35 @@ struct mlx4_catas_err {
252252
struct list_head list;
253253
};
254254

255+
#define MLX4_MAX_MAC_NUM 128
256+
#define MLX4_MAC_TABLE_SIZE (MLX4_MAX_MAC_NUM << 3)
257+
258+
struct mlx4_mac_table {
259+
__be64 entries[MLX4_MAX_MAC_NUM];
260+
int refs[MLX4_MAX_MAC_NUM];
261+
struct mutex mutex;
262+
int total;
263+
int max;
264+
};
265+
266+
#define MLX4_MAX_VLAN_NUM 128
267+
#define MLX4_VLAN_TABLE_SIZE (MLX4_MAX_VLAN_NUM << 2)
268+
269+
struct mlx4_vlan_table {
270+
__be32 entries[MLX4_MAX_VLAN_NUM];
271+
int refs[MLX4_MAX_VLAN_NUM];
272+
struct mutex mutex;
273+
int total;
274+
int max;
275+
};
276+
277+
struct mlx4_port_info {
278+
struct mlx4_dev *dev;
279+
int port;
280+
struct mlx4_mac_table mac_table;
281+
struct mlx4_vlan_table vlan_table;
282+
};
283+
255284
struct mlx4_priv {
256285
struct mlx4_dev dev;
257286

@@ -280,6 +309,7 @@ struct mlx4_priv {
280309

281310
struct mlx4_uar driver_uar;
282311
void __iomem *kar;
312+
struct mlx4_port_info port[MLX4_MAX_PORTS + 1];
283313
};
284314

285315
static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
@@ -350,4 +380,7 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
350380

351381
void mlx4_handle_catas_err(struct mlx4_dev *dev);
352382

383+
void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
384+
void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
385+
353386
#endif /* MLX4_H */

drivers/net/mlx4/port.c

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
/*
2+
* Copyright (c) 2007 Mellanox Technologies. All rights reserved.
3+
*
4+
* This software is available to you under a choice of one of two
5+
* licenses. You may choose to be licensed under the terms of the GNU
6+
* General Public License (GPL) Version 2, available from the file
7+
* COPYING in the main directory of this source tree, or the
8+
* OpenIB.org BSD license below:
9+
*
10+
* Redistribution and use in source and binary forms, with or
11+
* without modification, are permitted provided that the following
12+
* conditions are met:
13+
*
14+
* - Redistributions of source code must retain the above
15+
* copyright notice, this list of conditions and the following
16+
* disclaimer.
17+
*
18+
* - Redistributions in binary form must reproduce the above
19+
* copyright notice, this list of conditions and the following
20+
* disclaimer in the documentation and/or other materials
21+
* provided with the distribution.
22+
*
23+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30+
* SOFTWARE.
31+
*/
32+
33+
#include <linux/errno.h>
34+
#include <linux/if_ether.h>
35+
36+
#include <linux/mlx4/cmd.h>
37+
38+
#include "mlx4.h"
39+
40+
#define MLX4_MAC_VALID (1ull << 63)
41+
#define MLX4_MAC_MASK 0xffffffffffffULL
42+
43+
#define MLX4_VLAN_VALID (1u << 31)
44+
#define MLX4_VLAN_MASK 0xfff
45+
46+
void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table)
47+
{
48+
int i;
49+
50+
mutex_init(&table->mutex);
51+
for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
52+
table->entries[i] = 0;
53+
table->refs[i] = 0;
54+
}
55+
table->max = 1 << dev->caps.log_num_macs;
56+
table->total = 0;
57+
}
58+
59+
void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table)
60+
{
61+
int i;
62+
63+
mutex_init(&table->mutex);
64+
for (i = 0; i < MLX4_MAX_VLAN_NUM; i++) {
65+
table->entries[i] = 0;
66+
table->refs[i] = 0;
67+
}
68+
table->max = 1 << dev->caps.log_num_vlans;
69+
table->total = 0;
70+
}
71+
72+
static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port,
73+
__be64 *entries)
74+
{
75+
struct mlx4_cmd_mailbox *mailbox;
76+
u32 in_mod;
77+
int err;
78+
79+
mailbox = mlx4_alloc_cmd_mailbox(dev);
80+
if (IS_ERR(mailbox))
81+
return PTR_ERR(mailbox);
82+
83+
memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE);
84+
85+
in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port;
86+
err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
87+
MLX4_CMD_TIME_CLASS_B);
88+
89+
mlx4_free_cmd_mailbox(dev, mailbox);
90+
return err;
91+
}
92+
93+
int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index)
94+
{
95+
struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table;
96+
int i, err = 0;
97+
int free = -1;
98+
99+
mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac);
100+
mutex_lock(&table->mutex);
101+
for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) {
102+
if (free < 0 && !table->refs[i]) {
103+
free = i;
104+
continue;
105+
}
106+
107+
if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
108+
/* MAC already registered, increase refernce count */
109+
*index = i;
110+
++table->refs[i];
111+
goto out;
112+
}
113+
}
114+
mlx4_dbg(dev, "Free MAC index is %d\n", free);
115+
116+
if (table->total == table->max) {
117+
/* No free mac entries */
118+
err = -ENOSPC;
119+
goto out;
120+
}
121+
122+
/* Register new MAC */
123+
table->refs[free] = 1;
124+
table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID);
125+
126+
err = mlx4_set_port_mac_table(dev, port, table->entries);
127+
if (unlikely(err)) {
128+
mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) mac);
129+
table->refs[free] = 0;
130+
table->entries[free] = 0;
131+
goto out;
132+
}
133+
134+
*index = free;
135+
++table->total;
136+
out:
137+
mutex_unlock(&table->mutex);
138+
return err;
139+
}
140+
EXPORT_SYMBOL_GPL(mlx4_register_mac);
141+
142+
void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index)
143+
{
144+
struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table;
145+
146+
mutex_lock(&table->mutex);
147+
if (!table->refs[index]) {
148+
mlx4_warn(dev, "No MAC entry for index %d\n", index);
149+
goto out;
150+
}
151+
if (--table->refs[index]) {
152+
mlx4_warn(dev, "Have more references for index %d,"
153+
"no need to modify MAC table\n", index);
154+
goto out;
155+
}
156+
table->entries[index] = 0;
157+
mlx4_set_port_mac_table(dev, port, table->entries);
158+
--table->total;
159+
out:
160+
mutex_unlock(&table->mutex);
161+
}
162+
EXPORT_SYMBOL_GPL(mlx4_unregister_mac);
163+
164+
static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port,
165+
__be32 *entries)
166+
{
167+
struct mlx4_cmd_mailbox *mailbox;
168+
u32 in_mod;
169+
int err;
170+
171+
mailbox = mlx4_alloc_cmd_mailbox(dev);
172+
if (IS_ERR(mailbox))
173+
return PTR_ERR(mailbox);
174+
175+
memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE);
176+
in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port;
177+
err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
178+
MLX4_CMD_TIME_CLASS_B);
179+
180+
mlx4_free_cmd_mailbox(dev, mailbox);
181+
182+
return err;
183+
}
184+
185+
int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
186+
{
187+
struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
188+
int i, err = 0;
189+
int free = -1;
190+
191+
mutex_lock(&table->mutex);
192+
for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) {
193+
if (free < 0 && (table->refs[i] == 0)) {
194+
free = i;
195+
continue;
196+
}
197+
198+
if (table->refs[i] &&
199+
(vlan == (MLX4_VLAN_MASK &
200+
be32_to_cpu(table->entries[i])))) {
201+
/* Vlan already registered, increase refernce count */
202+
*index = i;
203+
++table->refs[i];
204+
goto out;
205+
}
206+
}
207+
208+
if (table->total == table->max) {
209+
/* No free vlan entries */
210+
err = -ENOSPC;
211+
goto out;
212+
}
213+
214+
/* Register new MAC */
215+
table->refs[free] = 1;
216+
table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID);
217+
218+
err = mlx4_set_port_vlan_table(dev, port, table->entries);
219+
if (unlikely(err)) {
220+
mlx4_warn(dev, "Failed adding vlan: %u\n", vlan);
221+
table->refs[free] = 0;
222+
table->entries[free] = 0;
223+
goto out;
224+
}
225+
226+
*index = free;
227+
++table->total;
228+
out:
229+
mutex_unlock(&table->mutex);
230+
return err;
231+
}
232+
EXPORT_SYMBOL_GPL(mlx4_register_vlan);
233+
234+
void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
235+
{
236+
struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
237+
238+
if (index < MLX4_VLAN_REGULAR) {
239+
mlx4_warn(dev, "Trying to free special vlan index %d\n", index);
240+
return;
241+
}
242+
243+
mutex_lock(&table->mutex);
244+
if (!table->refs[index]) {
245+
mlx4_warn(dev, "No vlan entry for index %d\n", index);
246+
goto out;
247+
}
248+
if (--table->refs[index]) {
249+
mlx4_dbg(dev, "Have more references for index %d,"
250+
"no need to modify vlan table\n", index);
251+
goto out;
252+
}
253+
table->entries[index] = 0;
254+
mlx4_set_port_vlan_table(dev, port, table->entries);
255+
--table->total;
256+
out:
257+
mutex_unlock(&table->mutex);
258+
}
259+
EXPORT_SYMBOL_GPL(mlx4_unregister_vlan);

include/linux/mlx4/cmd.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,15 @@ enum {
132132
MLX4_MAILBOX_SIZE = 4096
133133
};
134134

135+
enum {
136+
/* set port opcode modifiers */
137+
MLX4_SET_PORT_GENERAL = 0x0,
138+
MLX4_SET_PORT_RQP_CALC = 0x1,
139+
MLX4_SET_PORT_MAC_TABLE = 0x2,
140+
MLX4_SET_PORT_VLAN_TABLE = 0x3,
141+
MLX4_SET_PORT_PRIO_MAP = 0x4,
142+
};
143+
135144
struct mlx4_dev;
136145

137146
struct mlx4_cmd_mailbox {

include/linux/mlx4/device.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ enum mlx4_qp_region {
153153
MLX4_NUM_QP_REGION
154154
};
155155

156+
enum mlx4_special_vlan_idx {
157+
MLX4_NO_VLAN_IDX = 0,
158+
MLX4_VLAN_MISS_IDX,
159+
MLX4_VLAN_REGULAR
160+
};
161+
156162
enum {
157163
MLX4_NUM_FEXCH = 64 * 1024,
158164
};
@@ -438,6 +444,12 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
438444
int block_mcast_loopback);
439445
int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]);
440446

447+
int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index);
448+
void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index);
449+
450+
int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
451+
void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index);
452+
441453
int mlx4_map_phys_fmr(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u64 *page_list,
442454
int npages, u64 iova, u32 *lkey, u32 *rkey);
443455
int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages,

0 commit comments

Comments
 (0)