Loading drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +103 −44 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ #include <linux/ethtool.h> #include <linux/netdevice.h> #include <linux/mlx4/driver.h> #include <linux/in.h> #include <net/ip.h> #include "mlx4_en.h" #include "en_port.h" Loading Loading @@ -494,7 +496,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev, mutex_lock(&mdev->state_lock); if (priv->port_up) { port_up = 1; mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 1); } mlx4_en_free_resources(priv); Loading Loading @@ -589,7 +591,7 @@ static int mlx4_en_set_rxfh_indir(struct net_device *dev, mutex_lock(&mdev->state_lock); if (priv->port_up) { port_up = 1; mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 1); } priv->prof->rss_rings = rss_rings; Loading Loading @@ -664,27 +666,88 @@ static int mlx4_en_validate_flow(struct net_device *dev, if ((cmd->fs.flow_type & FLOW_EXT)) { if (cmd->fs.m_ext.vlan_etype || !(cmd->fs.m_ext.vlan_tci == 0 || cmd->fs.m_ext.vlan_tci == cpu_to_be16(0xfff))) !((cmd->fs.m_ext.vlan_tci & cpu_to_be16(VLAN_VID_MASK)) == 0 || (cmd->fs.m_ext.vlan_tci & cpu_to_be16(VLAN_VID_MASK)) == cpu_to_be16(VLAN_VID_MASK))) return -EINVAL; if (cmd->fs.m_ext.vlan_tci) { if (be16_to_cpu(cmd->fs.h_ext.vlan_tci) >= VLAN_N_VID) return -EINVAL; } } return 0; } static int mlx4_en_ethtool_add_mac_rule(struct ethtool_rxnfc *cmd, struct list_head *rule_list_h, struct mlx4_spec_list *spec_l2, unsigned char *mac) { int err = 0; __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16); spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH; memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN); memcpy(spec_l2->eth.dst_mac, mac, ETH_ALEN); if ((cmd->fs.flow_type & FLOW_EXT) && (cmd->fs.m_ext.vlan_tci & cpu_to_be16(VLAN_VID_MASK))) { spec_l2->eth.vlan_id = cmd->fs.h_ext.vlan_tci; spec_l2->eth.vlan_id_msk = cpu_to_be16(VLAN_VID_MASK); } list_add_tail(&spec_l2->list, rule_list_h); return err; } static int mlx4_en_ethtool_add_mac_rule_by_ipv4(struct mlx4_en_priv *priv, struct ethtool_rxnfc *cmd, struct list_head *rule_list_h, struct mlx4_spec_list *spec_l2, __be32 ipv4_dst) { __be64 be_mac = 0; unsigned char mac[ETH_ALEN]; if (!ipv4_is_multicast(ipv4_dst)) { if (cmd->fs.flow_type & FLOW_MAC_EXT) { memcpy(&mac, cmd->fs.h_ext.h_dest, ETH_ALEN); } else { be_mac = cpu_to_be64((priv->mac & MLX4_MAC_MASK) << 16); memcpy(&mac, &be_mac, ETH_ALEN); } } else { ip_eth_mc_map(ipv4_dst, mac); } return mlx4_en_ethtool_add_mac_rule(cmd, rule_list_h, spec_l2, &mac[0]); } static int add_ip_rule(struct mlx4_en_priv *priv, struct ethtool_rxnfc *cmd, struct list_head *list_h) { struct mlx4_spec_list *spec_l3; struct mlx4_spec_list *spec_l2 = NULL; struct mlx4_spec_list *spec_l3 = NULL; struct ethtool_usrip4_spec *l3_mask = &cmd->fs.m_u.usr_ip4_spec; spec_l3 = kzalloc(sizeof *spec_l3, GFP_KERNEL); if (!spec_l3) { spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL); spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL); if (!spec_l2 || !spec_l3) { en_err(priv, "Fail to alloc ethtool rule.\n"); kfree(spec_l2); kfree(spec_l3); return -ENOMEM; } mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h, spec_l2, cmd->fs.h_u. usr_ip4_spec.ip4dst); spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4; spec_l3->ipv4.src_ip = cmd->fs.h_u.usr_ip4_spec.ip4src; if (l3_mask->ip4src) Loading @@ -701,14 +764,17 @@ static int add_tcp_udp_rule(struct mlx4_en_priv *priv, struct ethtool_rxnfc *cmd, struct list_head *list_h, int proto) { struct mlx4_spec_list *spec_l3; struct mlx4_spec_list *spec_l4; struct mlx4_spec_list *spec_l2 = NULL; struct mlx4_spec_list *spec_l3 = NULL; struct mlx4_spec_list *spec_l4 = NULL; struct ethtool_tcpip4_spec *l4_mask = &cmd->fs.m_u.tcp_ip4_spec; spec_l3 = kzalloc(sizeof *spec_l3, GFP_KERNEL); spec_l4 = kzalloc(sizeof *spec_l4, GFP_KERNEL); if (!spec_l4 || !spec_l3) { spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL); spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL); spec_l4 = kzalloc(sizeof(*spec_l4), GFP_KERNEL); if (!spec_l2 || !spec_l3 || !spec_l4) { en_err(priv, "Fail to alloc ethtool rule.\n"); kfree(spec_l2); kfree(spec_l3); kfree(spec_l4); return -ENOMEM; Loading @@ -717,12 +783,20 @@ static int add_tcp_udp_rule(struct mlx4_en_priv *priv, spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4; if (proto == TCP_V4_FLOW) { mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h, spec_l2, cmd->fs.h_u. tcp_ip4_spec.ip4dst); spec_l4->id = MLX4_NET_TRANS_RULE_ID_TCP; spec_l3->ipv4.src_ip = cmd->fs.h_u.tcp_ip4_spec.ip4src; spec_l3->ipv4.dst_ip = cmd->fs.h_u.tcp_ip4_spec.ip4dst; spec_l4->tcp_udp.src_port = cmd->fs.h_u.tcp_ip4_spec.psrc; spec_l4->tcp_udp.dst_port = cmd->fs.h_u.tcp_ip4_spec.pdst; } else { mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h, spec_l2, cmd->fs.h_u. udp_ip4_spec.ip4dst); spec_l4->id = MLX4_NET_TRANS_RULE_ID_UDP; spec_l3->ipv4.src_ip = cmd->fs.h_u.udp_ip4_spec.ip4src; spec_l3->ipv4.dst_ip = cmd->fs.h_u.udp_ip4_spec.ip4dst; Loading Loading @@ -751,43 +825,23 @@ static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev, struct list_head *rule_list_h) { int err; __be64 be_mac; struct ethhdr *eth_spec; struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_spec_list *spec_l2; __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16); struct mlx4_en_priv *priv = netdev_priv(dev); err = mlx4_en_validate_flow(dev, cmd); if (err) return err; spec_l2 = kzalloc(sizeof *spec_l2, GFP_KERNEL); switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { case ETHER_FLOW: spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL); if (!spec_l2) return -ENOMEM; if (cmd->fs.flow_type & FLOW_MAC_EXT) { memcpy(&be_mac, cmd->fs.h_ext.h_dest, ETH_ALEN); } else { u64 mac = priv->mac & MLX4_MAC_MASK; be_mac = cpu_to_be64(mac << 16); } spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH; memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN); if ((cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) != ETHER_FLOW) memcpy(spec_l2->eth.dst_mac, &be_mac, ETH_ALEN); if ((cmd->fs.flow_type & FLOW_EXT) && cmd->fs.m_ext.vlan_tci) { spec_l2->eth.vlan_id = cmd->fs.h_ext.vlan_tci; spec_l2->eth.vlan_id_msk = cpu_to_be16(0xfff); } list_add_tail(&spec_l2->list, rule_list_h); switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { case ETHER_FLOW: eth_spec = &cmd->fs.h_u.ether_spec; memcpy(&spec_l2->eth.dst_mac, eth_spec->h_dest, ETH_ALEN); mlx4_en_ethtool_add_mac_rule(cmd, rule_list_h, spec_l2, ð_spec->h_dest[0]); spec_l2->eth.ether_type = eth_spec->h_proto; if (eth_spec->h_proto) spec_l2->eth.ether_type_enable = 1; Loading Loading @@ -861,6 +915,7 @@ static int mlx4_en_flow_replace(struct net_device *dev, loc_rule->id = 0; memset(&loc_rule->flow_spec, 0, sizeof(struct ethtool_rx_flow_spec)); list_del(&loc_rule->list); } err = mlx4_flow_attach(priv->mdev->dev, &rule, ®_id); if (err) { Loading @@ -871,6 +926,7 @@ static int mlx4_en_flow_replace(struct net_device *dev, loc_rule->id = reg_id; memcpy(&loc_rule->flow_spec, &cmd->fs, sizeof(struct ethtool_rx_flow_spec)); list_add_tail(&loc_rule->list, &priv->ethtool_list); out_free_list: list_for_each_entry_safe(spec, tmp_spec, &rule.list, list) { Loading Loading @@ -904,6 +960,7 @@ static int mlx4_en_flow_detach(struct net_device *dev, } rule->id = 0; memset(&rule->flow_spec, 0, sizeof(struct ethtool_rx_flow_spec)); list_del(&rule->list); out: return err; Loading Loading @@ -952,7 +1009,8 @@ static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, if ((cmd->cmd == ETHTOOL_GRXCLSRLCNT || cmd->cmd == ETHTOOL_GRXCLSRULE || cmd->cmd == ETHTOOL_GRXCLSRLALL) && mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED || !priv->port_up)) return -EINVAL; switch (cmd->cmd) { Loading Loading @@ -988,7 +1046,8 @@ static int mlx4_en_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED || !priv->port_up) return -EINVAL; switch (cmd->cmd) { Loading Loading @@ -1037,7 +1096,7 @@ static int mlx4_en_set_channels(struct net_device *dev, mutex_lock(&mdev->state_lock); if (priv->port_up) { port_up = 1; mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 1); } mlx4_en_free_resources(priv); Loading drivers/net/ethernet/mellanox/mlx4/en_netdev.c +27 −5 Original line number Diff line number Diff line Loading @@ -1039,6 +1039,9 @@ int mlx4_en_start_port(struct net_device *dev) INIT_LIST_HEAD(&priv->mc_list); INIT_LIST_HEAD(&priv->curr_list); INIT_LIST_HEAD(&priv->ethtool_list); memset(&priv->ethtool_rules[0], 0, sizeof(struct ethtool_flow_id) * MAX_NUM_OF_FS_RULES); /* Calculate Rx buf size */ dev->mtu = min(dev->mtu, priv->max_mtu); Loading Loading @@ -1175,6 +1178,8 @@ int mlx4_en_start_port(struct net_device *dev) priv->port_up = true; netif_tx_start_all_queues(dev); netif_device_attach(dev); return 0; tx_err: Loading @@ -1197,11 +1202,12 @@ int mlx4_en_start_port(struct net_device *dev) } void mlx4_en_stop_port(struct net_device *dev) void mlx4_en_stop_port(struct net_device *dev, int detach) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_mc_list *mclist, *tmp; struct ethtool_flow_id *flow, *tmp_flow; int i; u8 mc_list[16] = {0}; Loading @@ -1212,9 +1218,13 @@ void mlx4_en_stop_port(struct net_device *dev) /* Synchronize with tx routine */ netif_tx_lock_bh(dev); if (detach) netif_device_detach(dev); netif_tx_stop_all_queues(dev); netif_tx_unlock_bh(dev); netif_tx_disable(dev); /* Set port as not active */ priv->port_up = false; Loading Loading @@ -1281,8 +1291,20 @@ void mlx4_en_stop_port(struct net_device *dev) /* Unregister Mac address for the port */ mlx4_put_eth_qp(mdev->dev, priv->port, priv->mac, priv->base_qpn); if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN)) mdev->mac_removed[priv->port] = 1; /* Remove flow steering rules for the port*/ if (mdev->dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { ASSERT_RTNL(); list_for_each_entry_safe(flow, tmp_flow, &priv->ethtool_list, list) { mlx4_flow_detach(mdev->dev, flow->id); list_del(&flow->list); } } /* Free RX Rings */ for (i = 0; i < priv->rx_ring_num; i++) { mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); Loading @@ -1307,7 +1329,7 @@ static void mlx4_en_restart(struct work_struct *work) mutex_lock(&mdev->state_lock); if (priv->port_up) { mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 1); for (i = 0; i < priv->tx_ring_num; i++) netdev_tx_reset_queue(priv->tx_ring[i].tx_queue); if (mlx4_en_start_port(dev)) Loading Loading @@ -1379,7 +1401,7 @@ static int mlx4_en_close(struct net_device *dev) mutex_lock(&mdev->state_lock); mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 0); netif_carrier_off(dev); mutex_unlock(&mdev->state_lock); Loading Loading @@ -1517,7 +1539,7 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) * the port */ en_dbg(DRV, priv, "Change MTU called with card down!?\n"); } else { mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 1); err = mlx4_en_start_port(dev); if (err) { en_err(priv, "Failed restarting port:%d\n", Loading drivers/net/ethernet/mellanox/mlx4/fw.c +8 −3 Original line number Diff line number Diff line Loading @@ -127,7 +127,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) [0] = "RSS support", [1] = "RSS Toeplitz Hash Function support", [2] = "RSS XOR Hash Function support", [3] = "Device manage flow steering support" [3] = "Device manage flow steering support", [4] = "Automatic mac reassignment support" }; int i; Loading Loading @@ -478,6 +479,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x94 #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98 #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0 #define QUERY_DEV_CAP_FW_REASSIGN_MAC 0x9d dev_cap->flags2 = 0; mailbox = mlx4_alloc_cmd_mailbox(dev); Loading Loading @@ -637,6 +639,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) QUERY_DEV_CAP_BMME_FLAGS_OFFSET); MLX4_GET(dev_cap->reserved_lkey, outbox, QUERY_DEV_CAP_RSVD_LKEY_OFFSET); MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC); if (field & 1<<6) dev_cap->flags2 |= MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN; MLX4_GET(dev_cap->max_icm_sz, outbox, QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET); if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS) Loading Loading @@ -1287,14 +1292,14 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) /* Enable Ethernet flow steering * with udp unicast and tcp unicast */ MLX4_PUT(inbox, param->fs_hash_enable_bits, MLX4_PUT(inbox, (u8) (MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN), INIT_HCA_FS_ETH_BITS_OFFSET); MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET); /* Enable IPoIB flow steering * with udp unicast and tcp unicast */ MLX4_PUT(inbox, param->fs_hash_enable_bits, MLX4_PUT(inbox, (u8) (MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN), INIT_HCA_FS_IB_BITS_OFFSET); MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, INIT_HCA_FS_IB_NUM_ADDRS_OFFSET); Loading drivers/net/ethernet/mellanox/mlx4/fw.h +0 −1 Original line number Diff line number Diff line Loading @@ -171,7 +171,6 @@ struct mlx4_init_hca_param { u8 log_mpt_sz; u8 log_uar_sz; u8 uar_page_sz; /* log pg sz in 4k chunks */ u8 fs_hash_enable_bits; u8 steering_mode; /* for QUERY_HCA */ u64 dev_cap_enabled; }; Loading drivers/net/ethernet/mellanox/mlx4/main.c +0 −16 Original line number Diff line number Diff line Loading @@ -1415,22 +1415,6 @@ static int mlx4_init_hca(struct mlx4_dev *dev) if (mlx4_is_master(dev)) mlx4_parav_master_pf_caps(dev); priv->fs_hash_mode = MLX4_FS_L2_HASH; switch (priv->fs_hash_mode) { case MLX4_FS_L2_HASH: init_hca.fs_hash_enable_bits = 0; break; case MLX4_FS_L2_L3_L4_HASH: /* Enable flow steering with * udp unicast and tcp unicast */ init_hca.fs_hash_enable_bits = MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN; break; } profile = default_profile; if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) Loading Loading
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +103 −44 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ #include <linux/ethtool.h> #include <linux/netdevice.h> #include <linux/mlx4/driver.h> #include <linux/in.h> #include <net/ip.h> #include "mlx4_en.h" #include "en_port.h" Loading Loading @@ -494,7 +496,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev, mutex_lock(&mdev->state_lock); if (priv->port_up) { port_up = 1; mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 1); } mlx4_en_free_resources(priv); Loading Loading @@ -589,7 +591,7 @@ static int mlx4_en_set_rxfh_indir(struct net_device *dev, mutex_lock(&mdev->state_lock); if (priv->port_up) { port_up = 1; mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 1); } priv->prof->rss_rings = rss_rings; Loading Loading @@ -664,27 +666,88 @@ static int mlx4_en_validate_flow(struct net_device *dev, if ((cmd->fs.flow_type & FLOW_EXT)) { if (cmd->fs.m_ext.vlan_etype || !(cmd->fs.m_ext.vlan_tci == 0 || cmd->fs.m_ext.vlan_tci == cpu_to_be16(0xfff))) !((cmd->fs.m_ext.vlan_tci & cpu_to_be16(VLAN_VID_MASK)) == 0 || (cmd->fs.m_ext.vlan_tci & cpu_to_be16(VLAN_VID_MASK)) == cpu_to_be16(VLAN_VID_MASK))) return -EINVAL; if (cmd->fs.m_ext.vlan_tci) { if (be16_to_cpu(cmd->fs.h_ext.vlan_tci) >= VLAN_N_VID) return -EINVAL; } } return 0; } static int mlx4_en_ethtool_add_mac_rule(struct ethtool_rxnfc *cmd, struct list_head *rule_list_h, struct mlx4_spec_list *spec_l2, unsigned char *mac) { int err = 0; __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16); spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH; memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN); memcpy(spec_l2->eth.dst_mac, mac, ETH_ALEN); if ((cmd->fs.flow_type & FLOW_EXT) && (cmd->fs.m_ext.vlan_tci & cpu_to_be16(VLAN_VID_MASK))) { spec_l2->eth.vlan_id = cmd->fs.h_ext.vlan_tci; spec_l2->eth.vlan_id_msk = cpu_to_be16(VLAN_VID_MASK); } list_add_tail(&spec_l2->list, rule_list_h); return err; } static int mlx4_en_ethtool_add_mac_rule_by_ipv4(struct mlx4_en_priv *priv, struct ethtool_rxnfc *cmd, struct list_head *rule_list_h, struct mlx4_spec_list *spec_l2, __be32 ipv4_dst) { __be64 be_mac = 0; unsigned char mac[ETH_ALEN]; if (!ipv4_is_multicast(ipv4_dst)) { if (cmd->fs.flow_type & FLOW_MAC_EXT) { memcpy(&mac, cmd->fs.h_ext.h_dest, ETH_ALEN); } else { be_mac = cpu_to_be64((priv->mac & MLX4_MAC_MASK) << 16); memcpy(&mac, &be_mac, ETH_ALEN); } } else { ip_eth_mc_map(ipv4_dst, mac); } return mlx4_en_ethtool_add_mac_rule(cmd, rule_list_h, spec_l2, &mac[0]); } static int add_ip_rule(struct mlx4_en_priv *priv, struct ethtool_rxnfc *cmd, struct list_head *list_h) { struct mlx4_spec_list *spec_l3; struct mlx4_spec_list *spec_l2 = NULL; struct mlx4_spec_list *spec_l3 = NULL; struct ethtool_usrip4_spec *l3_mask = &cmd->fs.m_u.usr_ip4_spec; spec_l3 = kzalloc(sizeof *spec_l3, GFP_KERNEL); if (!spec_l3) { spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL); spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL); if (!spec_l2 || !spec_l3) { en_err(priv, "Fail to alloc ethtool rule.\n"); kfree(spec_l2); kfree(spec_l3); return -ENOMEM; } mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h, spec_l2, cmd->fs.h_u. usr_ip4_spec.ip4dst); spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4; spec_l3->ipv4.src_ip = cmd->fs.h_u.usr_ip4_spec.ip4src; if (l3_mask->ip4src) Loading @@ -701,14 +764,17 @@ static int add_tcp_udp_rule(struct mlx4_en_priv *priv, struct ethtool_rxnfc *cmd, struct list_head *list_h, int proto) { struct mlx4_spec_list *spec_l3; struct mlx4_spec_list *spec_l4; struct mlx4_spec_list *spec_l2 = NULL; struct mlx4_spec_list *spec_l3 = NULL; struct mlx4_spec_list *spec_l4 = NULL; struct ethtool_tcpip4_spec *l4_mask = &cmd->fs.m_u.tcp_ip4_spec; spec_l3 = kzalloc(sizeof *spec_l3, GFP_KERNEL); spec_l4 = kzalloc(sizeof *spec_l4, GFP_KERNEL); if (!spec_l4 || !spec_l3) { spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL); spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL); spec_l4 = kzalloc(sizeof(*spec_l4), GFP_KERNEL); if (!spec_l2 || !spec_l3 || !spec_l4) { en_err(priv, "Fail to alloc ethtool rule.\n"); kfree(spec_l2); kfree(spec_l3); kfree(spec_l4); return -ENOMEM; Loading @@ -717,12 +783,20 @@ static int add_tcp_udp_rule(struct mlx4_en_priv *priv, spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4; if (proto == TCP_V4_FLOW) { mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h, spec_l2, cmd->fs.h_u. tcp_ip4_spec.ip4dst); spec_l4->id = MLX4_NET_TRANS_RULE_ID_TCP; spec_l3->ipv4.src_ip = cmd->fs.h_u.tcp_ip4_spec.ip4src; spec_l3->ipv4.dst_ip = cmd->fs.h_u.tcp_ip4_spec.ip4dst; spec_l4->tcp_udp.src_port = cmd->fs.h_u.tcp_ip4_spec.psrc; spec_l4->tcp_udp.dst_port = cmd->fs.h_u.tcp_ip4_spec.pdst; } else { mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h, spec_l2, cmd->fs.h_u. udp_ip4_spec.ip4dst); spec_l4->id = MLX4_NET_TRANS_RULE_ID_UDP; spec_l3->ipv4.src_ip = cmd->fs.h_u.udp_ip4_spec.ip4src; spec_l3->ipv4.dst_ip = cmd->fs.h_u.udp_ip4_spec.ip4dst; Loading Loading @@ -751,43 +825,23 @@ static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev, struct list_head *rule_list_h) { int err; __be64 be_mac; struct ethhdr *eth_spec; struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_spec_list *spec_l2; __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16); struct mlx4_en_priv *priv = netdev_priv(dev); err = mlx4_en_validate_flow(dev, cmd); if (err) return err; spec_l2 = kzalloc(sizeof *spec_l2, GFP_KERNEL); switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { case ETHER_FLOW: spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL); if (!spec_l2) return -ENOMEM; if (cmd->fs.flow_type & FLOW_MAC_EXT) { memcpy(&be_mac, cmd->fs.h_ext.h_dest, ETH_ALEN); } else { u64 mac = priv->mac & MLX4_MAC_MASK; be_mac = cpu_to_be64(mac << 16); } spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH; memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN); if ((cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) != ETHER_FLOW) memcpy(spec_l2->eth.dst_mac, &be_mac, ETH_ALEN); if ((cmd->fs.flow_type & FLOW_EXT) && cmd->fs.m_ext.vlan_tci) { spec_l2->eth.vlan_id = cmd->fs.h_ext.vlan_tci; spec_l2->eth.vlan_id_msk = cpu_to_be16(0xfff); } list_add_tail(&spec_l2->list, rule_list_h); switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { case ETHER_FLOW: eth_spec = &cmd->fs.h_u.ether_spec; memcpy(&spec_l2->eth.dst_mac, eth_spec->h_dest, ETH_ALEN); mlx4_en_ethtool_add_mac_rule(cmd, rule_list_h, spec_l2, ð_spec->h_dest[0]); spec_l2->eth.ether_type = eth_spec->h_proto; if (eth_spec->h_proto) spec_l2->eth.ether_type_enable = 1; Loading Loading @@ -861,6 +915,7 @@ static int mlx4_en_flow_replace(struct net_device *dev, loc_rule->id = 0; memset(&loc_rule->flow_spec, 0, sizeof(struct ethtool_rx_flow_spec)); list_del(&loc_rule->list); } err = mlx4_flow_attach(priv->mdev->dev, &rule, ®_id); if (err) { Loading @@ -871,6 +926,7 @@ static int mlx4_en_flow_replace(struct net_device *dev, loc_rule->id = reg_id; memcpy(&loc_rule->flow_spec, &cmd->fs, sizeof(struct ethtool_rx_flow_spec)); list_add_tail(&loc_rule->list, &priv->ethtool_list); out_free_list: list_for_each_entry_safe(spec, tmp_spec, &rule.list, list) { Loading Loading @@ -904,6 +960,7 @@ static int mlx4_en_flow_detach(struct net_device *dev, } rule->id = 0; memset(&rule->flow_spec, 0, sizeof(struct ethtool_rx_flow_spec)); list_del(&rule->list); out: return err; Loading Loading @@ -952,7 +1009,8 @@ static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, if ((cmd->cmd == ETHTOOL_GRXCLSRLCNT || cmd->cmd == ETHTOOL_GRXCLSRULE || cmd->cmd == ETHTOOL_GRXCLSRLALL) && mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED || !priv->port_up)) return -EINVAL; switch (cmd->cmd) { Loading Loading @@ -988,7 +1046,8 @@ static int mlx4_en_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED || !priv->port_up) return -EINVAL; switch (cmd->cmd) { Loading Loading @@ -1037,7 +1096,7 @@ static int mlx4_en_set_channels(struct net_device *dev, mutex_lock(&mdev->state_lock); if (priv->port_up) { port_up = 1; mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 1); } mlx4_en_free_resources(priv); Loading
drivers/net/ethernet/mellanox/mlx4/en_netdev.c +27 −5 Original line number Diff line number Diff line Loading @@ -1039,6 +1039,9 @@ int mlx4_en_start_port(struct net_device *dev) INIT_LIST_HEAD(&priv->mc_list); INIT_LIST_HEAD(&priv->curr_list); INIT_LIST_HEAD(&priv->ethtool_list); memset(&priv->ethtool_rules[0], 0, sizeof(struct ethtool_flow_id) * MAX_NUM_OF_FS_RULES); /* Calculate Rx buf size */ dev->mtu = min(dev->mtu, priv->max_mtu); Loading Loading @@ -1175,6 +1178,8 @@ int mlx4_en_start_port(struct net_device *dev) priv->port_up = true; netif_tx_start_all_queues(dev); netif_device_attach(dev); return 0; tx_err: Loading @@ -1197,11 +1202,12 @@ int mlx4_en_start_port(struct net_device *dev) } void mlx4_en_stop_port(struct net_device *dev) void mlx4_en_stop_port(struct net_device *dev, int detach) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_mc_list *mclist, *tmp; struct ethtool_flow_id *flow, *tmp_flow; int i; u8 mc_list[16] = {0}; Loading @@ -1212,9 +1218,13 @@ void mlx4_en_stop_port(struct net_device *dev) /* Synchronize with tx routine */ netif_tx_lock_bh(dev); if (detach) netif_device_detach(dev); netif_tx_stop_all_queues(dev); netif_tx_unlock_bh(dev); netif_tx_disable(dev); /* Set port as not active */ priv->port_up = false; Loading Loading @@ -1281,8 +1291,20 @@ void mlx4_en_stop_port(struct net_device *dev) /* Unregister Mac address for the port */ mlx4_put_eth_qp(mdev->dev, priv->port, priv->mac, priv->base_qpn); if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN)) mdev->mac_removed[priv->port] = 1; /* Remove flow steering rules for the port*/ if (mdev->dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { ASSERT_RTNL(); list_for_each_entry_safe(flow, tmp_flow, &priv->ethtool_list, list) { mlx4_flow_detach(mdev->dev, flow->id); list_del(&flow->list); } } /* Free RX Rings */ for (i = 0; i < priv->rx_ring_num; i++) { mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); Loading @@ -1307,7 +1329,7 @@ static void mlx4_en_restart(struct work_struct *work) mutex_lock(&mdev->state_lock); if (priv->port_up) { mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 1); for (i = 0; i < priv->tx_ring_num; i++) netdev_tx_reset_queue(priv->tx_ring[i].tx_queue); if (mlx4_en_start_port(dev)) Loading Loading @@ -1379,7 +1401,7 @@ static int mlx4_en_close(struct net_device *dev) mutex_lock(&mdev->state_lock); mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 0); netif_carrier_off(dev); mutex_unlock(&mdev->state_lock); Loading Loading @@ -1517,7 +1539,7 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) * the port */ en_dbg(DRV, priv, "Change MTU called with card down!?\n"); } else { mlx4_en_stop_port(dev); mlx4_en_stop_port(dev, 1); err = mlx4_en_start_port(dev); if (err) { en_err(priv, "Failed restarting port:%d\n", Loading
drivers/net/ethernet/mellanox/mlx4/fw.c +8 −3 Original line number Diff line number Diff line Loading @@ -127,7 +127,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) [0] = "RSS support", [1] = "RSS Toeplitz Hash Function support", [2] = "RSS XOR Hash Function support", [3] = "Device manage flow steering support" [3] = "Device manage flow steering support", [4] = "Automatic mac reassignment support" }; int i; Loading Loading @@ -478,6 +479,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x94 #define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98 #define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0 #define QUERY_DEV_CAP_FW_REASSIGN_MAC 0x9d dev_cap->flags2 = 0; mailbox = mlx4_alloc_cmd_mailbox(dev); Loading Loading @@ -637,6 +639,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) QUERY_DEV_CAP_BMME_FLAGS_OFFSET); MLX4_GET(dev_cap->reserved_lkey, outbox, QUERY_DEV_CAP_RSVD_LKEY_OFFSET); MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC); if (field & 1<<6) dev_cap->flags2 |= MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN; MLX4_GET(dev_cap->max_icm_sz, outbox, QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET); if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS) Loading Loading @@ -1287,14 +1292,14 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) /* Enable Ethernet flow steering * with udp unicast and tcp unicast */ MLX4_PUT(inbox, param->fs_hash_enable_bits, MLX4_PUT(inbox, (u8) (MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN), INIT_HCA_FS_ETH_BITS_OFFSET); MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, INIT_HCA_FS_ETH_NUM_ADDRS_OFFSET); /* Enable IPoIB flow steering * with udp unicast and tcp unicast */ MLX4_PUT(inbox, param->fs_hash_enable_bits, MLX4_PUT(inbox, (u8) (MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN), INIT_HCA_FS_IB_BITS_OFFSET); MLX4_PUT(inbox, (u16) MLX4_FS_NUM_OF_L2_ADDR, INIT_HCA_FS_IB_NUM_ADDRS_OFFSET); Loading
drivers/net/ethernet/mellanox/mlx4/fw.h +0 −1 Original line number Diff line number Diff line Loading @@ -171,7 +171,6 @@ struct mlx4_init_hca_param { u8 log_mpt_sz; u8 log_uar_sz; u8 uar_page_sz; /* log pg sz in 4k chunks */ u8 fs_hash_enable_bits; u8 steering_mode; /* for QUERY_HCA */ u64 dev_cap_enabled; }; Loading
drivers/net/ethernet/mellanox/mlx4/main.c +0 −16 Original line number Diff line number Diff line Loading @@ -1415,22 +1415,6 @@ static int mlx4_init_hca(struct mlx4_dev *dev) if (mlx4_is_master(dev)) mlx4_parav_master_pf_caps(dev); priv->fs_hash_mode = MLX4_FS_L2_HASH; switch (priv->fs_hash_mode) { case MLX4_FS_L2_HASH: init_hca.fs_hash_enable_bits = 0; break; case MLX4_FS_L2_L3_L4_HASH: /* Enable flow steering with * udp unicast and tcp unicast */ init_hca.fs_hash_enable_bits = MLX4_FS_UDP_UC_EN | MLX4_FS_TCP_UC_EN; break; } profile = default_profile; if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) Loading