net/mlx4: Add set VF default vlan ID and priority support
[deliverable/linux.git] / drivers / net / ethernet / mellanox / mlx4 / resource_tracker.c
index 1391b52f443aa5489ec31ee7e155b087f0372b0c..5083d4babfe32a1822ac2bbb81e8e2fbfd386ac3 100644 (file)
@@ -75,6 +75,7 @@ struct res_gid {
        u8                      gid[16];
        enum mlx4_protocol      prot;
        enum mlx4_steer_type    steer;
+       u64                     reg_id;
 };
 
 enum res_qp_states {
@@ -352,6 +353,39 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
        }
 }
 
+static int update_vport_qp_param(struct mlx4_dev *dev,
+                                struct mlx4_cmd_mailbox *inbox,
+                                u8 slave)
+{
+       struct mlx4_qp_context  *qpc = inbox->buf + 8;
+       struct mlx4_vport_oper_state *vp_oper;
+       struct mlx4_priv *priv;
+       u32 qp_type;
+       int port;
+
+       port = (qpc->pri_path.sched_queue & 0x40) ? 2 : 1;
+       priv = mlx4_priv(dev);
+       vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
+
+       if (MLX4_VGT != vp_oper->state.default_vlan) {
+               qp_type = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
+               if (MLX4_QP_ST_RC == qp_type)
+                       return -EINVAL;
+
+               qpc->pri_path.vlan_index = vp_oper->vlan_idx;
+               qpc->pri_path.fl = (1 << 6) | (1 << 2); /* set cv bit and hide_cqe_vlan bit*/
+               qpc->pri_path.feup |= 1 << 3; /* set fvl bit */
+               qpc->pri_path.sched_queue &= 0xC7;
+               qpc->pri_path.sched_queue |= (vp_oper->state.default_qos) << 3;
+               mlx4_dbg(dev, "qp %d  port %d Q 0x%x set vlan to %d vidx %d feup %x fl %x\n",
+                        be32_to_cpu(qpc->local_qpn) & 0xffffff, port,
+                        (int)(qpc->pri_path.sched_queue), vp_oper->state.default_vlan,
+                        vp_oper->vlan_idx, (int)(qpc->pri_path.feup),
+                        (int)(qpc->pri_path.fl));
+       }
+       return 0;
+}
+
 static int mpt_mask(struct mlx4_dev *dev)
 {
        return dev->caps.num_mpts - 1;
@@ -2797,6 +2831,9 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
        update_pkey_index(dev, slave, inbox);
        update_gid(dev, inbox, (u8)slave);
        adjust_proxy_tun_qkey(dev, vhcr, qpc);
+       err = update_vport_qp_param(dev, inbox, slave);
+       if (err)
+               return err;
 
        return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
 }
@@ -2934,7 +2971,7 @@ static struct res_gid *find_gid(struct mlx4_dev *dev, int slave,
 
 static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
                       u8 *gid, enum mlx4_protocol prot,
-                      enum mlx4_steer_type steer)
+                      enum mlx4_steer_type steer, u64 reg_id)
 {
        struct res_gid *res;
        int err;
@@ -2951,6 +2988,7 @@ static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
                memcpy(res->gid, gid, 16);
                res->prot = prot;
                res->steer = steer;
+               res->reg_id = reg_id;
                list_add_tail(&res->list, &rqp->mcg_list);
                err = 0;
        }
@@ -2961,7 +2999,7 @@ static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
 
 static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
                       u8 *gid, enum mlx4_protocol prot,
