diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/fw.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.c | 108 |
1 files changed, 102 insertions, 6 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 7e2995ecea6f..d16a4d118903 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c | |||
@@ -225,13 +225,25 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
225 | #define QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID 0x80 | 225 | #define QUERY_FUNC_CAP_FLAGS0_FORCE_PHY_WQE_GID 0x80 |
226 | 226 | ||
227 | if (vhcr->op_modifier == 1) { | 227 | if (vhcr->op_modifier == 1) { |
228 | struct mlx4_active_ports actv_ports = | ||
229 | mlx4_get_active_ports(dev, slave); | ||
230 | int converted_port = mlx4_slave_convert_port( | ||
231 | dev, slave, vhcr->in_modifier); | ||
232 | |||
233 | if (converted_port < 0) | ||
234 | return -EINVAL; | ||
235 | |||
236 | vhcr->in_modifier = converted_port; | ||
228 | /* Set nic_info bit to mark new fields support */ | 237 | /* Set nic_info bit to mark new fields support */ |
229 | field = QUERY_FUNC_CAP_FLAGS1_NIC_INFO; | 238 | field = QUERY_FUNC_CAP_FLAGS1_NIC_INFO; |
230 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS1_OFFSET); | 239 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS1_OFFSET); |
231 | 240 | ||
232 | field = vhcr->in_modifier; /* phys-port = logical-port */ | 241 | /* phys-port = logical-port */ |
242 | field = vhcr->in_modifier - | ||
243 | find_first_bit(actv_ports.ports, dev->caps.num_ports); | ||
233 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_PHYS_PORT_OFFSET); | 244 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_PHYS_PORT_OFFSET); |
234 | 245 | ||
246 | field = vhcr->in_modifier; | ||
235 | /* size is now the QP number */ | 247 | /* size is now the QP number */ |
236 | size = dev->phys_caps.base_tunnel_sqpn + 8 * slave + field - 1; | 248 | size = dev->phys_caps.base_tunnel_sqpn + 8 * slave + field - 1; |
237 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_TUNNEL); | 249 | MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_TUNNEL); |
@@ -249,12 +261,16 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
249 | QUERY_FUNC_CAP_PHYS_PORT_ID); | 261 | QUERY_FUNC_CAP_PHYS_PORT_ID); |
250 | 262 | ||
251 | } else if (vhcr->op_modifier == 0) { | 263 | } else if (vhcr->op_modifier == 0) { |
264 | struct mlx4_active_ports actv_ports = | ||
265 | mlx4_get_active_ports(dev, slave); | ||
252 | /* enable rdma and ethernet interfaces, and new quota locations */ | 266 | /* enable rdma and ethernet interfaces, and new quota locations */ |
253 | field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA | | 267 | field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA | |
254 | QUERY_FUNC_CAP_FLAG_QUOTAS); | 268 | QUERY_FUNC_CAP_FLAG_QUOTAS); |
255 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); | 269 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); |
256 | 270 | ||
257 | field = dev->caps.num_ports; | 271 | field = min( |
272 | bitmap_weight(actv_ports.ports, dev->caps.num_ports), | ||
273 | dev->caps.num_ports); | ||
258 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); | 274 | MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); |
259 | 275 | ||
260 | size = dev->caps.function_caps; /* set PF behaviours */ | 276 | size = dev->caps.function_caps; /* set PF behaviours */ |
@@ -840,6 +856,10 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
840 | int err = 0; | 856 | int err = 0; |
841 | u8 field; | 857 | u8 field; |
842 | u32 bmme_flags; | 858 | u32 bmme_flags; |
859 | int real_port; | ||
860 | int slave_port; | ||
861 | int first_port; | ||
862 | struct mlx4_active_ports actv_ports; | ||
843 | 863 | ||
844 | err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, | 864 | err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, |
845 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); | 865 | MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); |
@@ -852,8 +872,26 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
852 | MLX4_GET(flags, outbox->buf, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); | 872 | MLX4_GET(flags, outbox->buf, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); |
853 | flags |= MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV; | 873 | flags |= MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV; |
854 | flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW; | 874 | flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW; |
875 | actv_ports = mlx4_get_active_ports(dev, slave); | ||
876 | first_port = find_first_bit(actv_ports.ports, dev->caps.num_ports); | ||
877 | for (slave_port = 0, real_port = first_port; | ||
878 | real_port < first_port + | ||
879 | bitmap_weight(actv_ports.ports, dev->caps.num_ports); | ||
880 | ++real_port, ++slave_port) { | ||
881 | if (flags & (MLX4_DEV_CAP_FLAG_WOL_PORT1 << real_port)) | ||
882 | flags |= MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port; | ||
883 | else | ||
884 | flags &= ~(MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port); | ||
885 | } | ||
886 | for (; slave_port < dev->caps.num_ports; ++slave_port) | ||
887 | flags &= ~(MLX4_DEV_CAP_FLAG_WOL_PORT1 << slave_port); | ||
855 | MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); | 888 | MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET); |
856 | 889 | ||
890 | MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_VL_PORT_OFFSET); | ||
891 | field &= ~0x0F; | ||
892 | field |= bitmap_weight(actv_ports.ports, dev->caps.num_ports) & 0x0F; | ||
893 | MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_VL_PORT_OFFSET); | ||
894 | |||
857 | /* For guests, disable timestamp */ | 895 | /* For guests, disable timestamp */ |
858 | MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET); | 896 | MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET); |
859 | field &= 0x7f; | 897 | field &= 0x7f; |
@@ -903,12 +941,20 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, | |||
903 | u16 short_field; | 941 | u16 short_field; |
904 | int err; | 942 | int err; |
905 | int admin_link_state; | 943 | int admin_link_state; |
944 | int port = mlx4_slave_convert_port(dev, slave, | ||
945 | vhcr->in_modifier & 0xFF); | ||
906 | 946 | ||
907 | #define MLX4_VF_PORT_NO_LINK_SENSE_MASK 0xE0 | 947 | #define MLX4_VF_PORT_NO_LINK_SENSE_MASK 0xE0 |
908 | #define MLX4_PORT_LINK_UP_MASK 0x80 | 948 | #define MLX4_PORT_LINK_UP_MASK 0x80 |
909 | #define QUERY_PORT_CUR_MAX_PKEY_OFFSET 0x0c | 949 | #define QUERY_PORT_CUR_MAX_PKEY_OFFSET 0x0c |
910 | #define QUERY_PORT_CUR_MAX_GID_OFFSET 0x0e | 950 | #define QUERY_PORT_CUR_MAX_GID_OFFSET 0x0e |
911 | 951 | ||
952 | if (port < 0) | ||
953 | return -EINVAL; | ||
954 | |||
955 | vhcr->in_modifier = (vhcr->in_modifier & ~0xFF) | | ||
956 | (port & 0xFF); | ||
957 | |||
912 | err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0, | 958 | err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0, |
913 | MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, | 959 | MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, |
914 | MLX4_CMD_NATIVE); | 960 | MLX4_CMD_NATIVE); |
@@ -935,7 +981,10 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, | |||
935 | MLX4_PUT(outbox->buf, port_type, | 981 | MLX4_PUT(outbox->buf, port_type, |
936 | QUERY_PORT_SUPPORTED_TYPE_OFFSET); | 982 | QUERY_PORT_SUPPORTED_TYPE_OFFSET); |
937 | 983 | ||
938 | short_field = 1; /* slave max gids */ | 984 | if (dev->caps.port_type[vhcr->in_modifier] == MLX4_PORT_TYPE_ETH) |
985 | short_field = mlx4_get_slave_num_gids(dev, slave, port); | ||
986 | else | ||
987 | short_field = 1; /* slave max gids */ | ||
939 | MLX4_PUT(outbox->buf, short_field, | 988 | MLX4_PUT(outbox->buf, short_field, |
940 | QUERY_PORT_CUR_MAX_GID_OFFSET); | 989 | QUERY_PORT_CUR_MAX_GID_OFFSET); |
941 | 990 | ||
@@ -1585,9 +1634,12 @@ int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave, | |||
1585 | struct mlx4_cmd_info *cmd) | 1634 | struct mlx4_cmd_info *cmd) |
1586 | { | 1635 | { |
1587 | struct mlx4_priv *priv = mlx4_priv(dev); | 1636 | struct mlx4_priv *priv = mlx4_priv(dev); |
1588 | int port = vhcr->in_modifier; | 1637 | int port = mlx4_slave_convert_port(dev, slave, vhcr->in_modifier); |
1589 | int err; | 1638 | int err; |
1590 | 1639 | ||
1640 | if (port < 0) | ||
1641 | return -EINVAL; | ||
1642 | |||
1591 | if (priv->mfunc.master.slave_state[slave].init_port_mask & (1 << port)) | 1643 | if (priv->mfunc.master.slave_state[slave].init_port_mask & (1 << port)) |
1592 | return 0; | 1644 | return 0; |
1593 | 1645 | ||
@@ -1677,9 +1729,12 @@ int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave, | |||
1677 | struct mlx4_cmd_info *cmd) | 1729 | struct mlx4_cmd_info *cmd) |
1678 | { | 1730 | { |
1679 | struct mlx4_priv *priv = mlx4_priv(dev); | 1731 | struct mlx4_priv *priv = mlx4_priv(dev); |
1680 | int port = vhcr->in_modifier; | 1732 | int port = mlx4_slave_convert_port(dev, slave, vhcr->in_modifier); |
1681 | int err; | 1733 | int err; |
1682 | 1734 | ||
1735 | if (port < 0) | ||
1736 | return -EINVAL; | ||
1737 | |||
1683 | if (!(priv->mfunc.master.slave_state[slave].init_port_mask & | 1738 | if (!(priv->mfunc.master.slave_state[slave].init_port_mask & |
1684 | (1 << port))) | 1739 | (1 << port))) |
1685 | return 0; | 1740 | return 0; |
@@ -1724,6 +1779,46 @@ int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic) | |||
1724 | MLX4_CMD_NATIVE); | 1779 | MLX4_CMD_NATIVE); |
1725 | } | 1780 | } |
1726 | 1781 | ||
1782 | struct mlx4_config_dev { | ||
1783 | __be32 update_flags; | ||
1784 | __be32 rsdv1[3]; | ||
1785 | __be16 vxlan_udp_dport; | ||
1786 | __be16 rsvd2; | ||
1787 | }; | ||
1788 | |||
1789 | #define MLX4_VXLAN_UDP_DPORT (1 << 0) | ||
1790 | |||
1791 | static int mlx4_CONFIG_DEV(struct mlx4_dev *dev, struct mlx4_config_dev *config_dev) | ||
1792 | { | ||
1793 | int err; | ||
1794 | struct mlx4_cmd_mailbox *mailbox; | ||
1795 | |||
1796 | mailbox = mlx4_alloc_cmd_mailbox(dev); | ||
1797 | if (IS_ERR(mailbox)) | ||
1798 | return PTR_ERR(mailbox); | ||
1799 | |||
1800 | memcpy(mailbox->buf, config_dev, sizeof(*config_dev)); | ||
1801 | |||
1802 | err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_CONFIG_DEV, | ||
1803 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); | ||
1804 | |||
1805 | mlx4_free_cmd_mailbox(dev, mailbox); | ||
1806 | return err; | ||
1807 | } | ||
1808 | |||
1809 | int mlx4_config_vxlan_port(struct mlx4_dev *dev, __be16 udp_port) | ||
1810 | { | ||
1811 | struct mlx4_config_dev config_dev; | ||
1812 | |||
1813 | memset(&config_dev, 0, sizeof(config_dev)); | ||
1814 | config_dev.update_flags = cpu_to_be32(MLX4_VXLAN_UDP_DPORT); | ||
1815 | config_dev.vxlan_udp_dport = udp_port; | ||
1816 | |||
1817 | return mlx4_CONFIG_DEV(dev, &config_dev); | ||
1818 | } | ||
1819 | EXPORT_SYMBOL_GPL(mlx4_config_vxlan_port); | ||
1820 | |||
1821 | |||
1727 | int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages) | 1822 | int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages) |
1728 | { | 1823 | { |
1729 | int ret = mlx4_cmd_imm(dev, icm_size, aux_pages, 0, 0, | 1824 | int ret = mlx4_cmd_imm(dev, icm_size, aux_pages, 0, 0, |
@@ -1891,7 +1986,8 @@ void mlx4_opreq_action(struct work_struct *work) | |||
1891 | err = EINVAL; | 1986 | err = EINVAL; |
1892 | break; | 1987 | break; |
1893 | } | 1988 | } |
1894 | err = mlx4_cmd(dev, 0, ((u32) err | cpu_to_be32(token) << 16), | 1989 | err = mlx4_cmd(dev, 0, ((u32) err | |
1990 | (__force u32)cpu_to_be32(token) << 16), | ||
1895 | 1, MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A, | 1991 | 1, MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A, |
1896 | MLX4_CMD_NATIVE); | 1992 | MLX4_CMD_NATIVE); |
1897 | if (err) { | 1993 | if (err) { |