Commit 273889e3 authored by David S. Miller's avatar David S. Miller

Merge tag 'mlx5-updates-2017-06-16' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
Mellanox mlx5 updates and cleanups 2017-06-16

mlx5-updates-2017-06-16

This series provide some updates and cleanups for mlx5 core and netdevice
driver.

From Eli Cohen, add a missing event string.
From Or Gerlitz, some checkpatch cleanups.
From Moni, Disalbe HW level LAG when SRIOV is enabled.
From Tariq, A code reuse cleanup in aRFS flow.
From Itay Aveksis, Typo fix.
From Gal Pressman, ethtool statistics updates and "update stats" deferred work optimizations.
From Majd Dibbiny, Fast unload support on kernel shutdown.
====================
Signed-off-by: default avatarDavid S. Miller <[email protected]>
parents a1a6b7ea 8812c24d
......@@ -439,7 +439,7 @@ static void get_atomic_caps(struct mlx5_ib_dev *dev,
u8 atomic_operations = MLX5_CAP_ATOMIC(dev->mdev, atomic_operations);
u8 atomic_size_qp = MLX5_CAP_ATOMIC(dev->mdev, atomic_size_qp);
u8 atomic_req_8B_endianness_mode =
MLX5_CAP_ATOMIC(dev->mdev, atomic_req_8B_endianess_mode);
MLX5_CAP_ATOMIC(dev->mdev, atomic_req_8B_endianness_mode);
/* Check if HW supports 8 bytes standard atomic operations and capable
* of host endianness respond
......
......@@ -274,7 +274,6 @@ void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db)
}
EXPORT_SYMBOL_GPL(mlx5_db_free);
void mlx5_fill_page_array(struct mlx5_buf *buf, __be64 *pas)
{
u64 addr;
......
......@@ -217,7 +217,6 @@ static void free_cmd(struct mlx5_cmd_work_ent *ent)
kfree(ent);
}
static int verify_signature(struct mlx5_cmd_work_ent *ent)
{
struct mlx5_cmd_mailbox *next = ent->out->next;
......@@ -786,6 +785,8 @@ static void cmd_work_handler(struct work_struct *work)
struct mlx5_cmd_layout *lay;
struct semaphore *sem;
unsigned long flags;
bool poll_cmd = ent->polling;
sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem;
down(sem);
......@@ -846,7 +847,7 @@ static void cmd_work_handler(struct work_struct *work)
iowrite32be(1 << ent->idx, &dev->iseg->cmd_dbell);
mmiowb();
/* if not in polling don't use ent after this point */
if (cmd->mode == CMD_MODE_POLLING) {
if (cmd->mode == CMD_MODE_POLLING || poll_cmd) {
poll_timeout(ent);
/* make sure we read the descriptor after ownership is SW */
rmb();
......@@ -874,7 +875,7 @@ static const char *deliv_status_to_str(u8 status)
case MLX5_CMD_DELIVERY_STAT_IN_LENGTH_ERR:
return "command input length error";
case MLX5_CMD_DELIVERY_STAT_OUT_LENGTH_ERR:
return "command ouput length error";
return "command output length error";
case MLX5_CMD_DELIVERY_STAT_RES_FLD_NOT_CLR_ERR:
return "reserved fields not cleared";
case MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR:
......@@ -890,7 +891,7 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
struct mlx5_cmd *cmd = &dev->cmd;
int err;
if (cmd->mode == CMD_MODE_POLLING) {
if (cmd->mode == CMD_MODE_POLLING || ent->polling) {
wait_for_completion(&ent->done);
} else if (!wait_for_completion_timeout(&ent->done, timeout)) {
ent->ret = -ETIMEDOUT;
......@@ -918,7 +919,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
struct mlx5_cmd_msg *out, void *uout, int uout_size,
mlx5_cmd_cbk_t callback,
void *context, int page_queue, u8 *status,
u8 token)
u8 token, bool force_polling)
{
struct mlx5_cmd *cmd = &dev->cmd;
struct mlx5_cmd_work_ent *ent;
......@@ -936,6 +937,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
return PTR_ERR(ent);
ent->token = token;
ent->polling = force_polling;
if (!callback)
init_completion(&ent->done);
......@@ -1001,7 +1003,6 @@ static ssize_t dbg_write(struct file *filp, const char __user *buf,
return err ? err : count;
}
static const struct file_operations fops = {
.owner = THIS_MODULE,
.open = simple_open,
......@@ -1153,7 +1154,7 @@ static struct mlx5_cmd_msg *mlx5_alloc_cmd_msg(struct mlx5_core_dev *dev,
}
static void mlx5_free_cmd_msg(struct mlx5_core_dev *dev,
struct mlx5_cmd_msg *msg)
struct mlx5_cmd_msg *msg)
{
struct mlx5_cmd_mailbox *head = msg->next;
struct mlx5_cmd_mailbox *next;
......@@ -1537,7 +1538,8 @@ static int is_manage_pages(void *in)
}
static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
int out_size, mlx5_cmd_cbk_t callback, void *context)
int out_size, mlx5_cmd_cbk_t callback, void *context,
bool force_polling)
{
struct mlx5_cmd_msg *inb;
struct mlx5_cmd_msg *outb;
......@@ -1582,7 +1584,7 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
}
err = mlx5_cmd_invoke(dev, inb, outb, out, out_size, callback, context,
pages_queue, &status, token);
pages_queue, &status, token, force_polling);
if (err)
goto out_out;
......@@ -1610,7 +1612,7 @@ int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
{
int err;
err = cmd_exec(dev, in, in_size, out, out_size, NULL, NULL);
err = cmd_exec(dev, in, in_size, out, out_size, NULL, NULL, false);
return err ? : mlx5_cmd_check(dev, in, out);
}
EXPORT_SYMBOL(mlx5_cmd_exec);
......@@ -1619,10 +1621,22 @@ int mlx5_cmd_exec_cb(struct mlx5_core_dev *dev, void *in, int in_size,
void *out, int out_size, mlx5_cmd_cbk_t callback,
void *context)
{
return cmd_exec(dev, in, in_size, out, out_size, callback, context);
return cmd_exec(dev, in, in_size, out, out_size, callback, context,
false);
}
EXPORT_SYMBOL(mlx5_cmd_exec_cb);
int mlx5_cmd_exec_polling(struct mlx5_core_dev *dev, void *in, int in_size,
void *out, int out_size)
{
int err;
err = cmd_exec(dev, in, in_size, out, out_size, NULL, NULL, true);
return err ? : mlx5_cmd_check(dev, in, out);
}
EXPORT_SYMBOL(mlx5_cmd_exec_polling);
static void destroy_msg_cache(struct mlx5_core_dev *dev)
{
struct cmd_msg_cache *ch;
......
......@@ -168,7 +168,6 @@ static ssize_t average_read(struct file *filp, char __user *buf, size_t count,
return ret;
}
static ssize_t average_write(struct file *filp, const char __user *buf,
size_t count, loff_t *pos)
{
......@@ -466,7 +465,6 @@ static ssize_t dbg_read(struct file *filp, char __user *buf, size_t count,
return -EINVAL;
}
if (is_str)
ret = snprintf(tbuf, sizeof(tbuf), "%s\n", (const char *)(unsigned long)field);
else
......@@ -562,7 +560,6 @@ void mlx5_debug_qp_remove(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp)
rem_res_tree(qp->dbg);
}
int mlx5_debug_eq_add(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
{
int err;
......
......@@ -822,7 +822,7 @@ void mlx5e_rx_am(struct mlx5e_rq *rq);
void mlx5e_rx_am_work(struct work_struct *work);
struct mlx5e_cq_moder mlx5e_am_get_def_profile(u8 rx_cq_period_mode);
void mlx5e_update_stats(struct mlx5e_priv *priv);
void mlx5e_update_stats(struct mlx5e_priv *priv, bool full);
int mlx5e_create_flow_steering(struct mlx5e_priv *priv);
void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv);
......
......@@ -178,6 +178,7 @@ static int arfs_add_default_rule(struct mlx5e_priv *priv,
struct mlx5_flow_destination dest;
MLX5_DECLARE_FLOW_ACT(flow_act);
struct mlx5_flow_spec *spec;
enum mlx5e_traffic_types tt;
int err = 0;
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
......@@ -187,24 +188,16 @@ static int arfs_add_default_rule(struct mlx5e_priv *priv,
}
dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
switch (type) {
case ARFS_IPV4_TCP:
dest.tir_num = tir[MLX5E_TT_IPV4_TCP].tirn;
break;
case ARFS_IPV4_UDP:
dest.tir_num = tir[MLX5E_TT_IPV4_UDP].tirn;
break;
case ARFS_IPV6_TCP:
dest.tir_num = tir[MLX5E_TT_IPV6_TCP].tirn;
break;
case ARFS_IPV6_UDP:
dest.tir_num = tir[MLX5E_TT_IPV6_UDP].tirn;
break;
default:
tt = arfs_get_tt(type);
if (tt == -EINVAL) {
netdev_err(priv->netdev, "%s: bad arfs_type: %d\n",
__func__, type);
err = -EINVAL;
goto out;
}
dest.tir_num = tir[tt].tirn;
arfs_t->default_rule = mlx5_add_flow_rules(arfs_t->ft.t, spec,
&flow_act,
&dest, 1);
......
......@@ -145,7 +145,6 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb)
int inlen;
void *in;
inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
in = kvzalloc(inlen, GFP_KERNEL);
if (!in)
......
......@@ -311,7 +311,7 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev,
mutex_lock(&priv->state_lock);
if (test_bit(MLX5E_STATE_OPENED, &priv->state))
mlx5e_update_stats(priv);
mlx5e_update_stats(priv, true);
channels = &priv->channels;
mutex_unlock(&priv->state_lock);
......
......@@ -170,7 +170,6 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
switch (rule_type) {
case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
rule_p = &priv->fs.vlan.untagged_rule;
......
......@@ -124,7 +124,8 @@ static void mlx5e_update_carrier(struct mlx5e_priv *priv)
u8 port_state;
port_state = mlx5_query_vport_state(mdev,
MLX5_QUERY_VPORT_STATE_IN_OP_MOD_VNIC_VPORT, 0);
MLX5_QUERY_VPORT_STATE_IN_OP_MOD_VNIC_VPORT,
0);
if (port_state == VPORT_STATE_UP) {
netdev_info(priv->netdev, "Link up\n");
......@@ -243,18 +244,14 @@ static void mlx5e_update_vport_counters(struct mlx5e_priv *priv)
mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen);
}
static void mlx5e_update_pport_counters(struct mlx5e_priv *priv)
static void mlx5e_update_pport_counters(struct mlx5e_priv *priv, bool full)
{
struct mlx5e_pport_stats *pstats = &priv->stats.pport;
struct mlx5_core_dev *mdev = priv->mdev;
u32 in[MLX5_ST_SZ_DW(ppcnt_reg)] = {0};
int sz = MLX5_ST_SZ_BYTES(ppcnt_reg);
int prio;
void *out;
u32 *in;
in = kvzalloc(sz, GFP_KERNEL);
if (!in)
return;
MLX5_SET(ppcnt_reg, in, local_port, 1);
......@@ -262,6 +259,9 @@ static void mlx5e_update_pport_counters(struct mlx5e_priv *priv)
MLX5_SET(ppcnt_reg, in, grp, MLX5_IEEE_802_3_COUNTERS_GROUP);
mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0);
if (!full)
return;
out = pstats->RFC_2863_counters;
MLX5_SET(ppcnt_reg, in, grp, MLX5_RFC_2863_COUNTERS_GROUP);
mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPCNT, 0, 0);
......@@ -287,52 +287,55 @@ static void mlx5e_update_pport_counters(struct mlx5e_priv *priv)
mlx5_core_access_reg(mdev, in, sz, out, sz,
MLX5_REG_PPCNT, 0, 0);
}
kvfree(in);
}
static void mlx5e_update_q_counter(struct mlx5e_priv *priv)
{
struct mlx5e_qcounter_stats *qcnt = &priv->stats.qcnt;
u32 out[MLX5_ST_SZ_DW(query_q_counter_out)];
int err;
if (!priv->q_counter)
return;
mlx5_core_query_out_of_buffer(priv->mdev, priv->q_counter,
&qcnt->rx_out_of_buffer);
err = mlx5_core_query_q_counter(priv->mdev, priv->q_counter, 0, out, sizeof(out));
if (err)
return;
qcnt->rx_out_of_buffer = MLX5_GET(query_q_counter_out, out, out_of_buffer);
}
static void mlx5e_update_pcie_counters(struct mlx5e_priv *priv)
{
struct mlx5e_pcie_stats *pcie_stats = &priv->stats.pcie;
struct mlx5_core_dev *mdev = priv->mdev;
u32 in[MLX5_ST_SZ_DW(mpcnt_reg)] = {0};
int sz = MLX5_ST_SZ_BYTES(mpcnt_reg);
void *out;
u32 *in;
if (!MLX5_CAP_MCAM_FEATURE(mdev, pcie_performance_group))
return;
in = kvzalloc(sz, GFP_KERNEL);
if (!in)
return;
out = pcie_stats->pcie_perf_counters;
MLX5_SET(mpcnt_reg, in, grp, MLX5_PCIE_PERFORMANCE_COUNTERS_GROUP);
mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_MPCNT, 0, 0);
kvfree(in);
}
void mlx5e_update_stats(struct mlx5e_priv *priv)
void mlx5e_update_stats(struct mlx5e_priv *priv, bool full)
{
mlx5e_update_pcie_counters(priv);
mlx5e_update_pport_counters(priv);
if (full)
mlx5e_update_pcie_counters(priv);
mlx5e_update_pport_counters(priv, full);
mlx5e_update_vport_counters(priv);
mlx5e_update_q_counter(priv);
mlx5e_update_sw_counters(priv);
}
static void mlx5e_update_ndo_stats(struct mlx5e_priv *priv)
{
mlx5e_update_stats(priv, false);
}
void mlx5e_update_stats_work(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
......@@ -3067,7 +3070,6 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
*/
stats->multicast =
VPORT_COUNTER_GET(vstats, received_eth_multicast.packets);
}
static void mlx5e_set_rx_mode(struct net_device *dev)
......@@ -3727,7 +3729,7 @@ static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
if (!MLX5_CAP_GEN(mdev, cq_moderation))
mlx5_core_warn(mdev, "CQ modiration is not supported\n");
mlx5_core_warn(mdev, "CQ moderation is not supported\n");
return 0;
}
......@@ -3860,7 +3862,7 @@ void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
/* set CQE compression */
params->rx_cqe_compress_def = false;
if (MLX5_CAP_GEN(mdev, cqe_compression) &&
MLX5_CAP_GEN(mdev, vport_group_manager))
MLX5_CAP_GEN(mdev, vport_group_manager))
params->rx_cqe_compress_def = cqe_compress_heuristic(link_speed, pci_bw);
MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS, params->rx_cqe_compress_def);
......@@ -4211,7 +4213,7 @@ static const struct mlx5e_profile mlx5e_nic_profile = {
.cleanup_tx = mlx5e_cleanup_nic_tx,
.enable = mlx5e_nic_enable,
.disable = mlx5e_nic_disable,
.update_stats = mlx5e_update_stats,
.update_stats = mlx5e_update_ndo_stats,
.max_nch = mlx5e_get_max_num_channels,
.rx_handlers.handle_rx_cqe = mlx5e_handle_rx_cqe,
.rx_handlers.handle_rx_cqe_mpwqe = mlx5e_handle_rx_cqe_mpwrq,
......
......@@ -1019,7 +1019,6 @@ mlx5e_vport_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
mlx5e_destroy_netdev(netdev_priv(netdev));
kfree(rpriv);
return err;
}
static void
......
......@@ -268,7 +268,7 @@ static const struct counter_desc pport_2819_stats_desc[] = {
};
static const struct counter_desc pport_phy_statistical_stats_desc[] = {
{ "rx_symbol_errors_phy", PPORT_PHY_STATISTICAL_OFF(phy_symbol_errors) },
{ "rx_pcs_symbol_err_phy", PPORT_PHY_STATISTICAL_OFF(phy_symbol_errors) },
{ "rx_corrected_bits_phy", PPORT_PHY_STATISTICAL_OFF(phy_corrected_bits) },
};
......
......@@ -245,7 +245,7 @@ mlx5e_txwqe_build_dsegs(struct mlx5e_txqsq *sq, struct sk_buff *skb,
int fsz = skb_frag_size(frag);
dma_addr = skb_frag_dma_map(sq->pdev, frag, 0, fsz,
DMA_TO_DEVICE);
DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(sq->pdev, dma_addr)))
return -ENOMEM;
......
......@@ -157,6 +157,8 @@ static const char *eqe_type_str(u8 type)
return "MLX5_EVENT_TYPE_PAGE_FAULT";
case MLX5_EVENT_TYPE_PPS_EVENT:
return "MLX5_EVENT_TYPE_PPS_EVENT";
case MLX5_EVENT_TYPE_NIC_VPORT_CHANGE:
return "MLX5_EVENT_TYPE_NIC_VPORT_CHANGE";
case MLX5_EVENT_TYPE_FPGA_ERROR:
return "MLX5_EVENT_TYPE_FPGA_ERROR";
default:
......@@ -189,7 +191,7 @@ static void eq_update_ci(struct mlx5_eq *eq, int arm)
{
__be32 __iomem *addr = eq->doorbell + (arm ? 0 : 2);
u32 val = (eq->cons_index & 0xffffff) | (eq->eqn << 24);
__raw_writel((__force u32) cpu_to_be32(val), addr);
__raw_writel((__force u32)cpu_to_be32(val), addr);
/* We still want ordering, just not swabbing, so add a barrier */
mb();
}
......@@ -675,7 +677,6 @@ int mlx5_eq_init(struct mlx5_core_dev *dev)
return err;
}
void mlx5_eq_cleanup(struct mlx5_core_dev *dev)
{
mlx5_eq_debugfs_cleanup(dev);
......@@ -687,7 +688,6 @@ int mlx5_start_eqs(struct mlx5_core_dev *dev)
u64 async_event_mask = MLX5_ASYNC_EVENT_MASK;
int err;
if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_ETH &&
MLX5_CAP_GEN(dev, vport_group_manager) &&
mlx5_core_is_pf(dev))
......
......@@ -1217,7 +1217,6 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
"vport[%d] configure ingress rules failed, illegal mac with spoofchk\n",
vport->vport);
return -EPERM;
}
esw_vport_cleanup_ingress_rules(esw, vport);
......
......@@ -691,7 +691,7 @@ mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn)
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec,
&flow_act, &dest, 1);
&flow_act, &dest, 1);
if (IS_ERR(flow_rule)) {
esw_warn(esw->dev, "fs offloads: Failed to add vport rx rule err %ld\n", PTR_ERR(flow_rule));
goto out;
......@@ -1093,7 +1093,7 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, u8 encap)
if (err) {
esw_warn(esw->dev, "Failed re-creating fast FDB table, err %d\n", err);
esw->offloads.encap = !encap;
(void) esw_create_offloads_fast_fdb_table(esw);
(void)esw_create_offloads_fast_fdb_table(esw);
}
return err;
}
......
......@@ -104,6 +104,7 @@ struct node_caps {
size_t arr_sz;
long *caps;
};
static struct init_tree_node {
enum fs_node_type type;
struct init_tree_node *children;
......@@ -1858,7 +1859,6 @@ static int create_anchor_flow_table(struct mlx5_flow_steering *steering)
static int init_root_ns(struct mlx5_flow_steering *steering)
{
steering->root_ns = create_root_ns(steering, FS_FT_NIC_RX);
if (!steering->root_ns)
goto cleanup;
......
......@@ -195,3 +195,31 @@ int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev)
MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA);
return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
}
int mlx5_cmd_force_teardown_hca(struct mlx5_core_dev *dev)
{
u32 out[MLX5_ST_SZ_DW(teardown_hca_out)] = {0};
u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {0};
int force_state;
int ret;
if (!MLX5_CAP_GEN(dev, force_teardown)) {
mlx5_core_dbg(dev, "force teardown is not supported in the firmware\n");
return -EOPNOTSUPP;
}
MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA);
MLX5_SET(teardown_hca_in, in, profile, MLX5_TEARDOWN_HCA_IN_PROFILE_FORCE_CLOSE);
ret = mlx5_cmd_exec_polling(dev, in, sizeof(in), out, sizeof(out));
if (ret)
return ret;
force_state = MLX5_GET(teardown_hca_out, out, force_state);
if (force_state == MLX5_TEARDOWN_HCA_OUT_FORCE_STATE_FAIL) {
mlx5_core_err(dev, "teardown with force mode failed\n");
return -EIO;
}
return 0;
}
......@@ -111,14 +111,14 @@ static int in_fatal(struct mlx5_core_dev *dev)
return 0;
}
void mlx5_enter_error_state(struct mlx5_core_dev *dev)
void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force)
{
mutex_lock(&dev->intf_state_mutex);
if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
goto unlock;
mlx5_core_err(dev, "start\n");
if (pci_channel_offline(dev->pdev) || in_fatal(dev)) {
if (pci_channel_offline(dev->pdev) || in_fatal(dev) || force) {
dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
trigger_cmd_completions(dev);
}
......
......@@ -61,6 +61,11 @@ struct mlx5_lag {
struct lag_tracker tracker;
struct delayed_work bond_work;
struct notifier_block nb;
/* Admin state. Allow lag only if allowed is true
* even if network conditions for lag were met
*/
bool allowed;
};
/* General purpose, use for short periods of time.
......@@ -214,6 +219,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
struct lag_tracker tracker;
u8 v2p_port1, v2p_port2;
int i, err;
bool do_bond;
if (!dev0 || !dev1)
return;
......@@ -222,13 +228,9 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
tracker = ldev->tracker;
mutex_unlock(&lag_mutex);
if (tracker.is_bonded && !mlx5_lag_is_bonded(ldev)) {
if (mlx5_sriov_is_enabled(dev0) ||
mlx5_sriov_is_enabled(dev1)) {
mlx5_core_warn(dev0, "LAG is not supported with SRIOV");
return;
}
do_bond = tracker.is_bonded && ldev->allowed;
if (do_bond && !mlx5_lag_is_bonded(ldev)) {
for (i = 0; i < MLX5_MAX_PORTS; i++)
mlx5_remove_dev_by_protocol(ldev->pf[i].dev,
MLX5_INTERFACE_PROTOCOL_IB);
......@@ -237,7 +239,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
mlx5_add_dev_by_protocol(dev0, MLX5_INTERFACE_PROTOCOL_IB);
mlx5_nic_vport_enable_roce(dev1);
} else if (tracker.is_bonded && mlx5_lag_is_bonded(ldev)) {
} else if (do_bond && mlx5_lag_is_bonded(ldev)) {
mlx5_infer_tx_affinity_mapping(&tracker, &v2p_port1,
&v2p_port2);
......@@ -252,7 +254,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
"Failed to modify LAG (%d)\n",
err);
}
} else if (!tracker.is_bonded && mlx5_lag_is_bonded(ldev)) {
} else if (!do_bond && mlx5_lag_is_bonded(ldev)) {
mlx5_remove_dev_by_protocol(dev0, MLX5_INTERFACE_PROTOCOL_IB);
mlx5_nic_vport_disable_roce(dev1);
......@@ -411,6 +413,15 @@ static int mlx5_lag_netdev_event(struct notifier_block *this,
return NOTIFY_DONE;
}
static bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
{
if ((ldev->pf[0].dev && mlx5_sriov_is_enabled(ldev->pf[0].dev)) ||
(ldev->pf[1].dev && mlx5_sriov_is_enabled(ldev->pf[1].dev)))
return false;
else
return true;
}
static struct mlx5_lag *mlx5_lag_dev_alloc(void)
{
struct mlx5_lag *ldev;
......@@ -420,6 +431,7 @@ static struct mlx5_lag *mlx5_lag_dev_alloc(void)
return NULL;
INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work);
ldev->allowed = mlx5_lag_check_prereq(ldev);
return ldev;
}
......@@ -444,7 +456,9 @@ static void mlx5_lag_dev_add_pf(struct mlx5_lag *ldev,
ldev->tracker.netdev_state[fn].link_up = 0;
ldev->tracker.netdev_state[fn].tx_enabled = 0;
ldev->allowed = mlx5_lag_check_prereq(ldev);
dev->priv.lag = ldev;
mutex_unlock(&lag_mutex);
}
......@@ -464,10 +478,10 @@ static void mlx5_lag_dev_remove_pf(struct mlx5_lag *ldev,
memset(&ldev->pf[i], 0, sizeof(*ldev->pf));
dev->priv.lag = NULL;
ldev->allowed = mlx5_lag_check_prereq(ldev);
mutex_unlock(&lag_mutex);
}
/* Must be called with intf_mutex held */
void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
{
......@@ -543,6 +557,44 @@ bool mlx5_lag_is_active(struct mlx5_core_dev *dev)
}
EXPORT_SYMBOL(mlx5_lag_is_active);
static int mlx5_lag_set_state(struct mlx5_core_dev *dev, bool allow)
{
struct mlx5_lag *ldev;
int ret = 0;
bool lag_active;
mlx5_dev_list_lock();
ldev = mlx5_lag_dev_get(dev);
if (!ldev) {
ret = -ENODEV;
goto unlock;
}
lag_active = mlx5_lag_is_bonded(ldev);
if (!mlx5_lag_check_prereq(ldev) && allow) {
ret = -EINVAL;
goto unlock;
}
if (ldev->allowed == allow)
goto unlock;
ldev->allowed = allow;
if ((lag_active && !allow) || allow)
mlx5_do_bond(ldev);
unlock:
mlx5_dev_list_unlock();
return ret;
}
int mlx5_lag_forbid(struct mlx5_core_dev *dev)
{
return mlx5_lag_set_state(dev, false);
}
int mlx5_lag_allow(struct mlx5_core_dev *dev)
{
return mlx5_lag_set_state(dev, true);
}
struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev)
{
struct net_device *ndev = NULL;
......@@ -586,4 +638,3 @@ bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv)
/* If bonded, we do not add an IB device for PF1. */
return false;
}
......@@ -356,12 +356,11 @@ static void mlx5_disable_msix(struct mlx5_core_dev *dev)
kfree(priv->msix_arr);
}
struct mlx5_reg_host_endianess {
struct mlx5_reg_host_endianness {
u8 he;
u8 rsvd[15];
};
#define CAP_MASK(pos, size) ((u64)((1 << (size)) - 1) << (pos))
enum {
......@@ -475,7 +474,7 @@ static int handle_hca_cap_atomic(struct mlx5_core_dev *dev)
req_endianness =