aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/mlx4/main.c62
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h1
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c1
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
721struct mlx4_ib_steering {
722 struct list_head list;
723 u64 reg_id;
724 union ib_gid gid;
725};
726
721static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) 727static 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, &reg_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
739err_add: 762err_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);
765err_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
168struct mlx4_ib_srq { 169struct 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)