aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx4/qp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/qp.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/qp.c100
1 files changed, 92 insertions, 8 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index fb2b36759cbf..81e2abe07bbb 100644
--- a/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -67,10 +67,18 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type)
67 complete(&qp->free); 67 complete(&qp->free);
68} 68}
69 69
70static int is_qp0(struct mlx4_dev *dev, struct mlx4_qp *qp) 70/* used for INIT/CLOSE port logic */
71static int is_master_qp0(struct mlx4_dev *dev, struct mlx4_qp *qp, int *real_qp0, int *proxy_qp0)
71{ 72{
72 return qp->qpn >= dev->caps.sqp_start && 73 /* this procedure is called after we already know we are on the master */
73 qp->qpn <= dev->caps.sqp_start + 1; 74 /* qp0 is either the proxy qp0, or the real qp0 */
75 u32 pf_proxy_offset = dev->phys_caps.base_proxy_sqpn + 8 * mlx4_master_func_num(dev);
76 *proxy_qp0 = qp->qpn >= pf_proxy_offset && qp->qpn <= pf_proxy_offset + 1;
77
78 *real_qp0 = qp->qpn >= dev->phys_caps.base_sqpn &&
79 qp->qpn <= dev->phys_caps.base_sqpn + 1;
80
81 return *real_qp0 || *proxy_qp0;
74} 82}
75 83
76static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, 84static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
@@ -122,6 +130,8 @@ static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
122 struct mlx4_priv *priv = mlx4_priv(dev); 130 struct mlx4_priv *priv = mlx4_priv(dev);
123 struct mlx4_cmd_mailbox *mailbox; 131 struct mlx4_cmd_mailbox *mailbox;
124 int ret = 0; 132 int ret = 0;
133 int real_qp0 = 0;
134 int proxy_qp0 = 0;
125 u8 port; 135 u8 port;
126 136
127 if (cur_state >= MLX4_QP_NUM_STATE || new_state >= MLX4_QP_NUM_STATE || 137 if (cur_state >= MLX4_QP_NUM_STATE || new_state >= MLX4_QP_NUM_STATE ||
@@ -133,9 +143,12 @@ static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
133 MLX4_CMD_2RST_QP, MLX4_CMD_TIME_CLASS_A, native); 143 MLX4_CMD_2RST_QP, MLX4_CMD_TIME_CLASS_A, native);
134 if (mlx4_is_master(dev) && cur_state != MLX4_QP_STATE_ERR && 144 if (mlx4_is_master(dev) && cur_state != MLX4_QP_STATE_ERR &&
135 cur_state != MLX4_QP_STATE_RST && 145 cur_state != MLX4_QP_STATE_RST &&
136 is_qp0(dev, qp)) { 146 is_master_qp0(dev, qp, &real_qp0, &proxy_qp0)) {
137 port = (qp->qpn & 1) + 1; 147 port = (qp->qpn & 1) + 1;
138 priv->mfunc.master.qp0_state[port].qp0_active = 0; 148 if (proxy_qp0)
149 priv->mfunc.master.qp0_state[port].proxy_qp0_active = 0;
150 else
151 priv->mfunc.master.qp0_state[port].qp0_active = 0;
139 } 152 }
140 return ret; 153 return ret;
141 } 154 }
@@ -162,6 +175,23 @@ static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
162 new_state == MLX4_QP_STATE_RST ? 2 : 0, 175 new_state == MLX4_QP_STATE_RST ? 2 : 0,
163 op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C, native); 176 op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C, native);
164 177
178 if (mlx4_is_master(dev) && is_master_qp0(dev, qp, &real_qp0, &proxy_qp0)) {
179 port = (qp->qpn & 1) + 1;
180 if (cur_state != MLX4_QP_STATE_ERR &&
181 cur_state != MLX4_QP_STATE_RST &&
182 new_state == MLX4_QP_STATE_ERR) {
183 if (proxy_qp0)
184 priv->mfunc.master.qp0_state[port].proxy_qp0_active = 0;
185 else
186 priv->mfunc.master.qp0_state[port].qp0_active = 0;
187 } else if (new_state == MLX4_QP_STATE_RTR) {
188 if (proxy_qp0)
189 priv->mfunc.master.qp0_state[port].proxy_qp0_active = 1;
190 else
191 priv->mfunc.master.qp0_state[port].qp0_active = 1;
192 }
193 }
194
165 mlx4_free_cmd_mailbox(dev, mailbox); 195 mlx4_free_cmd_mailbox(dev, mailbox);
166 return ret; 196 return ret;
167} 197}
@@ -392,6 +422,7 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
392 struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; 422 struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
393 int err; 423 int err;
394 int reserved_from_top = 0; 424 int reserved_from_top = 0;
425 int k;
395 426
396 spin_lock_init(&qp_table->lock); 427 spin_lock_init(&qp_table->lock);
397 INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC); 428 INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC);
@@ -406,7 +437,7 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
406 * We also reserve the MSB of the 24-bit QP number to indicate 437 * We also reserve the MSB of the 24-bit QP number to indicate
407 * that a QP is an XRC QP. 438 * that a QP is an XRC QP.
408 */ 439 */
409 dev->caps.sqp_start = 440 dev->phys_caps.base_sqpn =
410 ALIGN(dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], 8); 441 ALIGN(dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW], 8);
411 442
412 { 443 {
@@ -437,13 +468,66 @@ int mlx4_init_qp_table(struct mlx4_dev *dev)
437 468
438 } 469 }
439 470
471 /* Reserve 8 real SQPs in both native and SRIOV modes.
472 * In addition, in SRIOV mode, reserve 8 proxy SQPs per function
473 * (for all PFs and VFs), and 8 corresponding tunnel QPs.
474 * Each proxy SQP works opposite its own tunnel QP.
475 *
476 * The QPs are arranged as follows:
477 * a. 8 real SQPs
478 * b. All the proxy SQPs (8 per function)
479 * c. All the tunnel QPs (8 per function)
480 */
481
440 err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps, 482 err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps,
441 (1 << 23) - 1, dev->caps.sqp_start + 8, 483 (1 << 23) - 1, dev->phys_caps.base_sqpn + 8 +
484 16 * MLX4_MFUNC_MAX * !!mlx4_is_master(dev),
442 reserved_from_top); 485 reserved_from_top);
443 if (err) 486 if (err)
444 return err; 487 return err;
445 488
446 return mlx4_CONF_SPECIAL_QP(dev, dev->caps.sqp_start); 489 if (mlx4_is_mfunc(dev)) {
490 /* for PPF use */
491 dev->phys_caps.base_proxy_sqpn = dev->phys_caps.base_sqpn + 8;
492 dev->phys_caps.base_tunnel_sqpn = dev->phys_caps.base_sqpn + 8 + 8 * MLX4_MFUNC_MAX;
493
494 /* In mfunc, calculate proxy and tunnel qp offsets for the PF here,
495 * since the PF does not call mlx4_slave_caps */
496 dev->caps.qp0_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
497 dev->caps.qp0_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
498 dev->caps.qp1_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
499 dev->caps.qp1_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
500
501 if (!dev->caps.qp0_tunnel || !dev->caps.qp0_proxy ||
502 !dev->caps.qp1_tunnel || !dev->caps.qp1_proxy) {
503 err = -ENOMEM;
504 goto err_mem;
505 }
506
507 for (k = 0; k < dev->caps.num_ports; k++) {
508 dev->caps.qp0_proxy[k] = dev->phys_caps.base_proxy_sqpn +
509 8 * mlx4_master_func_num(dev) + k;
510 dev->caps.qp0_tunnel[k] = dev->caps.qp0_proxy[k] + 8 * MLX4_MFUNC_MAX;
511 dev->caps.qp1_proxy[k] = dev->phys_caps.base_proxy_sqpn +
512 8 * mlx4_master_func_num(dev) + MLX4_MAX_PORTS + k;
513 dev->caps.qp1_tunnel[k] = dev->caps.qp1_proxy[k] + 8 * MLX4_MFUNC_MAX;
514 }
515 }
516
517
518 err = mlx4_CONF_SPECIAL_QP(dev, dev->phys_caps.base_sqpn);
519 if (err)
520 goto err_mem;
521 return 0;
522
523err_mem:
524 kfree(dev->caps.qp0_tunnel);
525 kfree(dev->caps.qp0_proxy);
526 kfree(dev->caps.qp1_tunnel);
527 kfree(dev->caps.qp1_proxy);
528 dev->caps.qp0_tunnel = dev->caps.qp0_proxy =
529 dev->caps.qp1_tunnel = dev->caps.qp1_proxy = NULL;
530 return err;
447} 531}
448 532
449void mlx4_cleanup_qp_table(struct mlx4_dev *dev) 533void mlx4_cleanup_qp_table(struct mlx4_dev *dev)