diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/cmd.c | 9 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mcg.c | 218 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 22 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/profile.c | 5 |
5 files changed, 198 insertions, 69 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index bce0579a285..0f2069d9827 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c | |||
@@ -997,6 +997,15 @@ static struct mlx4_cmd_info cmd_info[] = { | |||
997 | .wrapper = mlx4_QP_ATTACH_wrapper | 997 | .wrapper = mlx4_QP_ATTACH_wrapper |
998 | }, | 998 | }, |
999 | { | 999 | { |
1000 | .opcode = MLX4_CMD_PROMISC, | ||
1001 | .has_inbox = false, | ||
1002 | .has_outbox = false, | ||
1003 | .out_is_imm = false, | ||
1004 | .encode_slave_id = false, | ||
1005 | .verify = NULL, | ||
1006 | .wrapper = mlx4_PROMISC_wrapper | ||
1007 | }, | ||
1008 | { | ||
1000 | .opcode = MLX4_CMD_INFORM_FLR_DONE, | 1009 | .opcode = MLX4_CMD_INFORM_FLR_DONE, |
1001 | .has_inbox = false, | 1010 | .has_inbox = false, |
1002 | .has_outbox = false, | 1011 | .has_outbox = false, |
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 64d03f8b23a..8be56326b04 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -75,6 +75,14 @@ MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero"); | |||
75 | 75 | ||
76 | #endif /* CONFIG_PCI_MSI */ | 76 | #endif /* CONFIG_PCI_MSI */ |
77 | 77 | ||
78 | int mlx4_log_num_mgm_entry_size = 10; | ||
79 | module_param_named(log_num_mgm_entry_size, | ||
80 | mlx4_log_num_mgm_entry_size, int, 0444); | ||
81 | MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num" | ||
82 | " of qp per mcg, for example:" | ||
83 | " 10 gives 248.range: 9<=" | ||
84 | " log_num_mgm_entry_size <= 12"); | ||
85 | |||
78 | static char mlx4_version[] __devinitdata = | 86 | static char mlx4_version[] __devinitdata = |
79 | DRV_NAME ": Mellanox ConnectX core driver v" | 87 | DRV_NAME ": Mellanox ConnectX core driver v" |
80 | DRV_VERSION " (" DRV_RELDATE ")\n"; | 88 | DRV_VERSION " (" DRV_RELDATE ")\n"; |
@@ -205,7 +213,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
205 | dev->caps.reserved_srqs = dev_cap->reserved_srqs; | 213 | dev->caps.reserved_srqs = dev_cap->reserved_srqs; |
206 | dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz; | 214 | dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz; |
207 | dev->caps.max_rq_desc_sz = dev_cap->max_rq_desc_sz; | 215 | dev->caps.max_rq_desc_sz = dev_cap->max_rq_desc_sz; |
208 | dev->caps.num_qp_per_mgm = MLX4_QP_PER_MGM; | 216 | dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); |
209 | /* | 217 | /* |
210 | * Subtract 1 from the limit because we need to allocate a | 218 | * Subtract 1 from the limit because we need to allocate a |
211 | * spare CQE so the HCA HW can tell the difference between an | 219 | * spare CQE so the HCA HW can tell the difference between an |
@@ -648,7 +656,8 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, | |||
648 | * and it's a lot easier than trying to track ref counts. | 656 | * and it's a lot easier than trying to track ref counts. |
649 | */ | 657 | */ |
650 | err = mlx4_init_icm_table(dev, &priv->mcg_table.table, | 658 | err = mlx4_init_icm_table(dev, &priv->mcg_table.table, |
651 | init_hca->mc_base, MLX4_MGM_ENTRY_SIZE, | 659 | init_hca->mc_base, |
660 | mlx4_get_mgm_entry_size(dev), | ||
652 | dev->caps.num_mgms + dev->caps.num_amgms, | 661 | dev->caps.num_mgms + dev->caps.num_amgms, |
653 | dev->caps.num_mgms + dev->caps.num_amgms, | 662 | dev->caps.num_mgms + dev->caps.num_amgms, |
654 | 0, 0); | 663 | 0, 0); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index 4187f7bbd79..b36c279bcca 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c | |||
@@ -44,6 +44,24 @@ | |||
44 | 44 | ||
45 | static const u8 zero_gid[16]; /* automatically initialized to 0 */ | 45 | static const u8 zero_gid[16]; /* automatically initialized to 0 */ |
46 | 46 | ||
47 | struct mlx4_mgm { | ||
48 | __be32 next_gid_index; | ||
49 | __be32 members_count; | ||
50 | u32 reserved[2]; | ||
51 | u8 gid[16]; | ||
52 | __be32 qp[MLX4_MAX_QP_PER_MGM]; | ||
53 | }; | ||
54 | |||
55 | int mlx4_get_mgm_entry_size(struct mlx4_dev *dev) | ||
56 | { | ||
57 | return min((1 << mlx4_log_num_mgm_entry_size), MLX4_MAX_MGM_ENTRY_SIZE); | ||
58 | } | ||
59 | |||
60 | int mlx4_get_qp_per_mgm(struct mlx4_dev *dev) | ||
61 | { | ||
62 | return 4 * (mlx4_get_mgm_entry_size(dev) / 16 - 2); | ||
63 | } | ||
64 | |||
47 | static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index, | 65 | static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index, |
48 | struct mlx4_cmd_mailbox *mailbox) | 66 | struct mlx4_cmd_mailbox *mailbox) |
49 | { | 67 | { |
@@ -58,12 +76,12 @@ static int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index, | |||
58 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); | 76 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); |
59 | } | 77 | } |
60 | 78 | ||
61 | static int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 vep_num, u8 port, u8 steer, | 79 | static int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 port, u8 steer, |
62 | struct mlx4_cmd_mailbox *mailbox) | 80 | struct mlx4_cmd_mailbox *mailbox) |
63 | { | 81 | { |
64 | u32 in_mod; | 82 | u32 in_mod; |
65 | 83 | ||
66 | in_mod = (u32) vep_num << 24 | (u32) port << 16 | steer << 1; | 84 | in_mod = (u32) port << 16 | steer << 1; |
67 | return mlx4_cmd(dev, mailbox->dma, in_mod, 0x1, | 85 | return mlx4_cmd(dev, mailbox->dma, in_mod, 0x1, |
68 | MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A, | 86 | MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A, |
69 | MLX4_CMD_NATIVE); | 87 | MLX4_CMD_NATIVE); |
@@ -104,7 +122,7 @@ static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num, | |||
104 | * Add new entry to steering data structure. | 122 | * Add new entry to steering data structure. |
105 | * All promisc QPs should be added as well | 123 | * All promisc QPs should be added as well |
106 | */ | 124 | */ |
107 | static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | 125 | static int new_steering_entry(struct mlx4_dev *dev, u8 port, |
108 | enum mlx4_steer_type steer, | 126 | enum mlx4_steer_type steer, |
109 | unsigned int index, u32 qpn) | 127 | unsigned int index, u32 qpn) |
110 | { | 128 | { |
@@ -117,10 +135,8 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
117 | struct mlx4_promisc_qp *dqp = NULL; | 135 | struct mlx4_promisc_qp *dqp = NULL; |
118 | u32 prot; | 136 | u32 prot; |
119 | int err; | 137 | int err; |
120 | u8 pf_num; | ||
121 | 138 | ||
122 | pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); | 139 | s_steer = &mlx4_priv(dev)->steer[0]; |
123 | s_steer = &mlx4_priv(dev)->steer[pf_num]; | ||
124 | new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL); | 140 | new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL); |
125 | if (!new_entry) | 141 | if (!new_entry) |
126 | return -ENOMEM; | 142 | return -ENOMEM; |
@@ -132,7 +148,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
132 | /* If the given qpn is also a promisc qp, | 148 | /* If the given qpn is also a promisc qp, |
133 | * it should be inserted to duplicates list | 149 | * it should be inserted to duplicates list |
134 | */ | 150 | */ |
135 | pqp = get_promisc_qp(dev, pf_num, steer, qpn); | 151 | pqp = get_promisc_qp(dev, 0, steer, qpn); |
136 | if (pqp) { | 152 | if (pqp) { |
137 | dqp = kmalloc(sizeof *dqp, GFP_KERNEL); | 153 | dqp = kmalloc(sizeof *dqp, GFP_KERNEL); |
138 | if (!dqp) { | 154 | if (!dqp) { |
@@ -167,7 +183,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
167 | /* don't add already existing qpn */ | 183 | /* don't add already existing qpn */ |
168 | if (pqp->qpn == qpn) | 184 | if (pqp->qpn == qpn) |
169 | continue; | 185 | continue; |
170 | if (members_count == MLX4_QP_PER_MGM) { | 186 | if (members_count == dev->caps.num_qp_per_mgm) { |
171 | /* out of space */ | 187 | /* out of space */ |
172 | err = -ENOMEM; | 188 | err = -ENOMEM; |
173 | goto out_mailbox; | 189 | goto out_mailbox; |
@@ -195,7 +211,7 @@ out_alloc: | |||
195 | } | 211 | } |
196 | 212 | ||
197 | /* update the data structures with existing steering entry */ | 213 | /* update the data structures with existing steering entry */ |
198 | static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | 214 | static int existing_steering_entry(struct mlx4_dev *dev, u8 port, |
199 | enum mlx4_steer_type steer, | 215 | enum mlx4_steer_type steer, |
200 | unsigned int index, u32 qpn) | 216 | unsigned int index, u32 qpn) |
201 | { | 217 | { |
@@ -203,12 +219,10 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
203 | struct mlx4_steer_index *tmp_entry, *entry = NULL; | 219 | struct mlx4_steer_index *tmp_entry, *entry = NULL; |
204 | struct mlx4_promisc_qp *pqp; | 220 | struct mlx4_promisc_qp *pqp; |
205 | struct mlx4_promisc_qp *dqp; | 221 | struct mlx4_promisc_qp *dqp; |
206 | u8 pf_num; | ||
207 | 222 | ||
208 | pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); | 223 | s_steer = &mlx4_priv(dev)->steer[0]; |
209 | s_steer = &mlx4_priv(dev)->steer[pf_num]; | ||
210 | 224 | ||
211 | pqp = get_promisc_qp(dev, pf_num, steer, qpn); | 225 | pqp = get_promisc_qp(dev, 0, steer, qpn); |
212 | if (!pqp) | 226 | if (!pqp) |
213 | return 0; /* nothing to do */ | 227 | return 0; /* nothing to do */ |
214 | 228 | ||
@@ -227,7 +241,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
227 | * we need to add it as a duplicate to this entry | 241 | * we need to add it as a duplicate to this entry |
228 | * for future references */ | 242 | * for future references */ |
229 | list_for_each_entry(dqp, &entry->duplicates, list) { | 243 | list_for_each_entry(dqp, &entry->duplicates, list) { |
230 | if (qpn == dqp->qpn) | 244 | if (qpn == pqp->qpn) |
231 | return 0; /* qp is already duplicated */ | 245 | return 0; /* qp is already duplicated */ |
232 | } | 246 | } |
233 | 247 | ||
@@ -243,20 +257,18 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
243 | 257 | ||
244 | /* Check whether a qpn is a duplicate on steering entry | 258 | /* Check whether a qpn is a duplicate on steering entry |
245 | * If so, it should not be removed from mgm */ | 259 | * If so, it should not be removed from mgm */ |
246 | static bool check_duplicate_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | 260 | static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port, |
247 | enum mlx4_steer_type steer, | 261 | enum mlx4_steer_type steer, |
248 | unsigned int index, u32 qpn) | 262 | unsigned int index, u32 qpn) |
249 | { | 263 | { |
250 | struct mlx4_steer *s_steer; | 264 | struct mlx4_steer *s_steer; |
251 | struct mlx4_steer_index *tmp_entry, *entry = NULL; | 265 | struct mlx4_steer_index *tmp_entry, *entry = NULL; |
252 | struct mlx4_promisc_qp *dqp, *tmp_dqp; | 266 | struct mlx4_promisc_qp *dqp, *tmp_dqp; |
253 | u8 pf_num; | ||
254 | 267 | ||
255 | pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); | 268 | s_steer = &mlx4_priv(dev)->steer[0]; |
256 | s_steer = &mlx4_priv(dev)->steer[pf_num]; | ||
257 | 269 | ||
258 | /* if qp is not promisc, it cannot be duplicated */ | 270 | /* if qp is not promisc, it cannot be duplicated */ |
259 | if (!get_promisc_qp(dev, pf_num, steer, qpn)) | 271 | if (!get_promisc_qp(dev, 0, steer, qpn)) |
260 | return false; | 272 | return false; |
261 | 273 | ||
262 | /* The qp is promisc qp so it is a duplicate on this index | 274 | /* The qp is promisc qp so it is a duplicate on this index |
@@ -281,7 +293,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
281 | } | 293 | } |
282 | 294 | ||
283 | /* I a steering entry contains only promisc QPs, it can be removed. */ | 295 | /* I a steering entry contains only promisc QPs, it can be removed. */ |
284 | static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | 296 | static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, |
285 | enum mlx4_steer_type steer, | 297 | enum mlx4_steer_type steer, |
286 | unsigned int index, u32 tqpn) | 298 | unsigned int index, u32 tqpn) |
287 | { | 299 | { |
@@ -293,10 +305,8 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
293 | u32 members_count; | 305 | u32 members_count; |
294 | bool ret = false; | 306 | bool ret = false; |
295 | int i; | 307 | int i; |
296 | u8 pf_num; | ||
297 | 308 | ||
298 | pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); | 309 | s_steer = &mlx4_priv(dev)->steer[0]; |
299 | s_steer = &mlx4_priv(dev)->steer[pf_num]; | ||
300 | 310 | ||
301 | mailbox = mlx4_alloc_cmd_mailbox(dev); | 311 | mailbox = mlx4_alloc_cmd_mailbox(dev); |
302 | if (IS_ERR(mailbox)) | 312 | if (IS_ERR(mailbox)) |
@@ -308,7 +318,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
308 | members_count = be32_to_cpu(mgm->members_count) & 0xffffff; | 318 | members_count = be32_to_cpu(mgm->members_count) & 0xffffff; |
309 | for (i = 0; i < members_count; i++) { | 319 | for (i = 0; i < members_count; i++) { |
310 | qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; | 320 | qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; |
311 | if (!get_promisc_qp(dev, pf_num, steer, qpn) && qpn != tqpn) { | 321 | if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) { |
312 | /* the qp is not promisc, the entry can't be removed */ | 322 | /* the qp is not promisc, the entry can't be removed */ |
313 | goto out; | 323 | goto out; |
314 | } | 324 | } |
@@ -334,7 +344,7 @@ out: | |||
334 | return ret; | 344 | return ret; |
335 | } | 345 | } |
336 | 346 | ||
337 | static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, | 347 | static int add_promisc_qp(struct mlx4_dev *dev, u8 port, |
338 | enum mlx4_steer_type steer, u32 qpn) | 348 | enum mlx4_steer_type steer, u32 qpn) |
339 | { | 349 | { |
340 | struct mlx4_steer *s_steer; | 350 | struct mlx4_steer *s_steer; |
@@ -349,14 +359,13 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
349 | bool found; | 359 | bool found; |
350 | int last_index; | 360 | int last_index; |
351 | int err; | 361 | int err; |
352 | u8 pf_num; | ||
353 | struct mlx4_priv *priv = mlx4_priv(dev); | 362 | struct mlx4_priv *priv = mlx4_priv(dev); |
354 | pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); | 363 | |
355 | s_steer = &mlx4_priv(dev)->steer[pf_num]; | 364 | s_steer = &mlx4_priv(dev)->steer[0]; |
356 | 365 | ||
357 | mutex_lock(&priv->mcg_table.mutex); | 366 | mutex_lock(&priv->mcg_table.mutex); |
358 | 367 | ||
359 | if (get_promisc_qp(dev, pf_num, steer, qpn)) { | 368 | if (get_promisc_qp(dev, 0, steer, qpn)) { |
360 | err = 0; /* Noting to do, already exists */ | 369 | err = 0; /* Noting to do, already exists */ |
361 | goto out_mutex; | 370 | goto out_mutex; |
362 | } | 371 | } |
@@ -399,7 +408,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
399 | } | 408 | } |
400 | if (!found) { | 409 | if (!found) { |
401 | /* Need to add the qpn to mgm */ | 410 | /* Need to add the qpn to mgm */ |
402 | if (members_count == MLX4_QP_PER_MGM) { | 411 | if (members_count == dev->caps.num_qp_per_mgm) { |
403 | /* entry is full */ | 412 | /* entry is full */ |
404 | err = -ENOMEM; | 413 | err = -ENOMEM; |
405 | goto out_mailbox; | 414 | goto out_mailbox; |
@@ -422,7 +431,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
422 | mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); | 431 | mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); |
423 | mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); | 432 | mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); |
424 | 433 | ||
425 | err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox); | 434 | err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox); |
426 | if (err) | 435 | if (err) |
427 | goto out_list; | 436 | goto out_list; |
428 | 437 | ||
@@ -441,7 +450,7 @@ out_mutex: | |||
441 | return err; | 450 | return err; |
442 | } | 451 | } |
443 | 452 | ||
444 | static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, | 453 | static int remove_promisc_qp(struct mlx4_dev *dev, u8 port, |
445 | enum mlx4_steer_type steer, u32 qpn) | 454 | enum mlx4_steer_type steer, u32 qpn) |
446 | { | 455 | { |
447 | struct mlx4_priv *priv = mlx4_priv(dev); | 456 | struct mlx4_priv *priv = mlx4_priv(dev); |
@@ -456,13 +465,11 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
456 | bool back_to_list = false; | 465 | bool back_to_list = false; |
457 | int loc, i; | 466 | int loc, i; |
458 | int err; | 467 | int err; |
459 | u8 pf_num; | ||
460 | 468 | ||
461 | pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); | 469 | s_steer = &mlx4_priv(dev)->steer[0]; |
462 | s_steer = &mlx4_priv(dev)->steer[pf_num]; | ||
463 | mutex_lock(&priv->mcg_table.mutex); | 470 | mutex_lock(&priv->mcg_table.mutex); |
464 | 471 | ||
465 | pqp = get_promisc_qp(dev, pf_num, steer, qpn); | 472 | pqp = get_promisc_qp(dev, 0, steer, qpn); |
466 | if (unlikely(!pqp)) { | 473 | if (unlikely(!pqp)) { |
467 | mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn); | 474 | mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn); |
468 | /* nothing to do */ | 475 | /* nothing to do */ |
@@ -481,12 +488,13 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, | |||
481 | goto out_list; | 488 | goto out_list; |
482 | } | 489 | } |
483 | mgm = mailbox->buf; | 490 | mgm = mailbox->buf; |
491 | memset(mgm, 0, sizeof *mgm); | ||
484 | members_count = 0; | 492 | members_count = 0; |
485 | list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list) | 493 | list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list) |
486 | mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); | 494 | mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); |
487 | mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); | 495 | mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); |
488 | 496 | ||
489 | err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox); | 497 | err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox); |
490 | if (err) | 498 | if (err) |
491 | goto out_mailbox; | 499 | goto out_mailbox; |
492 | 500 | ||
@@ -651,12 +659,13 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], | |||
651 | } | 659 | } |
652 | index += dev->caps.num_mgms; | 660 | index += dev->caps.num_mgms; |
653 | 661 | ||
662 | new_entry = 1; | ||
654 | memset(mgm, 0, sizeof *mgm); | 663 | memset(mgm, 0, sizeof *mgm); |
655 | memcpy(mgm->gid, gid, 16); | 664 | memcpy(mgm->gid, gid, 16); |
656 | } | 665 | } |
657 | 666 | ||
658 | members_count = be32_to_cpu(mgm->members_count) & 0xffffff; | 667 | members_count = be32_to_cpu(mgm->members_count) & 0xffffff; |
659 | if (members_count == MLX4_QP_PER_MGM) { | 668 | if (members_count == dev->caps.num_qp_per_mgm) { |
660 | mlx4_err(dev, "MGM at index %x is full.\n", index); | 669 | mlx4_err(dev, "MGM at index %x is full.\n", index); |
661 | err = -ENOMEM; | 670 | err = -ENOMEM; |
662 | goto out; | 671 | goto out; |
@@ -698,9 +707,9 @@ out: | |||
698 | if (prot == MLX4_PROT_ETH) { | 707 | if (prot == MLX4_PROT_ETH) { |
699 | /* manage the steering entry for promisc mode */ | 708 | /* manage the steering entry for promisc mode */ |
700 | if (new_entry) | 709 | if (new_entry) |
701 | new_steering_entry(dev, 0, port, steer, index, qp->qpn); | 710 | new_steering_entry(dev, port, steer, index, qp->qpn); |
702 | else | 711 | else |
703 | existing_steering_entry(dev, 0, port, steer, | 712 | existing_steering_entry(dev, port, steer, |
704 | index, qp->qpn); | 713 | index, qp->qpn); |
705 | } | 714 | } |
706 | if (err && link && index != -1) { | 715 | if (err && link && index != -1) { |
@@ -751,7 +760,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], | |||
751 | 760 | ||
752 | /* if this pq is also a promisc qp, it shouldn't be removed */ | 761 | /* if this pq is also a promisc qp, it shouldn't be removed */ |
753 | if (prot == MLX4_PROT_ETH && | 762 | if (prot == MLX4_PROT_ETH && |
754 | check_duplicate_entry(dev, 0, port, steer, index, qp->qpn)) | 763 | check_duplicate_entry(dev, port, steer, index, qp->qpn)) |
755 | goto out; | 764 | goto out; |
756 | 765 | ||
757 | members_count = be32_to_cpu(mgm->members_count) & 0xffffff; | 766 | members_count = be32_to_cpu(mgm->members_count) & 0xffffff; |
@@ -771,7 +780,8 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], | |||
771 | mgm->qp[i - 1] = 0; | 780 | mgm->qp[i - 1] = 0; |
772 | 781 | ||
773 | if (prot == MLX4_PROT_ETH) | 782 | if (prot == MLX4_PROT_ETH) |
774 | removed_entry = can_remove_steering_entry(dev, 0, port, steer, index, qp->qpn); | 783 | removed_entry = can_remove_steering_entry(dev, port, steer, |
784 | index, qp->qpn); | ||
775 | if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) { | 785 | if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) { |
776 | err = mlx4_WRITE_ENTRY(dev, index, mailbox); | 786 | err = mlx4_WRITE_ENTRY(dev, index, mailbox); |
777 | goto out; | 787 | goto out; |
@@ -830,6 +840,34 @@ out: | |||
830 | return err; | 840 | return err; |
831 | } | 841 | } |
832 | 842 | ||
843 | static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp, | ||
844 | u8 gid[16], u8 attach, u8 block_loopback, | ||
845 | enum mlx4_protocol prot) | ||
846 | { | ||
847 | struct mlx4_cmd_mailbox *mailbox; | ||
848 | int err = 0; | ||
849 | int qpn; | ||
850 | |||
851 | if (!mlx4_is_mfunc(dev)) | ||
852 | return -EBADF; | ||
853 | |||
854 | mailbox = mlx4_alloc_cmd_mailbox(dev); | ||
855 | if (IS_ERR(mailbox)) | ||
856 | return PTR_ERR(mailbox); | ||
857 | |||
858 | memcpy(mailbox->buf, gid, 16); | ||
859 | qpn = qp->qpn; | ||
860 | qpn |= (prot << 28); | ||
861 | if (attach && block_loopback) | ||
862 | qpn |= (1 << 31); | ||
863 | |||
864 | err = mlx4_cmd(dev, mailbox->dma, qpn, attach, | ||
865 | MLX4_CMD_QP_ATTACH, MLX4_CMD_TIME_CLASS_A, | ||
866 | MLX4_CMD_WRAPPED); | ||
867 | |||
868 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
869 | return err; | ||
870 | } | ||
833 | 871 | ||
834 | int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], | 872 | int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], |
835 | int block_mcast_loopback, enum mlx4_protocol prot) | 873 | int block_mcast_loopback, enum mlx4_protocol prot) |
@@ -845,9 +883,12 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], | |||
845 | if (prot == MLX4_PROT_ETH) | 883 | if (prot == MLX4_PROT_ETH) |
846 | gid[7] |= (steer << 1); | 884 | gid[7] |= (steer << 1); |
847 | 885 | ||
848 | return mlx4_qp_attach_common(dev, qp, gid, | 886 | if (mlx4_is_mfunc(dev)) |
849 | block_mcast_loopback, prot, | 887 | return mlx4_QP_ATTACH(dev, qp, gid, 1, |
850 | steer); | 888 | block_mcast_loopback, prot); |
889 | |||
890 | return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback, | ||
891 | prot, steer); | ||
851 | } | 892 | } |
852 | EXPORT_SYMBOL_GPL(mlx4_multicast_attach); | 893 | EXPORT_SYMBOL_GPL(mlx4_multicast_attach); |
853 | 894 | ||
@@ -862,22 +903,90 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], | |||
862 | !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) | 903 | !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) |
863 | return 0; | 904 | return 0; |
864 | 905 | ||
865 | if (prot == MLX4_PROT_ETH) { | 906 | if (prot == MLX4_PROT_ETH) |
866 | gid[7] |= (steer << 1); | 907 | gid[7] |= (steer << 1); |
867 | } | 908 | |
909 | if (mlx4_is_mfunc(dev)) | ||
910 | return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot); | ||
868 | 911 | ||
869 | return mlx4_qp_detach_common(dev, qp, gid, prot, steer); | 912 | return mlx4_qp_detach_common(dev, qp, gid, prot, steer); |
870 | } | 913 | } |
871 | EXPORT_SYMBOL_GPL(mlx4_multicast_detach); | 914 | EXPORT_SYMBOL_GPL(mlx4_multicast_detach); |
872 | 915 | ||
916 | static int mlx4_unicast_attach(struct mlx4_dev *dev, | ||
917 | struct mlx4_qp *qp, u8 gid[16], | ||
918 | int block_mcast_loopback, enum mlx4_protocol prot) | ||
919 | { | ||
920 | if (prot == MLX4_PROT_ETH && | ||
921 | !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) | ||
922 | return 0; | ||
923 | |||
924 | if (prot == MLX4_PROT_ETH) | ||
925 | gid[7] |= (MLX4_UC_STEER << 1); | ||
926 | |||
927 | if (mlx4_is_mfunc(dev)) | ||
928 | return mlx4_QP_ATTACH(dev, qp, gid, 1, | ||
929 | block_mcast_loopback, prot); | ||
930 | |||
931 | return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback, | ||
932 | prot, MLX4_UC_STEER); | ||
933 | } | ||
934 | EXPORT_SYMBOL_GPL(mlx4_unicast_attach); | ||
935 | |||
936 | static int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, | ||
937 | u8 gid[16], enum mlx4_protocol prot) | ||
938 | { | ||
939 | if (prot == MLX4_PROT_ETH && | ||
940 | !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) | ||
941 | return 0; | ||
942 | |||
943 | if (prot == MLX4_PROT_ETH) | ||
944 | gid[7] |= (MLX4_UC_STEER << 1); | ||
945 | |||
946 | if (mlx4_is_mfunc(dev)) | ||
947 | return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot); | ||
948 | |||
949 | return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_UC_STEER); | ||
950 | } | ||
951 | EXPORT_SYMBOL_GPL(mlx4_unicast_detach); | ||
952 | |||
953 | int mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave, | ||
954 | struct mlx4_vhcr *vhcr, | ||
955 | struct mlx4_cmd_mailbox *inbox, | ||
956 | struct mlx4_cmd_mailbox *outbox, | ||
957 | struct mlx4_cmd_info *cmd) | ||
958 | { | ||
959 | u32 qpn = (u32) vhcr->in_param & 0xffffffff; | ||
960 | u8 port = vhcr->in_param >> 62; | ||
961 | enum mlx4_steer_type steer = vhcr->in_modifier; | ||
962 | |||
963 | /* Promiscuous unicast is not allowed in mfunc */ | ||
964 | if (mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER) | ||
965 | return 0; | ||
966 | |||
967 | if (vhcr->op_modifier) | ||
968 | return add_promisc_qp(dev, port, steer, qpn); | ||
969 | else | ||
970 | return remove_promisc_qp(dev, port, steer, qpn); | ||
971 | } | ||
972 | |||
973 | static int mlx4_PROMISC(struct mlx4_dev *dev, u32 qpn, | ||
974 | enum mlx4_steer_type steer, u8 add, u8 port) | ||
975 | { | ||
976 | return mlx4_cmd(dev, (u64) qpn | (u64) port << 62, (u32) steer, add, | ||
977 | MLX4_CMD_PROMISC, MLX4_CMD_TIME_CLASS_A, | ||
978 | MLX4_CMD_WRAPPED); | ||
979 | } | ||
873 | 980 | ||
874 | int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) | 981 | int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) |
875 | { | 982 | { |
876 | if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) | 983 | if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) |
877 | return 0; | 984 | return 0; |
878 | 985 | ||
986 | if (mlx4_is_mfunc(dev)) | ||
987 | return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 1, port); | ||
879 | 988 | ||
880 | return add_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn); | 989 | return add_promisc_qp(dev, port, MLX4_MC_STEER, qpn); |
881 | } | 990 | } |
882 | EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add); | 991 | EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add); |
883 | 992 | ||
@@ -886,8 +995,10 @@ int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) | |||
886 | if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) | 995 | if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) |
887 | return 0; | 996 | return 0; |
888 | 997 | ||
998 | if (mlx4_is_mfunc(dev)) | ||
999 | return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 0, port); | ||
889 | 1000 | ||
890 | return remove_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn); | 1001 | return remove_promisc_qp(dev, port, MLX4_MC_STEER, qpn); |
891 | } | 1002 | } |
892 | EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove); | 1003 | EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove); |
893 | 1004 | ||
@@ -896,8 +1007,10 @@ int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) | |||
896 | if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) | 1007 | if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) |
897 | return 0; | 1008 | return 0; |
898 | 1009 | ||
1010 | if (mlx4_is_mfunc(dev)) | ||
1011 | return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 1, port); | ||
899 | 1012 | ||
900 | return add_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn); | 1013 | return add_promisc_qp(dev, port, MLX4_UC_STEER, qpn); |
901 | } | 1014 | } |
902 | EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add); | 1015 | EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add); |
903 | 1016 | ||
@@ -906,7 +1019,10 @@ int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) | |||
906 | if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) | 1019 | if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) |
907 | return 0; | 1020 | return 0; |
908 | 1021 | ||
909 | return remove_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn); | 1022 | if (mlx4_is_mfunc(dev)) |
1023 | return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 0, port); | ||
1024 | |||
1025 | return remove_promisc_qp(dev, port, MLX4_UC_STEER, qpn); | ||
910 | } | 1026 | } |
911 | EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove); | 1027 | EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove); |
912 | 1028 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 2488be8bb02..a38ffc99736 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -61,9 +61,9 @@ enum { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | enum { | 63 | enum { |
64 | MLX4_MGM_ENTRY_SIZE = 0x100, | 64 | MLX4_MAX_MGM_ENTRY_SIZE = 0x1000, |
65 | MLX4_QP_PER_MGM = 4 * (MLX4_MGM_ENTRY_SIZE / 16 - 2), | 65 | MLX4_MAX_QP_PER_MGM = 4 * (MLX4_MAX_MGM_ENTRY_SIZE / 16 - 2), |
66 | MLX4_MTT_ENTRY_PER_SEG = 8 | 66 | MLX4_MTT_ENTRY_PER_SEG = 8, |
67 | }; | 67 | }; |
68 | 68 | ||
69 | enum { | 69 | enum { |
@@ -190,6 +190,8 @@ do { \ | |||
190 | #define mlx4_warn(mdev, format, arg...) \ | 190 | #define mlx4_warn(mdev, format, arg...) \ |
191 | dev_warn(&mdev->pdev->dev, format, ##arg) | 191 | dev_warn(&mdev->pdev->dev, format, ##arg) |
192 | 192 | ||
193 | extern int mlx4_log_num_mgm_entry_size; | ||
194 | |||
193 | #define MLX4_MAX_NUM_SLAVES (MLX4_MAX_NUM_PF + MLX4_MAX_NUM_VF) | 195 | #define MLX4_MAX_NUM_SLAVES (MLX4_MAX_NUM_PF + MLX4_MAX_NUM_VF) |
194 | #define ALL_SLAVES 0xff | 196 | #define ALL_SLAVES 0xff |
195 | 197 | ||
@@ -417,9 +419,6 @@ struct mlx4_comm { | |||
417 | u32 slave_read; | 419 | u32 slave_read; |
418 | }; | 420 | }; |
419 | 421 | ||
420 | #define MGM_QPN_MASK 0x00FFFFFF | ||
421 | #define MGM_BLCK_LB_BIT 30 | ||
422 | |||
423 | #define VLAN_FLTR_SIZE 128 | 422 | #define VLAN_FLTR_SIZE 128 |
424 | 423 | ||
425 | struct mlx4_vlan_fltr { | 424 | struct mlx4_vlan_fltr { |
@@ -437,14 +436,6 @@ struct mlx4_steer_index { | |||
437 | struct list_head duplicates; | 436 | struct list_head duplicates; |
438 | }; | 437 | }; |
439 | 438 | ||
440 | struct mlx4_mgm { | ||
441 | __be32 next_gid_index; | ||
442 | __be32 members_count; | ||
443 | u32 reserved[2]; | ||
444 | u8 gid[16]; | ||
445 | __be32 qp[MLX4_QP_PER_MGM]; | ||
446 | }; | ||
447 | |||
448 | struct mlx4_slave_state { | 439 | struct mlx4_slave_state { |
449 | u8 comm_toggle; | 440 | u8 comm_toggle; |
450 | u8 last_cmd; | 441 | u8 last_cmd; |
@@ -1021,6 +1012,9 @@ int mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave, | |||
1021 | struct mlx4_cmd_mailbox *outbox, | 1012 | struct mlx4_cmd_mailbox *outbox, |
1022 | struct mlx4_cmd_info *cmd); | 1013 | struct mlx4_cmd_info *cmd); |
1023 | 1014 | ||
1015 | int mlx4_get_mgm_entry_size(struct mlx4_dev *dev); | ||
1016 | int mlx4_get_qp_per_mgm(struct mlx4_dev *dev); | ||
1017 | |||
1024 | static inline void set_param_l(u64 *arg, u32 val) | 1018 | static inline void set_param_l(u64 *arg, u32 val) |
1025 | { | 1019 | { |
1026 | *((u32 *)arg) = val; | 1020 | *((u32 *)arg) = val; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/profile.c b/drivers/net/ethernet/mellanox/mlx4/profile.c index b967647d0c7..771c4605ef8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/profile.c +++ b/drivers/net/ethernet/mellanox/mlx4/profile.c | |||
@@ -99,7 +99,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, | |||
99 | profile[MLX4_RES_DMPT].size = dev_cap->dmpt_entry_sz; | 99 | profile[MLX4_RES_DMPT].size = dev_cap->dmpt_entry_sz; |
100 | profile[MLX4_RES_CMPT].size = dev_cap->cmpt_entry_sz; | 100 | profile[MLX4_RES_CMPT].size = dev_cap->cmpt_entry_sz; |
101 | profile[MLX4_RES_MTT].size = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz; | 101 | profile[MLX4_RES_MTT].size = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz; |
102 | profile[MLX4_RES_MCG].size = MLX4_MGM_ENTRY_SIZE; | 102 | profile[MLX4_RES_MCG].size = mlx4_get_mgm_entry_size(dev); |
103 | 103 | ||
104 | profile[MLX4_RES_QP].num = request->num_qp; | 104 | profile[MLX4_RES_QP].num = request->num_qp; |
105 | profile[MLX4_RES_RDMARC].num = request->num_qp * request->rdmarc_per_qp; | 105 | profile[MLX4_RES_RDMARC].num = request->num_qp * request->rdmarc_per_qp; |
@@ -218,7 +218,8 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, | |||
218 | dev->caps.num_mgms = profile[i].num >> 1; | 218 | dev->caps.num_mgms = profile[i].num >> 1; |
219 | dev->caps.num_amgms = profile[i].num >> 1; | 219 | dev->caps.num_amgms = profile[i].num >> 1; |
220 | init_hca->mc_base = profile[i].start; | 220 | init_hca->mc_base = profile[i].start; |
221 | init_hca->log_mc_entry_sz = ilog2(MLX4_MGM_ENTRY_SIZE); | 221 | init_hca->log_mc_entry_sz = |
222 | ilog2(mlx4_get_mgm_entry_size(dev)); | ||
222 | init_hca->log_mc_table_sz = profile[i].log_num; | 223 | init_hca->log_mc_table_sz = profile[i].log_num; |
223 | init_hca->log_mc_hash_sz = profile[i].log_num - 1; | 224 | init_hca->log_mc_hash_sz = profile[i].log_num - 1; |
224 | break; | 225 | break; |