diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/qp.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/qp.c | 100 |
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 | ||
70 | static int is_qp0(struct mlx4_dev *dev, struct mlx4_qp *qp) | 70 | /* used for INIT/CLOSE port logic */ |
71 | static 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 | ||
76 | static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, | 84 | static 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 | |||
523 | err_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 | ||
449 | void mlx4_cleanup_qp_table(struct mlx4_dev *dev) | 533 | void mlx4_cleanup_qp_table(struct mlx4_dev *dev) |