Merge branch 'mlx4-next'

Amir Vadai says:

====================
Mellanox driver update Jul-22-2014

This patchset contains a fix by Eyal to fix a bug in mlx4_en with bonding
alb/tlb mode.
The second patch, by me, is an ethtool private flag that enable turning off the
BlueFlame hardware feature.
The last two patches, introduce a new low memory profile for mlx4_en and
mlx4_core. This mode is useful when running from a limited resources
environment, like kdump. This will reduce the memory consumed by both drivers
from more than 100M to ~30M.

This patchset was applied and tested on commit 575a193 ("net: mvpp2: Fix error
return code in mvpp2_probe")
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2014-07-22 19:53:55 -07:00
commit 2dbe82d0d1
8 changed files with 113 additions and 11 deletions

View File

@ -98,6 +98,10 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
drvinfo->eedump_len = 0; drvinfo->eedump_len = 0;
} }
static const char mlx4_en_priv_flags[][ETH_GSTRING_LEN] = {
"blueflame",
};
static const char main_strings[][ETH_GSTRING_LEN] = { static const char main_strings[][ETH_GSTRING_LEN] = {
"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
@ -235,6 +239,8 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
case ETH_SS_TEST: case ETH_SS_TEST:
return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
& MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2; & MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;
case ETH_SS_PRIV_FLAGS:
return ARRAY_SIZE(mlx4_en_priv_flags);
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
@ -358,6 +364,12 @@ static void mlx4_en_get_strings(struct net_device *dev,
#endif #endif
} }
break; break;
case ETH_SS_PRIV_FLAGS:
for (i = 0; i < ARRAY_SIZE(mlx4_en_priv_flags); i++)
strcpy(data + i * ETH_GSTRING_LEN,
mlx4_en_priv_flags[i]);
break;
} }
} }
@ -1209,6 +1221,49 @@ static int mlx4_en_get_ts_info(struct net_device *dev,
return ret; return ret;
} }
int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
bool bf_enabled_new = !!(flags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);
bool bf_enabled_old = !!(priv->pflags & MLX4_EN_PRIV_FLAGS_BLUEFLAME);
int i;
if (bf_enabled_new == bf_enabled_old)
return 0; /* Nothing to do */
if (bf_enabled_new) {
bool bf_supported = true;
for (i = 0; i < priv->tx_ring_num; i++)
bf_supported &= priv->tx_ring[i]->bf_alloced;
if (!bf_supported) {
en_err(priv, "BlueFlame is not supported\n");
return -EINVAL;
}
priv->pflags |= MLX4_EN_PRIV_FLAGS_BLUEFLAME;
} else {
priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME;
}
for (i = 0; i < priv->tx_ring_num; i++)
priv->tx_ring[i]->bf_enabled = bf_enabled_new;
en_info(priv, "BlueFlame %s\n",
bf_enabled_new ? "Enabled" : "Disabled");
return 0;
}
u32 mlx4_en_get_priv_flags(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
return priv->pflags;
}
const struct ethtool_ops mlx4_en_ethtool_ops = { const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_drvinfo = mlx4_en_get_drvinfo, .get_drvinfo = mlx4_en_get_drvinfo,
.get_settings = mlx4_en_get_settings, .get_settings = mlx4_en_get_settings,
@ -1236,6 +1291,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_channels = mlx4_en_get_channels, .get_channels = mlx4_en_get_channels,
.set_channels = mlx4_en_set_channels, .set_channels = mlx4_en_set_channels,
.get_ts_info = mlx4_en_get_ts_info, .get_ts_info = mlx4_en_get_ts_info,
.set_priv_flags = mlx4_en_set_priv_flags,
.get_priv_flags = mlx4_en_get_priv_flags,
}; };

View File

@ -129,8 +129,10 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
int i; int i;
params->udp_rss = udp_rss; params->udp_rss = udp_rss;
params->num_tx_rings_p_up = min_t(int, num_online_cpus(), params->num_tx_rings_p_up = mlx4_low_memory_profile() ?
MLX4_EN_MAX_TX_RING_P_UP); MLX4_EN_MIN_TX_RING_P_UP :
min_t(int, num_online_cpus(), MLX4_EN_MAX_TX_RING_P_UP);
if (params->udp_rss && !(mdev->dev->caps.flags if (params->udp_rss && !(mdev->dev->caps.flags
& MLX4_DEV_CAP_FLAG_UDP_RSS)) { & MLX4_DEV_CAP_FLAG_UDP_RSS)) {
mlx4_warn(mdev, "UDP RSS is not supported on this device\n"); mlx4_warn(mdev, "UDP RSS is not supported on this device\n");

View File

@ -644,6 +644,7 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
goto alloc_err; goto alloc_err;
} }
memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac)); memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac));
memcpy(priv->current_mac, entry->mac, sizeof(priv->current_mac));
entry->reg_id = reg_id; entry->reg_id = reg_id;
hlist_add_head_rcu(&entry->hlist, hlist_add_head_rcu(&entry->hlist,
@ -2464,6 +2465,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
priv->port = port; priv->port = port;
priv->port_up = false; priv->port_up = false;
priv->flags = prof->flags; priv->flags = prof->flags;
priv->pflags = MLX4_EN_PRIV_FLAGS_BLUEFLAME;
priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE | priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
MLX4_WQE_CTRL_SOLICITED); MLX4_WQE_CTRL_SOLICITED);
priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up; priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;

