diff options
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 22 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/eq.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 45 |
3 files changed, 47 insertions, 22 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 995d4b6d5c1e..f278b10ef714 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
| @@ -1637,6 +1637,17 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) | |||
| 1637 | /* Flush multicast filter */ | 1637 | /* Flush multicast filter */ |
| 1638 | mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG); | 1638 | mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG); |
| 1639 | 1639 | ||
| 1640 | /* Remove flow steering rules for the port*/ | ||
| 1641 | if (mdev->dev->caps.steering_mode == | ||
| 1642 | MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
| 1643 | ASSERT_RTNL(); | ||
| 1644 | list_for_each_entry_safe(flow, tmp_flow, | ||
| 1645 | &priv->ethtool_list, list) { | ||
| 1646 | mlx4_flow_detach(mdev->dev, flow->id); | ||
| 1647 | list_del(&flow->list); | ||
| 1648 | } | ||
| 1649 | } | ||
| 1650 | |||
| 1640 | mlx4_en_destroy_drop_qp(priv); | 1651 | mlx4_en_destroy_drop_qp(priv); |
| 1641 | 1652 | ||
| 1642 | /* Free TX Rings */ | 1653 | /* Free TX Rings */ |
| @@ -1657,17 +1668,6 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) | |||
| 1657 | if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN)) | 1668 | if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN)) |
| 1658 | mdev->mac_removed[priv->port] = 1; | 1669 | mdev->mac_removed[priv->port] = 1; |
| 1659 | 1670 | ||
| 1660 | /* Remove flow steering rules for the port*/ | ||
| 1661 | if (mdev->dev->caps.steering_mode == | ||
| 1662 | MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
| 1663 | ASSERT_RTNL(); | ||
| 1664 | list_for_each_entry_safe(flow, tmp_flow, | ||
| 1665 | &priv->ethtool_list, list) { | ||
| 1666 | mlx4_flow_detach(mdev->dev, flow->id); | ||
| 1667 | list_del(&flow->list); | ||
| 1668 | } | ||
| 1669 | } | ||
| 1670 | |||
| 1671 | /* Free RX Rings */ | 1671 | /* Free RX Rings */ |
| 1672 | for (i = 0; i < priv->rx_ring_num; i++) { | 1672 | for (i = 0; i < priv->rx_ring_num; i++) { |
| 1673 | mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); | 1673 | mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 251ae2f93116..8e3123a1df88 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c | |||
| @@ -771,7 +771,7 @@ int mlx4_MAP_EQ_wrapper(struct mlx4_dev *dev, int slave, | |||
| 771 | struct mlx4_slave_event_eq_info *event_eq = | 771 | struct mlx4_slave_event_eq_info *event_eq = |
| 772 | priv->mfunc.master.slave_state[slave].event_eq; | 772 | priv->mfunc.master.slave_state[slave].event_eq; |
| 773 | u32 in_modifier = vhcr->in_modifier; | 773 | u32 in_modifier = vhcr->in_modifier; |
| 774 | u32 eqn = in_modifier & 0x1FF; | 774 | u32 eqn = in_modifier & 0x3FF; |
| 775 | u64 in_param = vhcr->in_param; | 775 | u64 in_param = vhcr->in_param; |
| 776 | int err = 0; | 776 | int err = 0; |
| 777 | int i; | 777 | int i; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 2995687f1aee..1391b52f443a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
| @@ -99,6 +99,7 @@ struct res_qp { | |||
| 99 | struct list_head mcg_list; | 99 | struct list_head mcg_list; |
| 100 | spinlock_t mcg_spl; | 100 | spinlock_t mcg_spl; |
| 101 | int local_qpn; | 101 | int local_qpn; |
| 102 | atomic_t ref_count; | ||
| 102 | }; | 103 | }; |
| 103 | 104 | ||
| 104 | enum res_mtt_states { | 105 | enum res_mtt_states { |
| @@ -197,6 +198,7 @@ enum res_fs_rule_states { | |||
| 197 | 198 | ||
| 198 | struct res_fs_rule { | 199 | struct res_fs_rule { |
| 199 | struct res_common com; | 200 | struct res_common com; |
| 201 | int qpn; | ||
| 200 | }; | 202 | }; |
| 201 | 203 | ||
| 202 | static void *res_tracker_lookup(struct rb_root *root, u64 res_id) | 204 | static void *res_tracker_lookup(struct rb_root *root, u64 res_id) |
| @@ -355,7 +357,7 @@ static int mpt_mask(struct mlx4_dev *dev) | |||
| 355 | return dev->caps.num_mpts - 1; | 357 | return dev->caps.num_mpts - 1; |
| 356 | } | 358 | } |
| 357 | 359 | ||
| 358 | static void *find_res(struct mlx4_dev *dev, int res_id, | 360 | static void *find_res(struct mlx4_dev *dev, u64 res_id, |
| 359 | enum mlx4_resource type) | 361 | enum mlx4_resource type) |
| 360 | { | 362 | { |
| 361 | struct mlx4_priv *priv = mlx4_priv(dev); | 363 | struct mlx4_priv *priv = mlx4_priv(dev); |
| @@ -447,6 +449,7 @@ static struct res_common *alloc_qp_tr(int id) | |||
| 447 | ret->local_qpn = id; | 449 | ret->local_qpn = id; |
| 448 | INIT_LIST_HEAD(&ret->mcg_list); | 450 | INIT_LIST_HEAD(&ret->mcg_list); |
| 449 | spin_lock_init(&ret->mcg_spl); | 451 | spin_lock_init(&ret->mcg_spl); |
| 452 | atomic_set(&ret->ref_count, 0); | ||
| 450 | 453 | ||
| 451 | return &ret->com; | 454 | return &ret->com; |
| 452 | } | 455 | } |
| @@ -554,7 +557,7 @@ static struct res_common *alloc_xrcdn_tr(int id) | |||
| 554 | return &ret->com; | 557 | return &ret->com; |
| 555 | } | 558 | } |
| 556 | 559 | ||
| 557 | static struct res_common *alloc_fs_rule_tr(u64 id) | 560 | static struct res_common *alloc_fs_rule_tr(u64 id, int qpn) |
| 558 | { | 561 | { |
| 559 | struct res_fs_rule *ret; | 562 | struct res_fs_rule *ret; |
| 560 | 563 | ||
| @@ -564,7 +567,7 @@ static struct res_common *alloc_fs_rule_tr(u64 id) | |||
| 564 | 567 | ||
| 565 | ret->com.res_id = id; | 568 | ret->com.res_id = id; |
| 566 | ret->com.state = RES_FS_RULE_ALLOCATED; | 569 | ret->com.state = RES_FS_RULE_ALLOCATED; |
| 567 | 570 | ret->qpn = qpn; | |
| 568 | return &ret->com; | 571 | return &ret->com; |
| 569 | } | 572 | } |
| 570 | 573 | ||
| @@ -602,7 +605,7 @@ static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave, | |||
| 602 | ret = alloc_xrcdn_tr(id); | 605 | ret = alloc_xrcdn_tr(id); |
| 603 | break; | 606 | break; |
| 604 | case RES_FS_RULE: | 607 | case RES_FS_RULE: |
| 605 | ret = alloc_fs_rule_tr(id); | 608 | ret = alloc_fs_rule_tr(id, extra); |
| 606 | break; | 609 | break; |
| 607 | default: | 610 | default: |
| 608 | return NULL; | 611 | return NULL; |
| @@ -671,10 +674,14 @@ undo: | |||
| 671 | 674 | ||
| 672 | static int remove_qp_ok(struct res_qp *res) | 675 | static int remove_qp_ok(struct res_qp *res) |
| 673 | { | 676 | { |
| 674 | if (res->com.state == RES_QP_BUSY) | 677 | if (res->com.state == RES_QP_BUSY || atomic_read(&res->ref_count) || |
| 678 | !list_empty(&res->mcg_list)) { | ||
| 679 | pr_err("resource tracker: fail to remove qp, state %d, ref_count %d\n", | ||
| 680 | res->com.state, atomic_read(&res->ref_count)); | ||
| 675 | return -EBUSY; | 681 | return -EBUSY; |
| 676 | else if (res->com.state != RES_QP_RESERVED) | 682 | } else if (res->com.state != RES_QP_RESERVED) { |
| 677 | return -EPERM; | 683 | return -EPERM; |
| 684 | } | ||
| 678 | 685 | ||
| 679 | return 0; | 686 | return 0; |
| 680 | } | 687 | } |
| @@ -3124,6 +3131,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
| 3124 | struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; | 3131 | struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; |
| 3125 | int err; | 3132 | int err; |
| 3126 | int qpn; | 3133 | int qpn; |
| 3134 | struct res_qp *rqp; | ||
| 3127 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; | 3135 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; |
| 3128 | struct _rule_hw *rule_header; | 3136 | struct _rule_hw *rule_header; |
| 3129 | int header_id; | 3137 | int header_id; |
| @@ -3134,7 +3142,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
| 3134 | 3142 | ||
| 3135 | ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; | 3143 | ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; |
| 3136 | qpn = be32_to_cpu(ctrl->qpn) & 0xffffff; | 3144 | qpn = be32_to_cpu(ctrl->qpn) & 0xffffff; |
| 3137 | err = get_res(dev, slave, qpn, RES_QP, NULL); | 3145 | err = get_res(dev, slave, qpn, RES_QP, &rqp); |
| 3138 | if (err) { | 3146 | if (err) { |
| 3139 | pr_err("Steering rule with qpn 0x%x rejected.\n", qpn); | 3147 | pr_err("Steering rule with qpn 0x%x rejected.\n", qpn); |
| 3140 | return err; | 3148 | return err; |
| @@ -3175,14 +3183,16 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
| 3175 | if (err) | 3183 | if (err) |
| 3176 | goto err_put; | 3184 | goto err_put; |
| 3177 | 3185 | ||
| 3178 | err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0); | 3186 | err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, qpn); |
| 3179 | if (err) { | 3187 | if (err) { |
| 3180 | mlx4_err(dev, "Fail to add flow steering resources.\n "); | 3188 | mlx4_err(dev, "Fail to add flow steering resources.\n "); |
| 3181 | /* detach rule*/ | 3189 | /* detach rule*/ |
| 3182 | mlx4_cmd(dev, vhcr->out_param, 0, 0, | 3190 | mlx4_cmd(dev, vhcr->out_param, 0, 0, |
| 3183 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, | 3191 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, |
| 3184 | MLX4_CMD_NATIVE); | 3192 | MLX4_CMD_NATIVE); |
| 3193 | goto err_put; | ||
| 3185 | } | 3194 | } |
| 3195 | atomic_inc(&rqp->ref_count); | ||
| 3186 | err_put: | 3196 | err_put: |
| 3187 | put_res(dev, slave, qpn, RES_QP); | 3197 | put_res(dev, slave, qpn, RES_QP); |
| 3188 | return err; | 3198 | return err; |
| @@ -3195,20 +3205,35 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave, | |||
| 3195 | struct mlx4_cmd_info *cmd) | 3205 | struct mlx4_cmd_info *cmd) |
| 3196 | { | 3206 | { |
| 3197 | int err; | 3207 | int err; |
| 3208 | struct res_qp *rqp; | ||
| 3209 | struct res_fs_rule *rrule; | ||
| 3198 | 3210 | ||
| 3199 | if (dev->caps.steering_mode != | 3211 | if (dev->caps.steering_mode != |
| 3200 | MLX4_STEERING_MODE_DEVICE_MANAGED) | 3212 | MLX4_STEERING_MODE_DEVICE_MANAGED) |
| 3201 | return -EOPNOTSUPP; | 3213 | return -EOPNOTSUPP; |
| 3202 | 3214 | ||
| 3215 | err = get_res(dev, slave, vhcr->in_param, RES_FS_RULE, &rrule); | ||
| 3216 | if (err) | ||
| 3217 | return err; | ||
| 3218 | /* Release the rule form busy state before removal */ | ||
| 3219 | put_res(dev, slave, vhcr->in_param, RES_FS_RULE); | ||
| 3220 | err = get_res(dev, slave, rrule->qpn, RES_QP, &rqp); | ||
| 3221 | if (err) | ||
| 3222 | return err; | ||
| 3223 | |||
| 3203 | err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0); | 3224 | err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0); |
| 3204 | if (err) { | 3225 | if (err) { |
| 3205 | mlx4_err(dev, "Fail to remove flow steering resources.\n "); | 3226 | mlx4_err(dev, "Fail to remove flow steering resources.\n "); |
| 3206 | return err; | 3227 | goto out; |
| 3207 | } | 3228 | } |
| 3208 | 3229 | ||
| 3209 | err = mlx4_cmd(dev, vhcr->in_param, 0, 0, | 3230 | err = mlx4_cmd(dev, vhcr->in_param, 0, 0, |
| 3210 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, | 3231 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, |
| 3211 | MLX4_CMD_NATIVE); | 3232 | MLX4_CMD_NATIVE); |
| 3233 | if (!err) | ||
| 3234 | atomic_dec(&rqp->ref_count); | ||
| 3235 | out: | ||
| 3236 | put_res(dev, slave, rrule->qpn, RES_QP); | ||
| 3212 | return err; | 3237 | return err; |
| 3213 | } | 3238 | } |
| 3214 | 3239 | ||
| @@ -3806,6 +3831,7 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) | |||
| 3806 | mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); | 3831 | mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); |
| 3807 | /*VLAN*/ | 3832 | /*VLAN*/ |
| 3808 | rem_slave_macs(dev, slave); | 3833 | rem_slave_macs(dev, slave); |
| 3834 | rem_slave_fs_rule(dev, slave); | ||
| 3809 | rem_slave_qps(dev, slave); | 3835 | rem_slave_qps(dev, slave); |
| 3810 | rem_slave_srqs(dev, slave); | 3836 | rem_slave_srqs(dev, slave); |
| 3811 | rem_slave_cqs(dev, slave); | 3837 | rem_slave_cqs(dev, slave); |
| @@ -3814,6 +3840,5 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) | |||
| 3814 | rem_slave_mtts(dev, slave); | 3840 | rem_slave_mtts(dev, slave); |
| 3815 | rem_slave_counters(dev, slave); | 3841 | rem_slave_counters(dev, slave); |
| 3816 | rem_slave_xrcdns(dev, slave); | 3842 | rem_slave_xrcdns(dev, slave); |
| 3817 | rem_slave_fs_rule(dev, slave); | ||
| 3818 | mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); | 3843 | mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); |
| 3819 | } | 3844 | } |
