Add support to change the link state of VF (vPort)
Unified · Split
| @@ -39,6 +39,7 @@ · 38 unmodified lines | ||
| 39 | 39 | #include <linux/errno.h> |
| 40 | 40 | |
| 41 | 41 | #include <linux/mlx4/cmd.h> |
| 42 | +#include <linux/mlx4/device.h> | |
| 42 | 43 | #include <linux/semaphore.h> |
| 43 | 44 | #include <rdma/ib_smi.h> |
| 44 | 45 | |
| @@ -2178,7 +2179,54 @@ int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_in · 2133 unmodified lines | ||
| 2178 | 2179 | ivf->qos = s_info->default_qos; |
| 2179 | 2180 | ivf->tx_rate = s_info->tx_rate; |
| 2180 | 2181 | ivf->spoofchk = s_info->spoofchk; |
| 2182 | + ivf->linkstate = s_info->link_state; | |
| 2181 | 2183 | |
| 2182 | 2184 | return 0; |
| 2183 | 2185 | } |
| 2184 | 2186 | EXPORT_SYMBOL_GPL(mlx4_get_vf_config); |
| 2187 | + | |
| 2188 | +int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state) | |
| 2189 | +{ | |
| 2190 | + struct mlx4_priv *priv = mlx4_priv(dev); | |
| 2191 | + struct mlx4_vport_state *s_info; | |
| 2192 | + struct mlx4_vport_oper_state *vp_oper; | |
| 2193 | + int slave; | |
| 2194 | + u8 link_stat_event; | |
| 2195 | + | |
| 2196 | + slave = mlx4_get_slave_indx(dev, vf); | |
| 2197 | + if (slave < 0) | |
| 2198 | + return -EINVAL; | |
| 2199 | + | |
| 2200 | + switch (link_state) { | |
| 2201 | + case IFLA_VF_LINK_STATE_AUTO: | |
| 2202 | + /* get current link state */ | |
| 2203 | + if (!priv->sense.do_sense_port[port]) | |
| 2204 | + link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE; | |
| 2205 | + else | |
| 2206 | + link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN; | |
| 2207 | + break; | |
| 2208 | + | |
| 2209 | + case IFLA_VF_LINK_STATE_ENABLE: | |
| 2210 | + link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE; | |
| 2211 | + break; | |
| 2212 | + | |
| 2213 | + case IFLA_VF_LINK_STATE_DISABLE: | |
| 2214 | + link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN; | |
| 2215 | + break; | |
| 2216 | + | |
| 2217 | + default: | |
| 2218 | + mlx4_warn(dev, "unknown value for link_state %02x on slave %d port %d\n", | |
| 2219 | + link_state, slave, port); | |
| 2220 | + return -EINVAL; | |
| 2221 | + }; | |
| 2222 | + /* update the admin & oper state on the link state */ | |
| 2223 | + s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; | |
| 2224 | + vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; | |
| 2225 | + s_info->link_state = link_state; | |
| 2226 | + vp_oper->state.link_state = link_state; | |
| 2227 | + | |
| 2228 | + /* send event */ | |
| 2229 | + mlx4_gen_port_state_change_eqe(dev, slave, port, link_stat_event); | |
| 2230 | + return 0; | |
| 2231 | +} | |
| 2232 | +EXPORT_SYMBOL_GPL(mlx4_set_vf_link_state); | |
| @@ -2061,6 +2061,13 @@ static int mlx4_en_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_ · 2060 unmodified lines | ||
| 2061 | 2061 | return mlx4_get_vf_config(mdev->dev, en_priv->port, vf, ivf); |
| 2062 | 2062 | } |
| 2063 | 2063 | |
| 2064 | +static int mlx4_en_set_vf_link_state(struct net_device *dev, int vf, int link_state) | |
| 2065 | +{ | |
| 2066 | + struct mlx4_en_priv *en_priv = netdev_priv(dev); | |
| 2067 | + struct mlx4_en_dev *mdev = en_priv->mdev; | |
| 2068 | + | |
| 2069 | + return mlx4_set_vf_link_state(mdev->dev, en_priv->port, vf, link_state); | |
| 2070 | +} | |
| 2064 | 2071 | static const struct net_device_ops mlx4_netdev_ops = { |
| 2065 | 2072 | .ndo_open = mlx4_en_open, |
| 2066 | 2073 | .ndo_stop = mlx4_en_close, |
| @@ -2101,6 +2108,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = { · 34 unmodified lines | ||
| 2101 | 2108 | .ndo_set_vf_mac = mlx4_en_set_vf_mac, |
| 2102 | 2109 | .ndo_set_vf_vlan = mlx4_en_set_vf_vlan, |
| 2103 | 2110 | .ndo_set_vf_spoofchk = mlx4_en_set_vf_spoofchk, |
| 2111 | + .ndo_set_vf_link_state = mlx4_en_set_vf_link_state, | |
| 2104 | 2112 | .ndo_get_vf_config = mlx4_en_get_vf_config, |
| 2105 | 2113 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 2106 | 2114 | .ndo_poll_controller = mlx4_en_netpoll, |
| @@ -448,6 +448,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) · 447 unmodified lines | ||
| 448 | 448 | int i; |
| 449 | 449 | enum slave_port_gen_event gen_event; |
| 450 | 450 | unsigned long flags; |
| 451 | + struct mlx4_vport_state *s_info; | |
| 451 | 452 | |
| 452 | 453 | while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor))) { |
| 453 | 454 | /* |
| @@ -556,7 +557,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) · 102 unmodified lines | ||
| 556 | 557 | mlx4_dbg(dev, "%s: Sending MLX4_PORT_CHANGE_SUBTYPE_DOWN" |
| 557 | 558 | " to slave: %d, port:%d\n", |
| 558 | 559 | __func__, i, port); |
| 559 | − mlx4_slave_event(dev, i, eqe); | |
| 560 | + s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state; | |
| 561 | + if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) | |
| 562 | + mlx4_slave_event(dev, i, eqe); | |
| 560 | 563 | } else { /* IB port */ |
| 561 | 564 | set_and_calc_slave_port_state(dev, i, port, |
| 562 | 565 | MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN, |
| @@ -580,7 +583,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) · 17 unmodified lines | ||
| 580 | 583 | for (i = 0; i < dev->num_slaves; i++) { |
| 581 | 584 | if (i == mlx4_master_func_num(dev)) |
| 582 | 585 | continue; |
| 583 | − mlx4_slave_event(dev, i, eqe); | |
| 586 | + s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state; | |
| 587 | + if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) | |
| 588 | + mlx4_slave_event(dev, i, eqe); | |
| 584 | 589 | } |
| 585 | 590 | else /* IB port */ |
| 586 | 591 | /* port-up event will be sent to a slave when the |
| @@ -830,8 +830,10 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, · 829 unmodified lines | ||
| 830 | 830 | u8 port_type; |
| 831 | 831 | u16 short_field; |
| 832 | 832 | int err; |
| 833 | + int admin_link_state; | |
| 833 | 834 | |
| 834 | 835 | #define MLX4_VF_PORT_NO_LINK_SENSE_MASK 0xE0 |
| 836 | +#define MLX4_PORT_LINK_UP_MASK 0x80 | |
| 835 | 837 | #define QUERY_PORT_CUR_MAX_PKEY_OFFSET 0x0c |
| 836 | 838 | #define QUERY_PORT_CUR_MAX_GID_OFFSET 0x0e |
| 837 | 839 | |
| @@ -861,6 +863,12 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, · 23 unmodified lines | ||
| 861 | 863 | /* set port type to currently operating port type */ |
| 862 | 864 | port_type |= (dev->caps.port_type[vhcr->in_modifier] & 0x3); |
| 863 | 865 | |
| 866 | + admin_link_state = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.link_state; | |
| 867 | + if (IFLA_VF_LINK_STATE_ENABLE == admin_link_state) | |
| 868 | + port_type |= MLX4_PORT_LINK_UP_MASK; | |
| 869 | + else if (IFLA_VF_LINK_STATE_DISABLE == admin_link_state) | |
| 870 | + port_type &= ~MLX4_PORT_LINK_UP_MASK; | |
| 871 | + | |
| 864 | 872 | MLX4_PUT(outbox->buf, port_type, |
| 865 | 873 | QUERY_PORT_SUPPORTED_TYPE_OFFSET); |
| 866 | 874 | |
| @@ -482,6 +482,7 @@ struct mlx4_vport_state { · 481 unmodified lines | ||
| 482 | 482 | u8 default_qos; |
| 483 | 483 | u32 tx_rate; |
| 484 | 484 | bool spoofchk; |
| 485 | + u32 link_state; | |
| 485 | 486 | }; |
| 486 | 487 | |
| 487 | 488 | struct mlx4_vf_admin_state { |
| @@ -237,7 +237,7 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac); · 236 unmodified lines | ||
| 237 | 237 | int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos); |
| 238 | 238 | int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting); |
| 239 | 239 | int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_info *ivf); |
| 240 | − | |
| 240 | +int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state); | |
| 241 | 241 | |
| 242 | 242 | #define MLX4_COMM_GET_IF_REV(cmd_chan_ver) (u8)((cmd_chan_ver) >> 8) |
| 243 | 243 | |