View File

@ -335,8 +335,9 @@ void mlx4_en_set_num_rx_rings(struct mlx4_en_dev *mdev)
dev->caps.comp_pool/ dev->caps.comp_pool/
dev->caps.num_ports) - 1; dev->caps.num_ports) - 1;
num_rx_rings = min_t(int, num_of_eqs, num_rx_rings = mlx4_low_memory_profile() ? MIN_RX_RINGS :
netif_get_num_default_rss_queues()); min_t(int, num_of_eqs,
netif_get_num_default_rss_queues());
mdev->profile.prof[i].rx_ring_num = mdev->profile.prof[i].rx_ring_num =
rounddown_pow_of_two(num_rx_rings); rounddown_pow_of_two(num_rx_rings);
} }

View File

@ -126,8 +126,13 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
ring->bf.uar = &mdev->priv_uar; ring->bf.uar = &mdev->priv_uar;
ring->bf.uar->map = mdev->uar_map; ring->bf.uar->map = mdev->uar_map;
ring->bf_enabled = false; ring->bf_enabled = false;
} else ring->bf_alloced = false;
ring->bf_enabled = true; priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME;
} else {
ring->bf_alloced = true;
ring->bf_enabled = !!(priv->pflags &
MLX4_EN_PRIV_FLAGS_BLUEFLAME);
}
ring->hwtstamp_tx_type = priv->hwtstamp_config.tx_type; ring->hwtstamp_tx_type = priv->hwtstamp_config.tx_type;
ring->queue_index = queue_index; ring->queue_index = queue_index;
@ -161,7 +166,7 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring = *pring; struct mlx4_en_tx_ring *ring = *pring;
en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn); en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
if (ring->bf_enabled) if (ring->bf_alloced)
mlx4_bf_free(mdev->dev, &ring->bf); mlx4_bf_free(mdev->dev, &ring->bf);
mlx4_qp_remove(mdev->dev, &ring->qp); mlx4_qp_remove(mdev->dev, &ring->qp);
mlx4_qp_free(mdev->dev, &ring->qp); mlx4_qp_free(mdev->dev, &ring->qp);
@ -195,7 +200,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn, mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
ring->cqn, user_prio, &ring->context); ring->cqn, user_prio, &ring->context);
if (ring->bf_enabled) if (ring->bf_alloced)
ring->context.usr_page = cpu_to_be32(ring->bf.uar->index); ring->context.usr_page = cpu_to_be32(ring->bf.uar->index);
err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context, err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,

View File