-                      enum mlx4_steer_type steer)
+                      enum mlx4_steer_type steer, u64 *reg_id)
 {
        struct res_gid *res;
        int err;
@@ -2971,6 +3009,7 @@ static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
        if (!res || res->prot != prot || res->steer != steer)
                err = -EINVAL;
        else {
+               *reg_id = res->reg_id;
                list_del(&res->list);
                kfree(res);
                err = 0;
@@ -2980,6 +3019,37 @@ static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
        return err;
 }
 
+static int qp_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+                    int block_loopback, enum mlx4_protocol prot,
+                    enum mlx4_steer_type type, u64 *reg_id)
+{
+       switch (dev->caps.steering_mode) {
+       case MLX4_STEERING_MODE_DEVICE_MANAGED:
+               return mlx4_trans_to_dmfs_attach(dev, qp, gid, gid[5],
+                                               block_loopback, prot,
+                                               reg_id);
+       case MLX4_STEERING_MODE_B0:
+               return mlx4_qp_attach_common(dev, qp, gid,
+                                           block_loopback, prot, type);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int qp_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+                    enum mlx4_protocol prot, enum mlx4_steer_type type,
+                    u64 reg_id)
+{
+       switch (dev->caps.steering_mode) {
+       case MLX4_STEERING_MODE_DEVICE_MANAGED:
+               return mlx4_flow_detach(dev, reg_id);
+       case MLX4_STEERING_MODE_B0:
+               return mlx4_qp_detach_common(dev, qp, gid, prot, type);
+       default:
+               return -EINVAL;
+       }
+}
+
 int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                               struct mlx4_vhcr *vhcr,
                               struct mlx4_cmd_mailbox *inbox,
@@ -2992,14 +3062,12 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
        int err;
        int qpn;
        struct res_qp *rqp;
+       u64 reg_id = 0;
        int attach = vhcr->op_modifier;
        int block_loopback = vhcr->in_modifier >> 31;
        u8 steer_type_mask = 2;
        enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1;
 
-       if (dev->caps.steering_mode != MLX4_STEERING_MODE_B0)
-               return -EINVAL;
-
        qpn = vhcr->in_modifier & 0xffffff;
        err = get_res(dev, slave, qpn, RES_QP, &rqp);
        if (err)
@@ -3007,30 +3075,32 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
 
        qp.qpn = qpn;
        if (attach) {
-               err = add_mcg_res(dev, slave, rqp, gid, prot, type);
-               if (err)
+               err = qp_attach(dev, &qp, gid, block_loopback, prot,
+                               type, &reg_id);
+               if (err) {
+                       pr_err("Fail to attach rule to qp 0x%x\n", qpn);
                        goto ex_put;
-
-               err = mlx4_qp_attach_common(dev, &qp, gid,
-                                           block_loopback, prot, type);
+               }
+               err = add_mcg_res(dev, slave, rqp, gid, prot, type, reg_id);
                if (err)
-                       goto ex_rem;
+                       goto ex_detach;
        } else {
-               err = rem_mcg_res(dev, slave, rqp, gid, prot, type);
+               err = rem_mcg_res(dev, slave, rqp, gid, prot, type, &reg_id);
                if (err)
                        goto ex_put;
-               err = mlx4_qp_detach_common(dev, &qp, gid, prot, type);
-       }
 
+               err = qp_detach(dev, &qp, gid, prot, type, reg_id);
+               if (err)
+                       pr_err("Fail to detach rule from qp 0x%x reg_id = 0x%llx\n",
+                              qpn, reg_id);
+       }
        put_res(dev, slave, qpn, RES_QP);
-       return 0;
+       return err;
 
-ex_rem:
-       /* ignore error return below, already in error */
-       (void) rem_mcg_res(dev, slave, rqp, gid, prot, type);
+ex_detach:
+       qp_detach(dev, &qp, gid, prot, type, reg_id);
 ex_put:
        put_res(dev, slave, qpn, RES_QP);
-
        return err;
 }
 
@@ -3266,9 +3336,16 @@ static void detach_qp(struct mlx4_dev *dev, int slave, struct res_qp *rqp)
        struct mlx4_qp qp; /* dummy for calling attach/detach */
 
        list_for_each_entry_safe(rgid, tmp, &rqp->mcg_list, list) {
-               qp.qpn = rqp->local_qpn;
-               (void) mlx4_qp_detach_common(dev, &qp, rgid->gid, rgid->prot,
-                                            rgid->steer);
+               switch (dev->caps.steering_mode) {
+               case MLX4_STEERING_MODE_DEVICE_MANAGED:
+                       mlx4_flow_detach(dev, rgid->reg_id);
+                       break;
+               case MLX4_STEERING_MODE_B0:
+                       qp.qpn = rqp->local_qpn;
+                       (void) mlx4_qp_detach_common(dev, &qp, rgid->gid,
+                                                    rgid->prot, rgid->steer);
+                       break;
+               }
                list_del(&rgid->list);
                kfree(rgid);
        }
This page took 0.028622 seconds and 5 git commands to generate.