diff options
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 62 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/mlx4_ib.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/qp.c | 1 |
3 files changed, 57 insertions, 7 deletions
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 3530c41fcd1f..8a3a2037b005 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -718,26 +718,53 @@ int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp, | |||
718 | return ret; | 718 | return ret; |
719 | } | 719 | } |
720 | 720 | ||
721 | struct mlx4_ib_steering { | ||
722 | struct list_head list; | ||
723 | u64 reg_id; | ||
724 | union ib_gid gid; | ||
725 | }; | ||
726 | |||
721 | static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | 727 | static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) |
722 | { | 728 | { |
723 | int err; | 729 | int err; |
724 | struct mlx4_ib_dev *mdev = to_mdev(ibqp->device); | 730 | struct mlx4_ib_dev *mdev = to_mdev(ibqp->device); |
725 | struct mlx4_ib_qp *mqp = to_mqp(ibqp); | 731 | struct mlx4_ib_qp *mqp = to_mqp(ibqp); |
732 | u64 reg_id; | ||
733 | struct mlx4_ib_steering *ib_steering = NULL; | ||
734 | |||
735 | if (mdev->dev->caps.steering_mode == | ||
736 | MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
737 | ib_steering = kmalloc(sizeof(*ib_steering), GFP_KERNEL); | ||
738 | if (!ib_steering) | ||
739 | return -ENOMEM; | ||
740 | } | ||
726 | 741 | ||
727 | err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, | 742 | err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, mqp->port, |
728 | !!(mqp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK), | 743 | !!(mqp->flags & |
729 | MLX4_PROT_IB_IPV6); | 744 | MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK), |
745 | MLX4_PROT_IB_IPV6, ®_id); | ||
730 | if (err) | 746 | if (err) |
731 | return err; | 747 | goto err_malloc; |
732 | 748 | ||
733 | err = add_gid_entry(ibqp, gid); | 749 | err = add_gid_entry(ibqp, gid); |
734 | if (err) | 750 | if (err) |
735 | goto err_add; | 751 | goto err_add; |
736 | 752 | ||
753 | if (ib_steering) { | ||
754 | memcpy(ib_steering->gid.raw, gid->raw, 16); | ||
755 | ib_steering->reg_id = reg_id; | ||
756 | mutex_lock(&mqp->mutex); | ||
757 | list_add(&ib_steering->list, &mqp->steering_rules); | ||
758 | mutex_unlock(&mqp->mutex); | ||
759 | } | ||
737 | return 0; | 760 | return 0; |
738 | 761 | ||
739 | err_add: | 762 | err_add: |
740 | mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6); | 763 | mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, |
764 | MLX4_PROT_IB_IPV6, reg_id); | ||
765 | err_malloc: | ||
766 | kfree(ib_steering); | ||
767 | |||
741 | return err; | 768 | return err; |
742 | } | 769 | } |
743 | 770 | ||
@@ -765,9 +792,30 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
765 | u8 mac[6]; | 792 | u8 mac[6]; |
766 | struct net_device *ndev; | 793 | struct net_device *ndev; |
767 | struct mlx4_ib_gid_entry *ge; | 794 | struct mlx4_ib_gid_entry *ge; |
795 | u64 reg_id = 0; | ||
796 | |||
797 | if (mdev->dev->caps.steering_mode == | ||
798 | MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
799 | struct mlx4_ib_steering *ib_steering; | ||
800 | |||
801 | mutex_lock(&mqp->mutex); | ||
802 | list_for_each_entry(ib_steering, &mqp->steering_rules, list) { | ||
803 | if (!memcmp(ib_steering->gid.raw, gid->raw, 16)) { | ||
804 | list_del(&ib_steering->list); | ||
805 | break; | ||
806 | } | ||
807 | } | ||
808 | mutex_unlock(&mqp->mutex); | ||
809 | if (&ib_steering->list == &mqp->steering_rules) { | ||
810 | pr_err("Couldn't find reg_id for mgid. Steering rule is left attached\n"); | ||
811 | return -EINVAL; | ||
812 | } | ||
813 | reg_id = ib_steering->reg_id; | ||
814 | kfree(ib_steering); | ||
815 | } | ||
768 | 816 | ||
769 | err = mlx4_multicast_detach(mdev->dev, | 817 | err = mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, |
770 | &mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6); | 818 | MLX4_PROT_IB_IPV6, reg_id); |
771 | if (err) | 819 | if (err) |
772 | return err; | 820 | return err; |
773 | 821 | ||
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index ff36655d23d3..42df4f7a6a5b 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h | |||
@@ -163,6 +163,7 @@ struct mlx4_ib_qp { | |||
163 | u8 state; | 163 | u8 state; |
164 | int mlx_type; | 164 | int mlx_type; |
165 | struct list_head gid_list; | 165 | struct list_head gid_list; |
166 | struct list_head steering_rules; | ||
166 | }; | 167 | }; |
167 | 168 | ||
168 | struct mlx4_ib_srq { | 169 | struct mlx4_ib_srq { |
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 8d4ed24aef93..6af19f6c2b11 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c | |||
@@ -495,6 +495,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, | |||
495 | spin_lock_init(&qp->sq.lock); | 495 | spin_lock_init(&qp->sq.lock); |
496 | spin_lock_init(&qp->rq.lock); | 496 | spin_lock_init(&qp->rq.lock); |
497 | INIT_LIST_HEAD(&qp->gid_list); | 497 | INIT_LIST_HEAD(&qp->gid_list); |
498 | INIT_LIST_HEAD(&qp->steering_rules); | ||
498 | 499 | ||
499 | qp->state = IB_QPS_RESET; | 500 | qp->state = IB_QPS_RESET; |
500 | if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) | 501 | if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) |