@ -120,6 +120,16 @@ static struct mlx4_profile default_profile = {
.num_mtt = 1 << 20, /* It is really num mtt segements */ .num_mtt = 1 << 20, /* It is really num mtt segements */
}; };
static struct mlx4_profile low_mem_profile = {
.num_qp = 1 << 17,
.num_srq = 1 << 6,
.rdmarc_per_qp = 1 << 4,
.num_cq = 1 << 8,
.num_mcg = 1 << 8,
.num_mpt = 1 << 9,
.num_mtt = 1 << 7,
};
static int log_num_mac = 7; static int log_num_mac = 7;
module_param_named(log_num_mac, log_num_mac, int, 0444); module_param_named(log_num_mac, log_num_mac, int, 0444);
MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)"); MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)");
@ -129,6 +139,8 @@ module_param_named(log_num_vlan, log_num_vlan, int, 0444);
MODULE_PARM_DESC(log_num_vlan, "Log2 max number of VLANs per ETH port (0-7)"); MODULE_PARM_DESC(log_num_vlan, "Log2 max number of VLANs per ETH port (0-7)");
/* Log2 max number of VLANs per ETH port (0-7) */ /* Log2 max number of VLANs per ETH port (0-7) */
#define MLX4_LOG_NUM_VLANS 7 #define MLX4_LOG_NUM_VLANS 7
#define MLX4_MIN_LOG_NUM_VLANS 0
#define MLX4_MIN_LOG_NUM_MAC 1
static bool use_prio; static bool use_prio;
module_param_named(use_prio, use_prio, bool, 0444); module_param_named(use_prio, use_prio, bool, 0444);
@ -287,8 +299,13 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
if (mlx4_is_mfunc(dev)) if (mlx4_is_mfunc(dev))
dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_SENSE_SUPPORT; dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_SENSE_SUPPORT;
dev->caps.log_num_macs = log_num_mac; if (mlx4_low_memory_profile()) {
dev->caps.log_num_vlans = MLX4_LOG_NUM_VLANS; dev->caps.log_num_macs = MLX4_MIN_LOG_NUM_MAC;
dev->caps.log_num_vlans = MLX4_MIN_LOG_NUM_VLANS;
} else {
dev->caps.log_num_macs = log_num_mac;
dev->caps.log_num_vlans = MLX4_LOG_NUM_VLANS;
}
for (i = 1; i <= dev->caps.num_ports; ++i) { for (i = 1; i <= dev->caps.num_ports; ++i) {
dev->caps.port_type[i] = MLX4_PORT_TYPE_NONE; dev->caps.port_type[i] = MLX4_PORT_TYPE_NONE;
@ -1587,7 +1604,12 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
if (mlx4_is_master(dev)) if (mlx4_is_master(dev))
mlx4_parav_master_pf_caps(dev); mlx4_parav_master_pf_caps(dev);
profile = default_profile; if (mlx4_low_memory_profile()) {
mlx4_info(dev, "Running from within kdump kernel. Using low memory profile\n");
profile = low_mem_profile;
} else {
profile = default_profile;
}
if (dev->caps.steering_mode == if (dev->caps.steering_mode ==
MLX4_STEERING_MODE_DEVICE_MANAGED) MLX4_STEERING_MODE_DEVICE_MANAGED)
profile.num_mcg = MLX4_FS_NUM_MCG; profile.num_mcg = MLX4_FS_NUM_MCG;

View File

@ -93,6 +93,8 @@
* OS related constants and tunables * OS related constants and tunables
*/ */
#define MLX4_EN_PRIV_FLAGS_BLUEFLAME 1
#define MLX4_EN_WATCHDOG_TIMEOUT (15 * HZ) #define MLX4_EN_WATCHDOG_TIMEOUT (15 * HZ)
/* Use the maximum between 16384 and a single page */ /* Use the maximum between 16384 and a single page */
@ -119,6 +121,7 @@ enum {
#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE) #define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE)
#define MLX4_EN_SMALL_PKT_SIZE 64 #define MLX4_EN_SMALL_PKT_SIZE 64
#define MLX4_EN_MIN_TX_RING_P_UP 1
#define MLX4_EN_MAX_TX_RING_P_UP 32 #define MLX4_EN_MAX_TX_RING_P_UP 32
#define MLX4_EN_NUM_UP 8 #define MLX4_EN_NUM_UP 8
#define MLX4_EN_DEF_TX_RING_SIZE 512 #define MLX4_EN_DEF_TX_RING_SIZE 512
@ -278,6 +281,7 @@ struct mlx4_en_tx_ring {
unsigned long wake_queue; unsigned long wake_queue;
struct mlx4_bf bf; struct mlx4_bf bf;
bool bf_enabled; bool bf_enabled;
bool bf_alloced;
struct netdev_queue *tx_queue; struct netdev_queue *tx_queue;
int hwtstamp_tx_type; int hwtstamp_tx_type;
int inline_thold; int inline_thold;
@ -592,6 +596,8 @@ struct mlx4_en_priv {
#endif #endif
u64 tunnel_reg_id; u64 tunnel_reg_id;
__be16 vxlan_port; __be16 vxlan_port;
u32 pflags;
}; };
enum mlx4_en_wol { enum mlx4_en_wol {

View File

@ -1254,4 +1254,11 @@ int mlx4_vf_smi_enabled(struct mlx4_dev *dev, int slave, int port);
int mlx4_vf_get_enable_smi_admin(struct mlx4_dev *dev, int slave, int port); int mlx4_vf_get_enable_smi_admin(struct mlx4_dev *dev, int slave, int port);
int mlx4_vf_set_enable_smi_admin(struct mlx4_dev *dev, int slave, int port, int mlx4_vf_set_enable_smi_admin(struct mlx4_dev *dev, int slave, int port,
int enable); int enable);
/* Returns true if running in low memory profile (kdump kernel) */
static inline bool mlx4_low_memory_profile(void)
{
return reset_devices;
}
#endif /* MLX4_DEVICE_H */ #endif /* MLX4_DEVICE_H */