Merge branch 'mlx4'
Or Gerlitz says:
====================
This series adds support for the SRIOV ndo_set_vf callbacks to the mlx4 driver.
Series done against the net-next tree as of commit 37fe066098
"net:
fix address check in rtnl_fdb_del"
We have successfully tested the series on net-next, except for getting
the VF link info issue I have reported earlier today on netdev, we
see the problem for both ixgbe and mlx4 VFs. Just to make sure get
VF config is working OK with patch #6 - we have run it over 3.8.8 too.
We added to the V1 series two patches that disable HW timestamping
when running over a VF, as this isn't supported yet.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b38a54eaa0
|
@ -1490,6 +1490,69 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
|
||||||
|
{
|
||||||
|
int port, err;
|
||||||
|
struct mlx4_vport_state *vp_admin;
|
||||||
|
struct mlx4_vport_oper_state *vp_oper;
|
||||||
|
|
||||||
|
for (port = 1; port <= MLX4_MAX_PORTS; port++) {
|
||||||
|
vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
|
||||||
|
vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
|
||||||
|
vp_oper->state = *vp_admin;
|
||||||
|
if (MLX4_VGT != vp_admin->default_vlan) {
|
||||||
|
err = __mlx4_register_vlan(&priv->dev, port,
|
||||||
|
vp_admin->default_vlan, &(vp_oper->vlan_idx));
|
||||||
|
if (err) {
|
||||||
|
vp_oper->vlan_idx = NO_INDX;
|
||||||
|
mlx4_warn((&priv->dev),
|
||||||
|
"No vlan resorces slave %d, port %d\n",
|
||||||
|
slave, port);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
mlx4_dbg((&(priv->dev)), "alloc vlan %d idx %d slave %d port %d\n",
|
||||||
|
(int)(vp_oper->state.default_vlan),
|
||||||
|
vp_oper->vlan_idx, slave, port);
|
||||||
|
}
|
||||||
|
if (vp_admin->spoofchk) {
|
||||||
|
vp_oper->mac_idx = __mlx4_register_mac(&priv->dev,
|
||||||
|
port,
|
||||||
|
vp_admin->mac);
|
||||||
|
if (0 > vp_oper->mac_idx) {
|
||||||
|
err = vp_oper->mac_idx;
|
||||||
|
vp_oper->mac_idx = NO_INDX;
|
||||||
|
mlx4_warn((&priv->dev),
|
||||||
|
"No mac resorces slave %d, port %d\n",
|
||||||
|
slave, port);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
mlx4_dbg((&(priv->dev)), "alloc mac %llx idx %d slave %d port %d\n",
|
||||||
|
vp_oper->state.mac, vp_oper->mac_idx, slave, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mlx4_master_deactivate_admin_state(struct mlx4_priv *priv, int slave)
|
||||||
|
{
|
||||||
|
int port;
|
||||||
|
struct mlx4_vport_oper_state *vp_oper;
|
||||||
|
|
||||||
|
for (port = 1; port <= MLX4_MAX_PORTS; port++) {
|
||||||
|
vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
|
||||||
|
if (NO_INDX != vp_oper->vlan_idx) {
|
||||||
|
__mlx4_unregister_vlan(&priv->dev,
|
||||||
|
port, vp_oper->vlan_idx);
|
||||||
|
vp_oper->vlan_idx = NO_INDX;
|
||||||
|
}
|
||||||
|
if (NO_INDX != vp_oper->mac_idx) {
|
||||||
|
__mlx4_unregister_mac(&priv->dev, port, vp_oper->mac_idx);
|
||||||
|
vp_oper->mac_idx = NO_INDX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
|
static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
|
||||||
u16 param, u8 toggle)
|
u16 param, u8 toggle)
|
||||||
{
|
{
|
||||||
|
@ -1510,6 +1573,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
|
||||||
if (cmd == MLX4_COMM_CMD_RESET) {
|
if (cmd == MLX4_COMM_CMD_RESET) {
|
||||||
mlx4_warn(dev, "Received reset from slave:%d\n", slave);
|
mlx4_warn(dev, "Received reset from slave:%d\n", slave);
|
||||||
slave_state[slave].active = false;
|
slave_state[slave].active = false;
|
||||||
|
mlx4_master_deactivate_admin_state(priv, slave);
|
||||||
for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) {
|
for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) {
|
||||||
slave_state[slave].event_eq[i].eqn = -1;
|
slave_state[slave].event_eq[i].eqn = -1;
|
||||||
slave_state[slave].event_eq[i].token = 0;
|
slave_state[slave].event_eq[i].token = 0;
|
||||||
|
@ -1556,6 +1620,8 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
|
||||||
if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2)
|
if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2)
|
||||||
goto reset_slave;
|
goto reset_slave;
|
||||||
slave_state[slave].vhcr_dma |= param;
|
slave_state[slave].vhcr_dma |= param;
|
||||||
|
if (mlx4_master_activate_admin_state(priv, slave))
|
||||||
|
goto reset_slave;
|
||||||
slave_state[slave].active = true;
|
slave_state[slave].active = true;
|
||||||
mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_INIT, slave);
|
mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_INIT, slave);
|
||||||
break;
|
break;
|
||||||
|
@ -1732,6 +1798,18 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
|
||||||
if (!priv->mfunc.master.slave_state)
|
if (!priv->mfunc.master.slave_state)
|
||||||
goto err_comm;
|
goto err_comm;
|
||||||
|
|
||||||
|
priv->mfunc.master.vf_admin =
|
||||||
|
kzalloc(dev->num_slaves *
|
||||||
|
sizeof(struct mlx4_vf_admin_state), GFP_KERNEL);
|
||||||
|
if (!priv->mfunc.master.vf_admin)
|
||||||
|
goto err_comm_admin;
|
||||||
|
|
||||||
|
priv->mfunc.master.vf_oper =
|
||||||
|
kzalloc(dev->num_slaves *
|
||||||
|
sizeof(struct mlx4_vf_oper_state), GFP_KERNEL);
|
||||||
|
if (!priv->mfunc.master.vf_oper)
|
||||||
|
goto err_comm_oper;
|
||||||
|
|
||||||
for (i = 0; i < dev->num_slaves; ++i) {
|
for (i = 0; i < dev->num_slaves; ++i) {
|
||||||
s_state = &priv->mfunc.master.slave_state[i];
|
s_state = &priv->mfunc.master.slave_state[i];
|
||||||
s_state->last_cmd = MLX4_COMM_CMD_RESET;
|
s_state->last_cmd = MLX4_COMM_CMD_RESET;
|
||||||
|
@ -1752,6 +1830,10 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
|
||||||
goto err_slaves;
|
goto err_slaves;
|
||||||
}
|
}
|
||||||
INIT_LIST_HEAD(&s_state->mcast_filters[port]);
|
INIT_LIST_HEAD(&s_state->mcast_filters[port]);
|
||||||
|
priv->mfunc.master.vf_admin[i].vport[port].default_vlan = MLX4_VGT;
|
||||||
|
priv->mfunc.master.vf_oper[i].vport[port].state.default_vlan = MLX4_VGT;
|
||||||
|
priv->mfunc.master.vf_oper[i].vport[port].vlan_idx = NO_INDX;
|
||||||
|
priv->mfunc.master.vf_oper[i].vport[port].mac_idx = NO_INDX;
|
||||||
}
|
}
|
||||||
spin_lock_init(&s_state->lock);
|
spin_lock_init(&s_state->lock);
|
||||||
}
|
}
|
||||||
|
@ -1800,6 +1882,10 @@ err_slaves:
|
||||||
for (port = 1; port <= MLX4_MAX_PORTS; port++)
|
for (port = 1; port <= MLX4_MAX_PORTS; port++)
|
||||||
kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
|
kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
|
||||||
}
|
}
|
||||||
|
kfree(priv->mfunc.master.vf_oper);
|
||||||
|
err_comm_oper:
|
||||||
|
kfree(priv->mfunc.master.vf_admin);
|
||||||
|
err_comm_admin:
|
||||||
kfree(priv->mfunc.master.slave_state);
|
kfree(priv->mfunc.master.slave_state);
|
||||||
err_comm:
|
err_comm:
|
||||||
iounmap(priv->mfunc.comm);
|
iounmap(priv->mfunc.comm);
|
||||||
|
@ -1874,6 +1960,8 @@ void mlx4_multi_func_cleanup(struct mlx4_dev *dev)
|
||||||
kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
|
kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);
|
||||||
}
|
}
|
||||||
kfree(priv->mfunc.master.slave_state);
|
kfree(priv->mfunc.master.slave_state);
|
||||||
|
kfree(priv->mfunc.master.vf_admin);
|
||||||
|
kfree(priv->mfunc.master.vf_oper);
|
||||||
}
|
}
|
||||||
|
|
||||||
iounmap(priv->mfunc.comm);
|
iounmap(priv->mfunc.comm);
|
||||||
|
@ -1984,3 +2072,115 @@ u32 mlx4_comm_get_version(void)
|
||||||
{
|
{
|
||||||
return ((u32) CMD_CHAN_IF_REV << 8) | (u32) CMD_CHAN_VER;
|
return ((u32) CMD_CHAN_IF_REV << 8) | (u32) CMD_CHAN_VER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mlx4_get_slave_indx(struct mlx4_dev *dev, int vf)
|
||||||
|
{
|
||||||
|
if ((vf < 0) || (vf >= dev->num_vfs)) {
|
||||||
|
mlx4_err(dev, "Bad vf number:%d (number of activated vf: %d)\n", vf, dev->num_vfs);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vf+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac)
|
||||||
|
{
|
||||||
|
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||||
|
struct mlx4_vport_state *s_info;
|
||||||
|
int slave;
|
||||||
|
|
||||||
|
if (!mlx4_is_master(dev))
|
||||||
|
return -EPROTONOSUPPORT;
|
||||||
|
|
||||||
|
slave = mlx4_get_slave_indx(dev, vf);
|
||||||
|
if (slave < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
|
||||||
|
s_info->mac = mac;
|
||||||
|
mlx4_info(dev, "default mac on vf %d port %d to %llX will take afect only after vf restart\n",
|
||||||
|
vf, port, s_info->mac);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mlx4_set_vf_mac);
|
||||||
|
|
||||||
|
int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
|
||||||
|
{
|
||||||
|
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||||
|
struct mlx4_vport_state *s_info;
|
||||||
|
int slave;
|
||||||
|
|
||||||
|
if ((!mlx4_is_master(dev)) ||
|
||||||
|
!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL))
|
||||||
|
return -EPROTONOSUPPORT;
|
||||||
|
|
||||||
|
if ((vlan > 4095) || (qos > 7))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
slave = mlx4_get_slave_indx(dev, vf);
|
||||||
|
if (slave < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
|
||||||
|
if ((0 == vlan) && (0 == qos))
|
||||||
|
s_info->default_vlan = MLX4_VGT;
|
||||||
|
else
|
||||||
|
s_info->default_vlan = vlan;
|
||||||
|
s_info->default_qos = qos;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan);
|
||||||
|
|
||||||
|
int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting)
|
||||||
|
{
|
||||||
|
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||||
|
struct mlx4_vport_state *s_info;
|
||||||
|
int slave;
|
||||||
|
|
||||||
|
if ((!mlx4_is_master(dev)) ||
|
||||||
|
!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FSM))
|
||||||
|
return -EPROTONOSUPPORT;
|
||||||
|
|
||||||
|
slave = mlx4_get_slave_indx(dev, vf);
|
||||||
|
if (slave < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
|
||||||
|
s_info->spoofchk = setting;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mlx4_set_vf_spoofchk);
|
||||||
|
|
||||||
|
int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_info *ivf)
|
||||||
|
{
|
||||||
|
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||||
|
struct mlx4_vport_state *s_info;
|
||||||
|
int slave;
|
||||||
|
|
||||||
|
if (!mlx4_is_master(dev))
|
||||||
|
return -EPROTONOSUPPORT;
|
||||||
|
|
||||||
|
slave = mlx4_get_slave_indx(dev, vf);
|
||||||
|
if (slave < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
|
||||||
|
ivf->vf = vf;
|
||||||
|
|
||||||
|
/* need to convert it to a func */
|
||||||
|
ivf->mac[0] = ((s_info->mac >> (5*8)) & 0xff);
|
||||||
|
ivf->mac[1] = ((s_info->mac >> (4*8)) & 0xff);
|
||||||
|
ivf->mac[2] = ((s_info->mac >> (3*8)) & 0xff);
|
||||||
|
ivf->mac[3] = ((s_info->mac >> (2*8)) & 0xff);
|
||||||
|
ivf->mac[4] = ((s_info->mac >> (1*8)) & 0xff);
|
||||||
|
ivf->mac[5] = ((s_info->mac) & 0xff);
|
||||||
|
|
||||||
|
ivf->vlan = s_info->default_vlan;
|
||||||
|
ivf->qos = s_info->default_qos;
|
||||||
|
ivf->tx_rate = s_info->tx_rate;
|
||||||
|
ivf->spoofchk = s_info->spoofchk;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mlx4_get_vf_config);
|
||||||
|
|
|
@ -1373,6 +1373,7 @@ static void mlx4_en_service_task(struct work_struct *work)
|
||||||
|
|
||||||
mutex_lock(&mdev->state_lock);
|
mutex_lock(&mdev->state_lock);
|
||||||
if (mdev->device_up) {
|
if (mdev->device_up) {
|
||||||
|
if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
|
||||||
mlx4_en_ptp_overflow_check(mdev);
|
mlx4_en_ptp_overflow_check(mdev);
|
||||||
|
|
||||||
queue_delayed_work(mdev->workqueue, &priv->service_task,
|
queue_delayed_work(mdev->workqueue, &priv->service_task,
|
||||||
|
@ -2023,6 +2024,42 @@ static int mlx4_en_set_features(struct net_device *netdev,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mlx4_en_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
|
||||||
|
{
|
||||||
|
struct mlx4_en_priv *en_priv = netdev_priv(dev);
|
||||||
|
struct mlx4_en_dev *mdev = en_priv->mdev;
|
||||||
|
u64 mac_u64 = mlx4_en_mac_to_u64(mac);
|
||||||
|
|
||||||
|
if (!is_valid_ether_addr(mac))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return mlx4_set_vf_mac(mdev->dev, en_priv->port, queue, mac_u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mlx4_en_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos)
|
||||||
|
{
|
||||||
|
struct mlx4_en_priv *en_priv = netdev_priv(dev);
|
||||||
|
struct mlx4_en_dev *mdev = en_priv->mdev;
|
||||||
|
|
||||||
|
return mlx4_set_vf_vlan(mdev->dev, en_priv->port, vf, vlan, qos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mlx4_en_set_vf_spoofchk(struct net_device *dev, int vf, bool setting)
|
||||||
|
{
|
||||||
|
struct mlx4_en_priv *en_priv = netdev_priv(dev);
|
||||||
|
struct mlx4_en_dev *mdev = en_priv->mdev;
|
||||||
|
|
||||||
|
return mlx4_set_vf_spoofchk(mdev->dev, en_priv->port, vf, setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mlx4_en_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_info *ivf)
|
||||||
|
{
|
||||||
|
struct mlx4_en_priv *en_priv = netdev_priv(dev);
|
||||||
|
struct mlx4_en_dev *mdev = en_priv->mdev;
|
||||||
|
|
||||||
|
return mlx4_get_vf_config(mdev->dev, en_priv->port, vf, ivf);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct net_device_ops mlx4_netdev_ops = {
|
static const struct net_device_ops mlx4_netdev_ops = {
|
||||||
.ndo_open = mlx4_en_open,
|
.ndo_open = mlx4_en_open,
|
||||||
.ndo_stop = mlx4_en_close,
|
.ndo_stop = mlx4_en_close,
|
||||||
|
@ -2047,6 +2084,33 @@ static const struct net_device_ops mlx4_netdev_ops = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct net_device_ops mlx4_netdev_ops_master = {
|
||||||
|
.ndo_open = mlx4_en_open,
|
||||||
|
.ndo_stop = mlx4_en_close,
|
||||||
|
.ndo_start_xmit = mlx4_en_xmit,
|
||||||
|
.ndo_select_queue = mlx4_en_select_queue,
|
||||||
|
.ndo_get_stats = mlx4_en_get_stats,
|
||||||
|
.ndo_set_rx_mode = mlx4_en_set_rx_mode,
|
||||||
|
.ndo_set_mac_address = mlx4_en_set_mac,
|
||||||
|
.ndo_validate_addr = eth_validate_addr,
|
||||||
|
.ndo_change_mtu = mlx4_en_change_mtu,
|
||||||
|
.ndo_tx_timeout = mlx4_en_tx_timeout,
|
||||||
|
.ndo_vlan_rx_add_vid = mlx4_en_vlan_rx_add_vid,
|
||||||
|
.ndo_vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid,
|
||||||
|
.ndo_set_vf_mac = mlx4_en_set_vf_mac,
|
||||||
|
.ndo_set_vf_vlan = mlx4_en_set_vf_vlan,
|
||||||
|
.ndo_set_vf_spoofchk = mlx4_en_set_vf_spoofchk,
|
||||||
|
.ndo_get_vf_config = mlx4_en_get_vf_config,
|
||||||
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||||
|
.ndo_poll_controller = mlx4_en_netpoll,
|
||||||
|
#endif
|
||||||
|
.ndo_set_features = mlx4_en_set_features,
|
||||||
|
.ndo_setup_tc = mlx4_en_setup_tc,
|
||||||
|
#ifdef CONFIG_RFS_ACCEL
|
||||||
|
.ndo_rx_flow_steer = mlx4_en_filter_rfs,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
|
int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
|
||||||
struct mlx4_en_port_profile *prof)
|
struct mlx4_en_port_profile *prof)
|
||||||
{
|
{
|
||||||
|
@ -2163,6 +2227,9 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
|
||||||
/*
|
/*
|
||||||
* Initialize netdev entry points
|
* Initialize netdev entry points
|
||||||
*/
|
*/
|
||||||
|
if (mlx4_is_master(priv->mdev->dev))
|
||||||
|
dev->netdev_ops = &mlx4_netdev_ops_master;
|
||||||
|
else
|
||||||
dev->netdev_ops = &mlx4_netdev_ops;
|
dev->netdev_ops = &mlx4_netdev_ops;
|
||||||
dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
|
dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
|
||||||
netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
|
netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
|
||||||
|
@ -2228,8 +2295,11 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
|
||||||
}
|
}
|
||||||
mlx4_en_set_default_moderation(priv);
|
mlx4_en_set_default_moderation(priv);
|
||||||
queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
|
queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
|
||||||
|
|
||||||
|
if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
|
||||||
queue_delayed_work(mdev->workqueue, &priv->service_task,
|
queue_delayed_work(mdev->workqueue, &priv->service_task,
|
||||||
SERVICE_TASK_DELAY);
|
SERVICE_TASK_DELAY);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -468,6 +468,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
|
||||||
#define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66
|
#define QUERY_DEV_CAP_RSVD_XRC_OFFSET 0x66
|
||||||
#define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67
|
#define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67
|
||||||
#define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET 0x68
|
#define QUERY_DEV_CAP_MAX_COUNTERS_OFFSET 0x68
|
||||||
|
#define QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET 0x70
|
||||||
#define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76
|
#define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76
|
||||||
#define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77
|
#define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77
|
||||||
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80
|
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80
|
||||||
|
@ -655,6 +656,12 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
|
||||||
MLX4_GET(dev_cap->max_counters, outbox,
|
MLX4_GET(dev_cap->max_counters, outbox,
|
||||||
QUERY_DEV_CAP_MAX_COUNTERS_OFFSET);
|
QUERY_DEV_CAP_MAX_COUNTERS_OFFSET);
|
||||||
|
|
||||||
|
MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
|
||||||
|
if (field32 & (1 << 26))
|
||||||
|
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL;
|
||||||
|
if (field32 & (1 << 20))
|
||||||
|
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FSM;
|
||||||
|
|
||||||
if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
|
if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
|
||||||
for (i = 1; i <= dev_cap->num_ports; ++i) {
|
for (i = 1; i <= dev_cap->num_ports; ++i) {
|
||||||
MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
|
MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
|
||||||
|
@ -784,6 +791,11 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
|
||||||
flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW;
|
flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW;
|
||||||
MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
|
MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
|
||||||
|
|
||||||
|
/* For guests, disable timestamp */
|
||||||
|
MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
|
||||||
|
field &= 0x7f;
|
||||||
|
MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
|
||||||
|
|
||||||
/* For guests, report Blueflame disabled */
|
/* For guests, report Blueflame disabled */
|
||||||
MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET);
|
MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET);
|
||||||
field &= 0x7f;
|
field &= 0x7f;
|
||||||
|
@ -811,6 +823,7 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
|
||||||
struct mlx4_cmd_mailbox *outbox,
|
struct mlx4_cmd_mailbox *outbox,
|
||||||
struct mlx4_cmd_info *cmd)
|
struct mlx4_cmd_info *cmd)
|
||||||
{
|
{
|
||||||
|
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||||
u64 def_mac;
|
u64 def_mac;
|
||||||
u8 port_type;
|
u8 port_type;
|
||||||
u16 short_field;
|
u16 short_field;
|
||||||
|
@ -828,6 +841,9 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
|
||||||
/* set slave default_mac address */
|
/* set slave default_mac address */
|
||||||
MLX4_GET(def_mac, outbox->buf, QUERY_PORT_MAC_OFFSET);
|
MLX4_GET(def_mac, outbox->buf, QUERY_PORT_MAC_OFFSET);
|
||||||
def_mac += slave << 8;
|
def_mac += slave << 8;
|
||||||
|
/* if config MAC in DB use it */
|
||||||
|
if (priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac)
|
||||||
|
def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac;
|
||||||
MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET);
|
MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET);
|
||||||
|
|
||||||
/* get port type - currently only eth is enabled */
|
/* get port type - currently only eth is enabled */
|
||||||
|
|
|
@ -473,6 +473,30 @@ struct mlx4_slave_state {
|
||||||
enum slave_port_state port_state[MLX4_MAX_PORTS + 1];
|
enum slave_port_state port_state[MLX4_MAX_PORTS + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MLX4_VGT 4095
|
||||||
|
#define NO_INDX (-1)
|
||||||
|
|
||||||
|
struct mlx4_vport_state {
|
||||||
|
u64 mac;
|
||||||
|
u16 default_vlan;
|
||||||
|
u8 default_qos;
|
||||||
|
u32 tx_rate;
|
||||||
|
bool spoofchk;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mlx4_vf_admin_state {
|
||||||
|
struct mlx4_vport_state vport[MLX4_MAX_PORTS + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mlx4_vport_oper_state {
|
||||||
|
struct mlx4_vport_state state;
|
||||||
|
int mac_idx;
|
||||||
|
int vlan_idx;
|
||||||
|
};
|
||||||
|
struct mlx4_vf_oper_state {
|
||||||
|
struct mlx4_vport_oper_state vport[MLX4_MAX_PORTS + 1];
|
||||||
|
};
|
||||||
|
|
||||||
struct slave_list {
|
struct slave_list {
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
struct list_head res_list[MLX4_NUM_OF_RESOURCE_TYPE];
|
struct list_head res_list[MLX4_NUM_OF_RESOURCE_TYPE];
|
||||||
|
@ -503,6 +527,8 @@ struct mlx4_master_qp0_state {
|
||||||
|
|
||||||
struct mlx4_mfunc_master_ctx {
|
struct mlx4_mfunc_master_ctx {
|
||||||
struct mlx4_slave_state *slave_state;
|
struct mlx4_slave_state *slave_state;
|
||||||
|
struct mlx4_vf_admin_state *vf_admin;
|
||||||
|
struct mlx4_vf_oper_state *vf_oper;
|
||||||
struct mlx4_master_qp0_state qp0_state[MLX4_MAX_PORTS + 1];
|
struct mlx4_master_qp0_state qp0_state[MLX4_MAX_PORTS + 1];
|
||||||
int init_port_ref[MLX4_MAX_PORTS + 1];
|
int init_port_ref[MLX4_MAX_PORTS + 1];
|
||||||
u16 max_mtu[MLX4_MAX_PORTS + 1];
|
u16 max_mtu[MLX4_MAX_PORTS + 1];
|
||||||
|
@ -1131,6 +1157,8 @@ int mlx4_change_port_types(struct mlx4_dev *dev,
|
||||||
|
|
||||||
void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
|
void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
|
||||||
void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
|
void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
|
||||||
|
void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index);
|
||||||
|
int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
|
||||||
|
|
||||||
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz);
|
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz);
|
||||||
/* resource tracker functions*/
|
/* resource tracker functions*/
|
||||||
|
|
|
@ -141,8 +141,9 @@ int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
|
if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
|
||||||
/* MAC already registered, Must not have duplicates */
|
/* MAC already registered, increment ref count */
|
||||||
err = -EEXIST;
|
err = i;
|
||||||
|
++table->refs[i];
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +166,7 @@ int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
|
||||||
table->entries[free] = 0;
|
table->entries[free] = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
table->refs[free] = 1;
|
||||||
err = free;
|
err = free;
|
||||||
++table->total;
|
++table->total;
|
||||||
out:
|
out:
|
||||||
|
@ -206,12 +207,16 @@ void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
|
||||||
struct mlx4_mac_table *table = &info->mac_table;
|
struct mlx4_mac_table *table = &info->mac_table;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
index = find_index(dev, table, mac);
|
|
||||||
|
|
||||||
mutex_lock(&table->mutex);
|
mutex_lock(&table->mutex);
|
||||||
|
index = find_index(dev, table, mac);
|
||||||
|
|
||||||
if (validate_index(dev, table, index))
|
if (validate_index(dev, table, index))
|
||||||
goto out;
|
goto out;
|
||||||
|
if (--table->refs[index]) {
|
||||||
|
mlx4_dbg(dev, "Have more references for index %d,"
|
||||||
|
"no need to modify mac table\n", index);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
table->entries[index] = 0;
|
table->entries[index] = 0;
|
||||||
mlx4_set_port_mac_table(dev, port, table->entries);
|
mlx4_set_port_mac_table(dev, port, table->entries);
|
||||||
|
@ -305,7 +310,7 @@ int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan);
|
EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan);
|
||||||
|
|
||||||
static int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan,
|
int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan,
|
||||||
int *index)
|
int *index)
|
||||||
{
|
{
|
||||||
struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
|
struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
|
||||||
|
@ -379,7 +384,7 @@ int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mlx4_register_vlan);
|
EXPORT_SYMBOL_GPL(mlx4_register_vlan);
|
||||||
|
|
||||||
static void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
|
void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
|
||||||
{
|
{
|
||||||
struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
|
struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
|
||||||
|
|
||||||
|
|
|
@ -353,6 +353,47 @@ 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));
|
||||||
|
}
|
||||||
|
if (vp_oper->state.spoofchk) {
|
||||||
|
qpc->pri_path.feup |= 1 << 5; /* set fsm bit */;
|
||||||
|
qpc->pri_path.grh_mylmc = (0x80 & qpc->pri_path.grh_mylmc) + vp_oper->mac_idx;
|
||||||
|
mlx4_dbg(dev, "spoof qp %d port %d feup 0x%x, myLmc 0x%x mindx %d\n",
|
||||||
|
be32_to_cpu(qpc->local_qpn) & 0xffffff, port,
|
||||||
|
(int)qpc->pri_path.feup, (int)qpc->pri_path.grh_mylmc,
|
||||||
|
vp_oper->mac_idx);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mpt_mask(struct mlx4_dev *dev)
|
static int mpt_mask(struct mlx4_dev *dev)
|
||||||
{
|
{
|
||||||
return dev->caps.num_mpts - 1;
|
return dev->caps.num_mpts - 1;
|
||||||
|
@ -2798,6 +2839,9 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
|
||||||
update_pkey_index(dev, slave, inbox);
|
update_pkey_index(dev, slave, inbox);
|
||||||
update_gid(dev, inbox, (u8)slave);
|
update_gid(dev, inbox, (u8)slave);
|
||||||
adjust_proxy_tun_qkey(dev, vhcr, qpc);
|
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);
|
return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#define MLX4_CMD_H
|
#define MLX4_CMD_H
|
||||||
|
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/* initialization and general commands */
|
/* initialization and general commands */
|
||||||
|
@ -232,6 +233,11 @@ struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev);
|
||||||
void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox);
|
void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox);
|
||||||
|
|
||||||
u32 mlx4_comm_get_version(void);
|
u32 mlx4_comm_get_version(void);
|
||||||
|
int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac);
|
||||||
|
int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos);
|
||||||
|
int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting);
|
||||||
|
int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_info *ivf);
|
||||||
|
|
||||||
|
|
||||||
#define MLX4_COMM_GET_IF_REV(cmd_chan_ver) (u8)((cmd_chan_ver) >> 8)
|
#define MLX4_COMM_GET_IF_REV(cmd_chan_ver) (u8)((cmd_chan_ver) >> 8)
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,9 @@ enum {
|
||||||
MLX4_DEV_CAP_FLAG2_RSS_XOR = 1LL << 2,
|
MLX4_DEV_CAP_FLAG2_RSS_XOR = 1LL << 2,
|
||||||
MLX4_DEV_CAP_FLAG2_FS_EN = 1LL << 3,
|
MLX4_DEV_CAP_FLAG2_FS_EN = 1LL << 3,
|
||||||
MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN = 1LL << 4,
|
MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN = 1LL << 4,
|
||||||
MLX4_DEV_CAP_FLAG2_TS = 1LL << 5
|
MLX4_DEV_CAP_FLAG2_TS = 1LL << 5,
|
||||||
|
MLX4_DEV_CAP_FLAG2_VLAN_CONTROL = 1LL << 6,
|
||||||
|
MLX4_DEV_CAP_FLAG2_FSM = 1LL << 7
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
Loading…
Reference in New Issue