85
static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num,
86
enum mlx4_steer_type steer,
89
struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num];
90
struct mlx4_promisc_qp *pqp;
92
list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
101
* Add new entry to steering data structure.
102
* All promisc QPs should be added as well
104
static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
105
enum mlx4_steer_type steer,
106
unsigned int index, u32 qpn)
108
struct mlx4_steer *s_steer;
109
struct mlx4_cmd_mailbox *mailbox;
110
struct mlx4_mgm *mgm;
112
struct mlx4_steer_index *new_entry;
113
struct mlx4_promisc_qp *pqp;
114
struct mlx4_promisc_qp *dqp = NULL;
119
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
120
s_steer = &mlx4_priv(dev)->steer[pf_num];
121
new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL);
125
INIT_LIST_HEAD(&new_entry->duplicates);
126
new_entry->index = index;
127
list_add_tail(&new_entry->list, &s_steer->steer_entries[steer]);
129
/* If the given qpn is also a promisc qp,
130
* it should be inserted to duplicates list
132
pqp = get_promisc_qp(dev, pf_num, steer, qpn);
134
dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
140
list_add_tail(&dqp->list, &new_entry->duplicates);
143
/* if no promisc qps for this vep, we are done */
144
if (list_empty(&s_steer->promisc_qps[steer]))
147
/* now need to add all the promisc qps to the new
148
* steering entry, as they should also receive the packets
149
* destined to this address */
150
mailbox = mlx4_alloc_cmd_mailbox(dev);
151
if (IS_ERR(mailbox)) {
157
err = mlx4_READ_ENTRY(dev, index, mailbox);
161
members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
162
prot = be32_to_cpu(mgm->members_count) >> 30;
163
list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
164
/* don't add already existing qpn */
167
if (members_count == MLX4_QP_PER_MGM) {
174
mgm->qp[members_count++] = cpu_to_be32(pqp->qpn & MGM_QPN_MASK);
176
/* update the qps count and update the entry with all the promisc qps*/
177
mgm->members_count = cpu_to_be32(members_count | (prot << 30));
178
err = mlx4_WRITE_ENTRY(dev, index, mailbox);
181
mlx4_free_cmd_mailbox(dev, mailbox);
186
list_del(&dqp->list);
189
list_del(&new_entry->list);
194
/* update the data structures with existing steering entry */
195
static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
196
enum mlx4_steer_type steer,
197
unsigned int index, u32 qpn)
199
struct mlx4_steer *s_steer;
200
struct mlx4_steer_index *tmp_entry, *entry = NULL;
201
struct mlx4_promisc_qp *pqp;
202
struct mlx4_promisc_qp *dqp;
205
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
206
s_steer = &mlx4_priv(dev)->steer[pf_num];
208
pqp = get_promisc_qp(dev, pf_num, steer, qpn);
210
return 0; /* nothing to do */
212
list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) {
213
if (tmp_entry->index == index) {
218
if (unlikely(!entry)) {
219
mlx4_warn(dev, "Steering entry at index %x is not registered\n", index);
223
/* the given qpn is listed as a promisc qpn
224
* we need to add it as a duplicate to this entry
225
* for future references */
226
list_for_each_entry(dqp, &entry->duplicates, list) {
228
return 0; /* qp is already duplicated */
231
/* add the qp as a duplicate on this index */
232
dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
236
list_add_tail(&dqp->list, &entry->duplicates);
241
/* Check whether a qpn is a duplicate on steering entry
242
* If so, it should not be removed from mgm */
243
static bool check_duplicate_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
244
enum mlx4_steer_type steer,
245
unsigned int index, u32 qpn)
247
struct mlx4_steer *s_steer;
248
struct mlx4_steer_index *tmp_entry, *entry = NULL;
249
struct mlx4_promisc_qp *dqp, *tmp_dqp;
252
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
253
s_steer = &mlx4_priv(dev)->steer[pf_num];
255
/* if qp is not promisc, it cannot be duplicated */
256
if (!get_promisc_qp(dev, pf_num, steer, qpn))
259
/* The qp is promisc qp so it is a duplicate on this index
260
* Find the index entry, and remove the duplicate */
261
list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) {
262
if (tmp_entry->index == index) {
267
if (unlikely(!entry)) {
268
mlx4_warn(dev, "Steering entry for index %x is not registered\n", index);
271
list_for_each_entry_safe(dqp, tmp_dqp, &entry->duplicates, list) {
272
if (dqp->qpn == qpn) {
273
list_del(&dqp->list);
280
/* I a steering entry contains only promisc QPs, it can be removed. */
281
static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
282
enum mlx4_steer_type steer,
283
unsigned int index, u32 tqpn)
285
struct mlx4_steer *s_steer;
286
struct mlx4_cmd_mailbox *mailbox;
287
struct mlx4_mgm *mgm;
288
struct mlx4_steer_index *entry = NULL, *tmp_entry;
295
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
296
s_steer = &mlx4_priv(dev)->steer[pf_num];
298
mailbox = mlx4_alloc_cmd_mailbox(dev);
303
if (mlx4_READ_ENTRY(dev, index, mailbox))
305
members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
306
for (i = 0; i < members_count; i++) {
307
qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
308
if (!get_promisc_qp(dev, pf_num, steer, qpn) && qpn != tqpn) {
309
/* the qp is not promisc, the entry can't be removed */
313
/* All the qps currently registered for this entry are promiscuous,
314
* Checking for duplicates */
316
list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) {
317
if (entry->index == index) {
318
if (list_empty(&entry->duplicates)) {
319
list_del(&entry->list);
322
/* This entry contains duplicates so it shouldn't be removed */
330
mlx4_free_cmd_mailbox(dev, mailbox);
334
static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
335
enum mlx4_steer_type steer, u32 qpn)
337
struct mlx4_steer *s_steer;
338
struct mlx4_cmd_mailbox *mailbox;
339
struct mlx4_mgm *mgm;
340
struct mlx4_steer_index *entry;
341
struct mlx4_promisc_qp *pqp;
342
struct mlx4_promisc_qp *dqp;
350
struct mlx4_priv *priv = mlx4_priv(dev);
351
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
352
s_steer = &mlx4_priv(dev)->steer[pf_num];
354
mutex_lock(&priv->mcg_table.mutex);
356
if (get_promisc_qp(dev, pf_num, steer, qpn)) {
357
err = 0; /* Noting to do, already exists */
361
pqp = kmalloc(sizeof *pqp, GFP_KERNEL);
368
mailbox = mlx4_alloc_cmd_mailbox(dev);
369
if (IS_ERR(mailbox)) {
375
/* the promisc qp needs to be added for each one of the steering
376
* entries, if it already exists, needs to be added as a duplicate
378
list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
379
err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
383
members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
384
prot = be32_to_cpu(mgm->members_count) >> 30;
386
for (i = 0; i < members_count; i++) {
387
if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
388
/* Entry already exists, add to duplicates */
389
dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
393
list_add_tail(&dqp->list, &entry->duplicates);
398
/* Need to add the qpn to mgm */
399
if (members_count == MLX4_QP_PER_MGM) {
404
mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK);
405
mgm->members_count = cpu_to_be32(members_count | (prot << 30));
406
err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
410
last_index = entry->index;
413
/* add the new qpn to list of promisc qps */
414
list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
415
/* now need to add all the promisc qps to default entry */
416
memset(mgm, 0, sizeof *mgm);
418
list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
419
mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
420
mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
422
err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox);
426
mlx4_free_cmd_mailbox(dev, mailbox);
427
mutex_unlock(&priv->mcg_table.mutex);
431
list_del(&pqp->list);
433
mlx4_free_cmd_mailbox(dev, mailbox);
437
mutex_unlock(&priv->mcg_table.mutex);
441
static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
442
enum mlx4_steer_type steer, u32 qpn)
444
struct mlx4_priv *priv = mlx4_priv(dev);
445
struct mlx4_steer *s_steer;
446
struct mlx4_cmd_mailbox *mailbox;
447
struct mlx4_mgm *mgm;
448
struct mlx4_steer_index *entry;
449
struct mlx4_promisc_qp *pqp;
450
struct mlx4_promisc_qp *dqp;
453
bool back_to_list = false;
458
pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
459
s_steer = &mlx4_priv(dev)->steer[pf_num];
460
mutex_lock(&priv->mcg_table.mutex);
462
pqp = get_promisc_qp(dev, pf_num, steer, qpn);
463
if (unlikely(!pqp)) {
464
mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn);
470
/*remove from list of promisc qps */
471
list_del(&pqp->list);
473
/* set the default entry not to include the removed one */
474
mailbox = mlx4_alloc_cmd_mailbox(dev);
475
if (IS_ERR(mailbox)) {
482
list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
483
mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
484
mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
486
err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox);
490
/* remove the qp from all the steering entries*/
491
list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
493
list_for_each_entry(dqp, &entry->duplicates, list) {
494
if (dqp->qpn == qpn) {
500
/* a duplicate, no need to change the mgm,
501
* only update the duplicates list */
502
list_del(&dqp->list);
505
err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
508
members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
509
for (loc = -1, i = 0; i < members_count; ++i)
510
if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn)
513
mgm->members_count = cpu_to_be32(--members_count |
514
(MLX4_PROT_ETH << 30));
515
mgm->qp[loc] = mgm->qp[i - 1];
518
err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
526
mlx4_free_cmd_mailbox(dev, mailbox);
529
list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
533
mutex_unlock(&priv->mcg_table.mutex);
83
538
* Caller must hold MCG table semaphore. gid and mgm parameters must
84
539
* be properly aligned for command interface.
343
825
mlx4_free_cmd_mailbox(dev, mailbox);
830
int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
831
int block_mcast_loopback, enum mlx4_protocol prot)
833
enum mlx4_steer_type steer;
835
steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
837
if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
840
if (prot == MLX4_PROT_ETH)
841
gid[7] |= (steer << 1);
843
return mlx4_qp_attach_common(dev, qp, gid,
844
block_mcast_loopback, prot,
847
EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
849
int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
850
enum mlx4_protocol prot)
852
enum mlx4_steer_type steer;
854
steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
856
if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
859
if (prot == MLX4_PROT_ETH) {
860
gid[7] |= (steer << 1);
863
return mlx4_qp_detach_common(dev, qp, gid, prot, steer);
346
865
EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
868
int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
870
if (!dev->caps.vep_mc_steering)
874
return add_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn);
876
EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
878
int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
880
if (!dev->caps.vep_mc_steering)
884
return remove_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn);
886
EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
888
int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
890
if (!dev->caps.vep_mc_steering)
894
return add_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
896
EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
898
int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
900
if (!dev->caps.vep_mc_steering)
903
return remove_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
905
EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove);
348
907
int mlx4_init_mcg_table(struct mlx4_dev *dev)
350
909
struct mlx4_priv *priv = mlx4_priv(dev);