Merge branch 'mlx4-misc-improvements'

Tariq Toukan says:

====================
mlx4 misc improvements

This patchset contains several improvements and cleanups
from the team to the mlx4 Eth and core drivers.

Series generated against net-next commit:
4e8f2fc1a5 Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Thanks,
Tariq.

v3:
* Patch 6/9: forgot to actually update the commit message in v2, now it is.

v2:
* Patch 1/9: used EOPNOTSUPP and not ENOTSUPP.
* Patch 3/9: dropped, to be submitted separately in the future.
* Patch 6/9: updated commit message.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2017-01-30 15:26:44 -05:00
Родитель 30357d7d8a 1f8176f735
Коммит 4be9993493
10 изменённых файлов: 228 добавлений и 63 удалений

Просмотреть файл

@ -902,6 +902,7 @@ mlx4_en_set_link_ksettings(struct net_device *dev,
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_ptys_reg ptys_reg;
__be32 proto_admin;
u8 cur_autoneg;
int ret;
u32 ptys_adv = ethtool2ptys_link_modes(
@ -931,10 +932,21 @@ mlx4_en_set_link_ksettings(struct net_device *dev,
return 0;
}
proto_admin = link_ksettings->base.autoneg == AUTONEG_ENABLE ?
cpu_to_be32(ptys_adv) :
speed_set_ptys_admin(priv, speed,
ptys_reg.eth_proto_cap);
cur_autoneg = ptys_reg.flags & MLX4_PTYS_AN_DISABLE_ADMIN ?
AUTONEG_DISABLE : AUTONEG_ENABLE;
if (link_ksettings->base.autoneg == AUTONEG_DISABLE) {
proto_admin = speed_set_ptys_admin(priv, speed,
ptys_reg.eth_proto_cap);
if ((be32_to_cpu(proto_admin) &
(MLX4_PROT_MASK(MLX4_1000BASE_CX_SGMII) |
MLX4_PROT_MASK(MLX4_1000BASE_KX))) &&
(ptys_reg.flags & MLX4_PTYS_AN_DISABLE_CAP))
ptys_reg.flags |= MLX4_PTYS_AN_DISABLE_ADMIN;
} else {
proto_admin = cpu_to_be32(ptys_adv);
ptys_reg.flags &= ~MLX4_PTYS_AN_DISABLE_ADMIN;
}
proto_admin &= ptys_reg.eth_proto_cap;
if (!proto_admin) {
@ -942,7 +954,9 @@ mlx4_en_set_link_ksettings(struct net_device *dev,
return -EINVAL; /* nothing to change due to bad input */
}
if (proto_admin == ptys_reg.eth_proto_admin)
if ((proto_admin == ptys_reg.eth_proto_admin) &&
((ptys_reg.flags & MLX4_PTYS_AN_DISABLE_CAP) &&
(link_ksettings->base.autoneg == cur_autoneg)))
return 0; /* Nothing to change */
en_dbg(DRV, priv, "mlx4_ACCESS_PTYS_REG SET: ptys_reg.eth_proto_admin = 0x%x\n",
@ -1788,7 +1802,7 @@ static int mlx4_en_set_channels(struct net_device *dev,
netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]);
netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
if (dev->num_tc)
if (netdev_get_num_tc(dev))
mlx4_en_setup_tc(dev, MLX4_EN_NUM_UP);
en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num[TX]);
@ -1980,7 +1994,7 @@ static int mlx4_en_get_module_info(struct net_device *dev,
modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
break;
default:
return -ENOSYS;
return -EINVAL;
}
return 0;

Просмотреть файл

@ -1695,6 +1695,14 @@ int mlx4_en_start_port(struct net_device *dev)
priv->port, err);
goto tx_err;
}
err = mlx4_SET_PORT_user_mtu(mdev->dev, priv->port, dev->mtu);
if (err) {
en_err(priv, "Failed to pass user MTU(%d) to Firmware for port %d, with error %d\n",
dev->mtu, priv->port, err);
goto tx_err;
}
/* Set default qp number */
err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port, priv->base_qpn, 0);
if (err) {

Просмотреть файл

@ -35,7 +35,6 @@
#define _MLX4_EN_PORT_H_
#define SET_PORT_GEN_ALL_VALID 0x7
#define SET_PORT_PROMISC_SHIFT 31
#define SET_PORT_MC_PROMISC_SHIFT 30

Просмотреть файл

@ -710,7 +710,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
u16 rings_p_up = priv->num_tx_rings_p_up;
u8 up = 0;
if (dev->num_tc)
if (netdev_get_num_tc(dev))
return skb_tx_hash(dev, skb);
if (skb_vlan_tag_present(skb))

Просмотреть файл

@ -672,7 +672,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port,
MLX4_GET(field, outbox, QUERY_FUNC_CAP_PHYS_PORT_OFFSET);
func_cap->physical_port = field;
if (func_cap->physical_port != gen_or_port) {
err = -ENOSYS;
err = -EINVAL;
goto out;
}
@ -1875,7 +1875,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
*((u8 *) mailbox->buf + INIT_HCA_VERSION_OFFSET) = INIT_HCA_VERSION;
*((u8 *) mailbox->buf + INIT_HCA_CACHELINE_SZ_OFFSET) =
(ilog2(cache_line_size()) - 4) << 5;
((ilog2(cache_line_size()) - 4) << 5) | (1 << 4);
#if defined(__LITTLE_ENDIAN)
*(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1);
@ -2983,7 +2983,7 @@ static int mlx4_SET_PORT_phv_bit(struct mlx4_dev *dev, u8 port, u8 phv_bit)
return PTR_ERR(mailbox);
context = mailbox->buf;
context->v_ignore_fcs |= SET_PORT_GEN_PHV_VALID;
context->flags2 |= SET_PORT_GEN_PHV_VALID;
if (phv_bit)
context->phv_en |= SET_PORT_GEN_PHV_EN;

Просмотреть файл

@ -838,7 +838,7 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
*/
if (hca_param.global_caps) {
mlx4_err(dev, "Unknown hca global capabilities\n");
return -ENOSYS;
return -EINVAL;
}
mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz;
@ -896,7 +896,7 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
PF_CONTEXT_BEHAVIOUR_MASK) {
mlx4_err(dev, "Unknown pf context behaviour %x known flags %x\n",
func_cap.pf_context_behaviour, PF_CONTEXT_BEHAVIOUR_MASK);
return -ENOSYS;
return -EINVAL;
}
dev->caps.num_ports = func_cap.num_ports;
@ -3492,7 +3492,7 @@ slave_start:
mlx4_enable_msi_x(dev);
if ((mlx4_is_mfunc(dev)) &&
!(dev->flags & MLX4_FLAG_MSI_X)) {
err = -ENOSYS;
err = -EOPNOTSUPP;
mlx4_err(dev, "INTx is not supported in multi-function mode, aborting\n");
goto err_free_eq;
}

Просмотреть файл

@ -487,6 +487,7 @@ struct mlx4_slave_state {
bool vst_qinq_supported;
u8 function;
dma_addr_t vhcr_dma;
u16 user_mtu[MLX4_MAX_PORTS + 1];
u16 mtu[MLX4_MAX_PORTS + 1];
__be32 ib_cap_mask[MLX4_MAX_PORTS + 1];
struct mlx4_slave_eqe eq[MLX4_MFUNC_MAX_EQES];
@ -590,6 +591,7 @@ struct mlx4_mfunc_master_ctx {
struct mlx4_master_qp0_state qp0_state[MLX4_MAX_PORTS + 1];
int init_port_ref[MLX4_MAX_PORTS + 1];
u16 max_mtu[MLX4_MAX_PORTS + 1];
u16 max_user_mtu[MLX4_MAX_PORTS + 1];
u8 pptx;
u8 pprx;
int disable_mcast_ref[MLX4_MAX_PORTS + 1];
@ -774,7 +776,9 @@ struct mlx4_vlan_table {
int max;
};
#define SET_PORT_GEN_ALL_VALID 0x7
#define SET_PORT_GEN_ALL_VALID (MLX4_FLAG_V_MTU_MASK | \
MLX4_FLAG_V_PPRX_MASK | \
MLX4_FLAG_V_PPTX_MASK)
#define SET_PORT_PROMISC_SHIFT 31
#define SET_PORT_MC_PROMISC_SHIFT 30
@ -787,7 +791,7 @@ enum {
struct mlx4_set_port_general_context {
u16 reserved1;
u8 v_ignore_fcs;
u8 flags2;
u8 flags;
union {
u8 ignore_fcs;
@ -803,7 +807,8 @@ struct mlx4_set_port_general_context {
u16 reserved4;
u32 reserved5;
u8 phv_en;
u8 reserved6[3];
u8 reserved6[5];
__be16 user_mtu;
};
struct mlx4_set_port_rqp_calc_context {

Просмотреть файл

@ -50,7 +50,11 @@
#define MLX4_STATS_ERROR_COUNTERS_MASK 0x1ffc30ULL
#define MLX4_STATS_PORT_COUNTERS_MASK 0x1fe00000ULL
#define MLX4_FLAG_V_IGNORE_FCS_MASK 0x2
#define MLX4_FLAG2_V_IGNORE_FCS_MASK BIT(1)
#define MLX4_FLAG2_V_USER_MTU_MASK BIT(5)
#define MLX4_FLAG_V_MTU_MASK BIT(0)
#define MLX4_FLAG_V_PPRX_MASK BIT(1)
#define MLX4_FLAG_V_PPTX_MASK BIT(2)
#define MLX4_IGNORE_FCS_MASK 0x1
#define MLX4_TC_MAX_NUMBER 8
@ -1239,13 +1243,96 @@ void mlx4_reset_roce_gids(struct mlx4_dev *dev, int slave)
return;
}
static void
mlx4_en_set_port_mtu(struct mlx4_dev *dev, int slave, int port,
struct mlx4_set_port_general_context *gen_context)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master;
struct mlx4_slave_state *slave_st = &master->slave_state[slave];
u16 mtu, prev_mtu;
/* Mtu is configured as the max USER_MTU among all
* the functions on the port.
*/
mtu = be16_to_cpu(gen_context->mtu);
mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port] +
ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
prev_mtu = slave_st->mtu[port];
slave_st->mtu[port] = mtu;
if (mtu > master->max_mtu[port])
master->max_mtu[port] = mtu;
if (mtu < prev_mtu && prev_mtu == master->max_mtu[port]) {
int i;
slave_st->mtu[port] = mtu;
master->max_mtu[port] = mtu;
for (i = 0; i < dev->num_slaves; i++)
master->max_mtu[port] =
max_t(u16, master->max_mtu[port],
master->slave_state[i].mtu[port]);
}
gen_context->mtu = cpu_to_be16(master->max_mtu[port]);
}
static void
mlx4_en_set_port_user_mtu(struct mlx4_dev *dev, int slave, int port,
struct mlx4_set_port_general_context *gen_context)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master;
struct mlx4_slave_state *slave_st = &master->slave_state[slave];
u16 user_mtu, prev_user_mtu;
/* User Mtu is configured as the max USER_MTU among all
* the functions on the port.
*/
user_mtu = be16_to_cpu(gen_context->user_mtu);
user_mtu = min_t(int, user_mtu, dev->caps.eth_mtu_cap[port]);
prev_user_mtu = slave_st->user_mtu[port];
slave_st->user_mtu[port] = user_mtu;
if (user_mtu > master->max_user_mtu[port])
master->max_user_mtu[port] = user_mtu;
if (user_mtu < prev_user_mtu &&
prev_user_mtu == master->max_user_mtu[port]) {
int i;
slave_st->user_mtu[port] = user_mtu;
master->max_user_mtu[port] = user_mtu;
for (i = 0; i < dev->num_slaves; i++)
master->max_user_mtu[port] =
max_t(u16, master->max_user_mtu[port],
master->slave_state[i].user_mtu[port]);
}
gen_context->user_mtu = cpu_to_be16(master->max_user_mtu[port]);
}
static void
mlx4_en_set_port_global_pause(struct mlx4_dev *dev, int slave,
struct mlx4_set_port_general_context *gen_context)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master;
/* Slave cannot change Global Pause configuration */
if (slave != mlx4_master_func_num(dev) &&
(gen_context->pptx != master->pptx ||
gen_context->pprx != master->pprx)) {
gen_context->pptx = master->pptx;
gen_context->pprx = master->pprx;
mlx4_warn(dev, "denying Global Pause change for slave:%d\n",
slave);
} else {
master->pptx = gen_context->pptx;
master->pprx = gen_context->pprx;
}
}
static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
u8 op_mod, struct mlx4_cmd_mailbox *inbox)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_port_info *port_info;
struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master;
struct mlx4_slave_state *slave_st = &master->slave_state[slave];
struct mlx4_set_port_rqp_calc_context *qpn_context;
struct mlx4_set_port_general_context *gen_context;
struct mlx4_roce_gid_entry *gid_entry_tbl, *gid_entry_mbox, *gid_entry_mb1;
@ -1256,7 +1343,6 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
int base;
u32 in_modifier;
u32 promisc;
u16 mtu, prev_mtu;
int err;
int i, j;
int offset;
@ -1269,7 +1355,9 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
is_eth = op_mod;
port_info = &priv->port[port];
/* Slaves cannot perform SET_PORT operations except changing MTU */
/* Slaves cannot perform SET_PORT operations,
* except for changing MTU and USER_MTU.
*/
if (is_eth) {
if (slave != dev->caps.function &&
in_modifier != MLX4_SET_PORT_GENERAL &&
@ -1297,40 +1385,20 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
break;
case MLX4_SET_PORT_GENERAL:
gen_context = inbox->buf;
/* Mtu is configured as the max MTU among all the
* the functions on the port. */
mtu = be16_to_cpu(gen_context->mtu);
mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port] +
ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
prev_mtu = slave_st->mtu[port];
slave_st->mtu[port] = mtu;
if (mtu > master->max_mtu[port])
master->max_mtu[port] = mtu;
if (mtu < prev_mtu && prev_mtu ==
master->max_mtu[port]) {
slave_st->mtu[port] = mtu;
master->max_mtu[port] = mtu;
for (i = 0; i < dev->num_slaves; i++) {
master->max_mtu[port] =
max(master->max_mtu[port],
master->slave_state[i].mtu[port]);
}
}
gen_context->mtu = cpu_to_be16(master->max_mtu[port]);
/* Slave cannot change Global Pause configuration */
if (slave != mlx4_master_func_num(dev) &&
((gen_context->pptx != master->pptx) ||
(gen_context->pprx != master->pprx))) {
gen_context->pptx = master->pptx;
gen_context->pprx = master->pprx;
mlx4_warn(dev,
"denying Global Pause change for slave:%d\n",
slave);
} else {
master->pptx = gen_context->pptx;
master->pprx = gen_context->pprx;
}
if (gen_context->flags & MLX4_FLAG_V_MTU_MASK)
mlx4_en_set_port_mtu(dev, slave, port,
gen_context);
if (gen_context->flags2 & MLX4_FLAG2_V_USER_MTU_MASK)
mlx4_en_set_port_user_mtu(dev, slave, port,
gen_context);
if (gen_context->flags &
(MLX4_FLAG_V_PPRX_MASK || MLX4_FLAG_V_PPTX_MASK))
mlx4_en_set_port_global_pause(dev, slave,
gen_context);
break;
case MLX4_SET_PORT_GID_TABLE:
/* change to MULTIPLE entries: number of guest's gids
@ -1608,6 +1676,30 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
}
EXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc);
int mlx4_SET_PORT_user_mtu(struct mlx4_dev *dev, u8 port, u16 user_mtu)
{
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_set_port_general_context *context;
u32 in_mod;
int err;
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
context = mailbox->buf;
context->flags2 |= MLX4_FLAG2_V_USER_MTU_MASK;
context->user_mtu = cpu_to_be16(user_mtu);
in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
err = mlx4_cmd(dev, mailbox->dma, in_mod, MLX4_SET_PORT_ETH_OPCODE,
MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_WRAPPED);
mlx4_free_cmd_mailbox(dev, mailbox);
return err;
}
EXPORT_SYMBOL(mlx4_SET_PORT_user_mtu);
int mlx4_SET_PORT_fcs_check(struct mlx4_dev *dev, u8 port, u8 ignore_fcs_value)
{
struct mlx4_cmd_mailbox *mailbox;
@ -1619,7 +1711,7 @@ int mlx4_SET_PORT_fcs_check(struct mlx4_dev *dev, u8 port, u8 ignore_fcs_value)
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
context = mailbox->buf;
context->v_ignore_fcs |= MLX4_FLAG_V_IGNORE_FCS_MASK;
context->flags2 |= MLX4_FLAG2_V_IGNORE_FCS_MASK;
if (ignore_fcs_value)
context->ignore_fcs |= MLX4_IGNORE_FCS_MASK;
else

Просмотреть файл

@ -77,6 +77,7 @@ struct res_common {
int from_state;
int to_state;
int removing;
const char *func_name;
};
enum {
@ -837,6 +838,36 @@ static int mpt_mask(struct mlx4_dev *dev)
return dev->caps.num_mpts - 1;
}
static const char *mlx4_resource_type_to_str(enum mlx4_resource t)
{
switch (t) {
case RES_QP:
return "QP";
case RES_CQ:
return "CQ";
case RES_SRQ:
return "SRQ";
case RES_XRCD:
return "XRCD";
case RES_MPT:
return "MPT";
case RES_MTT:
return "MTT";
case RES_MAC:
return "MAC";
case RES_VLAN:
return "VLAN";
case RES_COUNTER:
return "COUNTER";
case RES_FS_RULE:
return "FS_RULE";
case RES_EQ:
return "EQ";
default:
return "INVALID RESOURCE";
}
}
static void *find_res(struct mlx4_dev *dev, u64 res_id,
enum mlx4_resource type)
{
@ -846,9 +877,9 @@ static void *find_res(struct mlx4_dev *dev, u64 res_id,
res_id);
}
static int get_res(struct mlx4_dev *dev, int slave, u64 res_id,
enum mlx4_resource type,
void *res)
static int _get_res(struct mlx4_dev *dev, int slave, u64 res_id,
enum mlx4_resource type,
void *res, const char *func_name)
{
struct res_common *r;
int err = 0;
@ -861,6 +892,10 @@ static int get_res(struct mlx4_dev *dev, int slave, u64 res_id,
}
if (r->state == RES_ANY_BUSY) {
mlx4_warn(dev,
"%s(%d) trying to get resource %llx of type %s, but it's already taken by %s\n",
func_name, slave, res_id, mlx4_resource_type_to_str(type),
r->func_name);
err = -EBUSY;
goto exit;
}
@ -872,6 +907,7 @@ static int get_res(struct mlx4_dev *dev, int slave, u64 res_id,
r->from_state = r->state;
r->state = RES_ANY_BUSY;
r->func_name = func_name;
if (res)
*((struct res_common **)res) = r;
@ -881,6 +917,9 @@ exit:
return err;
}
#define get_res(dev, slave, res_id, type, res) \
_get_res((dev), (slave), (res_id), (type), (res), __func__)
int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev,
enum mlx4_resource type,
u64 res_id, int *slave)
@ -911,8 +950,10 @@ static void put_res(struct mlx4_dev *dev, int slave, u64 res_id,
spin_lock_irq(mlx4_tlock(dev));
r = find_res(dev, res_id, type);
if (r)
if (r) {
r->state = r->from_state;
r->func_name = "";
}
spin_unlock_irq(mlx4_tlock(dev));
}
@ -1396,7 +1437,7 @@ static int remove_ok(struct res_common *res, enum mlx4_resource type, int extra)
case RES_MTT:
return remove_mtt_ok((struct res_mtt *)res, extra);
case RES_MAC:
return -ENOSYS;
return -EOPNOTSUPP;
case RES_EQ:
return remove_eq_ok((struct res_eq *)res);
case RES_COUNTER:

Просмотреть файл

@ -1374,6 +1374,7 @@ int mlx4_get_base_qpn(struct mlx4_dev *dev, u8 port);
int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac);
int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx);
int mlx4_SET_PORT_user_mtu(struct mlx4_dev *dev, u8 port, u16 user_mtu);
int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
u8 promisc);
int mlx4_SET_PORT_BEACON(struct mlx4_dev *dev, u8 port, u16 time);
@ -1539,8 +1540,13 @@ enum mlx4_ptys_proto {
MLX4_PTYS_EN = 1<<2,
};
enum mlx4_ptys_flags {
MLX4_PTYS_AN_DISABLE_CAP = 1 << 5,
MLX4_PTYS_AN_DISABLE_ADMIN = 1 << 6,
};
struct mlx4_ptys_reg {
u8 resrvd1;
u8 flags;
u8 local_port;
u8 resrvd2;
u8 proto_mask;