diff options
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_resources.c | 8 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/intf.c | 54 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 89 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/qp.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 3 | ||||
| -rw-r--r-- | include/linux/mlx4/device.h | 1 | ||||
| -rw-r--r-- | include/linux/mlx4/driver.h | 19 |
8 files changed, 177 insertions, 2 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c index f1a5500ff72d..34f2fdf4fe5d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c | |||
| @@ -50,10 +50,14 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride, | |||
| 50 | context->mtu_msgmax = 0xff; | 50 | context->mtu_msgmax = 0xff; |
| 51 | if (!is_tx && !rss) | 51 | if (!is_tx && !rss) |
| 52 | context->rq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4); | 52 | context->rq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4); |
| 53 | if (is_tx) | 53 | if (is_tx) { |
| 54 | context->sq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4); | 54 | context->sq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4); |
| 55 | else | 55 | if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PORT_REMAP) |
| 56 | context->params2 |= MLX4_QP_BIT_FPP; | ||
| 57 | |||
| 58 | } else { | ||
| 56 | context->sq_size_stride = ilog2(TXBB_SIZE) - 4; | 59 | context->sq_size_stride = ilog2(TXBB_SIZE) - 4; |
| 60 | } | ||
| 57 | context->usr_page = cpu_to_be32(mdev->priv_uar.index); | 61 | context->usr_page = cpu_to_be32(mdev->priv_uar.index); |
| 58 | context->local_qpn = cpu_to_be32(qpn); | 62 | context->local_qpn = cpu_to_be32(qpn); |
| 59 | context->pri_path.ackto = 1 & 0x07; | 63 | context->pri_path.ackto = 1 & 0x07; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/intf.c b/drivers/net/ethernet/mellanox/mlx4/intf.c index 68d2bad325d5..6fce58718837 100644 --- a/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/drivers/net/ethernet/mellanox/mlx4/intf.c | |||
| @@ -33,11 +33,13 @@ | |||
| 33 | 33 | ||
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 35 | #include <linux/export.h> | 35 | #include <linux/export.h> |
| 36 | #include <linux/errno.h> | ||
| 36 | 37 | ||
| 37 | #include "mlx4.h" | 38 | #include "mlx4.h" |
| 38 | 39 | ||
| 39 | struct mlx4_device_context { | 40 | struct mlx4_device_context { |
| 40 | struct list_head list; | 41 | struct list_head list; |
| 42 | struct list_head bond_list; | ||
| 41 | struct mlx4_interface *intf; | 43 | struct mlx4_interface *intf; |
| 42 | void *context; | 44 | void *context; |
| 43 | }; | 45 | }; |
| @@ -115,6 +117,58 @@ void mlx4_unregister_interface(struct mlx4_interface *intf) | |||
| 115 | } | 117 | } |
| 116 | EXPORT_SYMBOL_GPL(mlx4_unregister_interface); | 118 | EXPORT_SYMBOL_GPL(mlx4_unregister_interface); |
| 117 | 119 | ||
| 120 | int mlx4_do_bond(struct mlx4_dev *dev, bool enable) | ||
| 121 | { | ||
| 122 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
| 123 | struct mlx4_device_context *dev_ctx = NULL, *temp_dev_ctx; | ||
| 124 | unsigned long flags; | ||
| 125 | int ret; | ||
| 126 | LIST_HEAD(bond_list); | ||
| 127 | |||
| 128 | if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PORT_REMAP)) | ||
| 129 | return -ENOTSUPP; | ||
| 130 | |||
| 131 | ret = mlx4_disable_rx_port_check(dev, enable); | ||
| 132 | if (ret) { | ||
| 133 | mlx4_err(dev, "Fail to %s rx port check\n", | ||
| 134 | enable ? "enable" : "disable"); | ||
| 135 | return ret; | ||
| 136 | } | ||
| 137 | if (enable) { | ||
| 138 | dev->flags |= MLX4_FLAG_BONDED; | ||
| 139 | } else { | ||
| 140 | ret = mlx4_virt2phy_port_map(dev, 1, 2); | ||
| 141 | if (ret) { | ||
| 142 | mlx4_err(dev, "Fail to reset port map\n"); | ||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | dev->flags &= ~MLX4_FLAG_BONDED; | ||
| 146 | } | ||
| 147 | |||
| 148 | spin_lock_irqsave(&priv->ctx_lock, flags); | ||
| 149 | list_for_each_entry_safe(dev_ctx, temp_dev_ctx, &priv->ctx_list, list) { | ||
| 150 | if (dev_ctx->intf->flags & MLX4_INTFF_BONDING) { | ||
| 151 | list_add_tail(&dev_ctx->bond_list, &bond_list); | ||
| 152 | list_del(&dev_ctx->list); | ||
| 153 | } | ||
| 154 | } | ||
| 155 | spin_unlock_irqrestore(&priv->ctx_lock, flags); | ||
| 156 | |||
| 157 | list_for_each_entry(dev_ctx, &bond_list, bond_list) { | ||
| 158 | dev_ctx->intf->remove(dev, dev_ctx->context); | ||
| 159 | dev_ctx->context = dev_ctx->intf->add(dev); | ||
| 160 | |||
| 161 | spin_lock_irqsave(&priv->ctx_lock, flags); | ||
| 162 | list_add_tail(&dev_ctx->list, &priv->ctx_list); | ||
| 163 | spin_unlock_irqrestore(&priv->ctx_lock, flags); | ||
| 164 | |||
| 165 | mlx4_dbg(dev, "Inrerface for protocol %d restarted with when bonded mode is %s\n", | ||
| 166 | dev_ctx->intf->protocol, enable ? | ||
| 167 | "enabled" : "disabled"); | ||
| 168 | } | ||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | |||
| 118 | void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, | 172 | void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, |
| 119 | unsigned long param) | 173 | unsigned long param) |
| 120 | { | 174 | { |
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index cc9f48439244..f3245fe0f442 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
| @@ -1160,6 +1160,91 @@ err_set_port: | |||
| 1160 | return err ? err : count; | 1160 | return err ? err : count; |
| 1161 | } | 1161 | } |
| 1162 | 1162 | ||
| 1163 | int mlx4_bond(struct mlx4_dev *dev) | ||
| 1164 | { | ||
| 1165 | int ret = 0; | ||
| 1166 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
| 1167 | |||
| 1168 | mutex_lock(&priv->bond_mutex); | ||
| 1169 | |||
| 1170 | if (!mlx4_is_bonded(dev)) | ||
| 1171 | ret = mlx4_do_bond(dev, true); | ||
| 1172 | else | ||
| 1173 | ret = 0; | ||
| 1174 | |||
| 1175 | mutex_unlock(&priv->bond_mutex); | ||
| 1176 | if (ret) | ||
| 1177 | mlx4_err(dev, "Failed to bond device: %d\n", ret); | ||
| 1178 | else | ||
| 1179 | mlx4_dbg(dev, "Device is bonded\n"); | ||
| 1180 | return ret; | ||
| 1181 | } | ||
| 1182 | EXPORT_SYMBOL_GPL(mlx4_bond); | ||
| 1183 | |||
| 1184 | int mlx4_unbond(struct mlx4_dev *dev) | ||
| 1185 | { | ||
| 1186 | int ret = 0; | ||
| 1187 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
| 1188 | |||
| 1189 | mutex_lock(&priv->bond_mutex); | ||
| 1190 | |||
| 1191 | if (mlx4_is_bonded(dev)) | ||
| 1192 | ret = mlx4_do_bond(dev, false); | ||
| 1193 | |||
| 1194 | mutex_unlock(&priv->bond_mutex); | ||
| 1195 | if (ret) | ||
| 1196 | mlx4_err(dev, "Failed to unbond device: %d\n", ret); | ||
| 1197 | else | ||
| 1198 | mlx4_dbg(dev, "Device is unbonded\n"); | ||
| 1199 | return ret; | ||
| 1200 | } | ||
| 1201 | EXPORT_SYMBOL_GPL(mlx4_unbond); | ||
| 1202 | |||
| 1203 | |||
| 1204 | int mlx4_port_map_set(struct mlx4_dev *dev, struct mlx4_port_map *v2p) | ||
| 1205 | { | ||
| 1206 | u8 port1 = v2p->port1; | ||
| 1207 | u8 port2 = v2p->port2; | ||
| 1208 | struct mlx4_priv *priv = mlx4_priv(dev); | ||
| 1209 | int err; | ||
| 1210 | |||
| 1211 | if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PORT_REMAP)) | ||
| 1212 | return -ENOTSUPP; | ||
| 1213 | |||
| 1214 | mutex_lock(&priv->bond_mutex); | ||
| 1215 | |||
| 1216 | /* zero means keep current mapping for this port */ | ||
| 1217 | if (port1 == 0) | ||
| 1218 | port1 = priv->v2p.port1; | ||
| 1219 | if (port2 == 0) | ||
| 1220 | port2 = priv->v2p.port2; | ||
| 1221 | |||
| 1222 | if ((port1 < 1) || (port1 > MLX4_MAX_PORTS) || | ||
| 1223 | (port2 < 1) || (port2 > MLX4_MAX_PORTS) || | ||
| 1224 | (port1 == 2 && port2 == 1)) { | ||
| 1225 | /* besides boundary checks cross mapping makes | ||
| 1226 | * no sense and therefore not allowed */ | ||
| 1227 | err = -EINVAL; | ||
| 1228 | } else if ((port1 == priv->v2p.port1) && | ||
| 1229 | (port2 == priv->v2p.port2)) { | ||
| 1230 | err = 0; | ||
| 1231 | } else { | ||
| 1232 | err = mlx4_virt2phy_port_map(dev, port1, port2); | ||
| 1233 | if (!err) { | ||
| 1234 | mlx4_dbg(dev, "port map changed: [%d][%d]\n", | ||
| 1235 | port1, port2); | ||
| 1236 | priv->v2p.port1 = port1; | ||
| 1237 | priv->v2p.port2 = port2; | ||
| 1238 | } else { | ||
| 1239 | mlx4_err(dev, "Failed to change port mape: %d\n", err); | ||
| 1240 | } | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | mutex_unlock(&priv->bond_mutex); | ||
| 1244 | return err; | ||
| 1245 | } | ||
| 1246 | EXPORT_SYMBOL_GPL(mlx4_port_map_set); | ||
| 1247 | |||
| 1163 | static int mlx4_load_fw(struct mlx4_dev *dev) | 1248 | static int mlx4_load_fw(struct mlx4_dev *dev) |
| 1164 | { | 1249 | { |
| 1165 | struct mlx4_priv *priv = mlx4_priv(dev); | 1250 | struct mlx4_priv *priv = mlx4_priv(dev); |
| @@ -2638,6 +2723,7 @@ static int mlx4_load_one(struct pci_dev *pdev, int pci_dev_data, | |||
| 2638 | spin_lock_init(&priv->ctx_lock); | 2723 | spin_lock_init(&priv->ctx_lock); |
| 2639 | 2724 | ||
| 2640 | mutex_init(&priv->port_mutex); | 2725 | mutex_init(&priv->port_mutex); |
| 2726 | mutex_init(&priv->bond_mutex); | ||
| 2641 | 2727 | ||
| 2642 | INIT_LIST_HEAD(&priv->pgdir_list); | 2728 | INIT_LIST_HEAD(&priv->pgdir_list); |
| 2643 | mutex_init(&priv->pgdir_mutex); | 2729 | mutex_init(&priv->pgdir_mutex); |
| @@ -2934,6 +3020,9 @@ slave_start: | |||
| 2934 | goto err_port; | 3020 | goto err_port; |
| 2935 | } | 3021 | } |
| 2936 | 3022 | ||
| 3023 | priv->v2p.port1 = 1; | ||
| 3024 | priv->v2p.port2 = 2; | ||
| 3025 | |||
| 2937 | err = mlx4_register_device(dev); | 3026 | err = mlx4_register_device(dev); |
| 2938 | if (err) | 3027 | if (err) |
| 2939 | goto err_port; | 3028 | goto err_port; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 148dc0945aab..803f17653da7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
| @@ -885,6 +885,8 @@ struct mlx4_priv { | |||
| 885 | int reserved_mtts; | 885 | int reserved_mtts; |
| 886 | int fs_hash_mode; | 886 | int fs_hash_mode; |
| 887 | u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS]; | 887 | u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS]; |
| 888 | struct mlx4_port_map v2p; /* cached port mapping configuration */ | ||
| 889 | struct mutex bond_mutex; /* for bond mode */ | ||
| 888 | __be64 slave_node_guids[MLX4_MFUNC_MAX]; | 890 | __be64 slave_node_guids[MLX4_MFUNC_MAX]; |
| 889 | 891 | ||
| 890 | atomic_t opreq_count; | 892 | atomic_t opreq_count; |
| @@ -1364,6 +1366,7 @@ int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave, int port); | |||
| 1364 | /* Returns the VF index of slave */ | 1366 | /* Returns the VF index of slave */ |
| 1365 | int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave); | 1367 | int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave); |
| 1366 | int mlx4_config_mad_demux(struct mlx4_dev *dev); | 1368 | int mlx4_config_mad_demux(struct mlx4_dev *dev); |
| 1369 | int mlx4_do_bond(struct mlx4_dev *dev, bool enable); | ||
| 1367 | 1370 | ||
| 1368 | enum mlx4_zone_flags { | 1371 | enum mlx4_zone_flags { |
| 1369 | MLX4_ZONE_ALLOW_ALLOC_FROM_LOWER_PRIO = 1UL << 0, | 1372 | MLX4_ZONE_ALLOW_ALLOC_FROM_LOWER_PRIO = 1UL << 0, |
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 1586ecce13c7..2bb8553bd905 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c | |||
| @@ -882,6 +882,8 @@ int mlx4_qp_to_ready(struct mlx4_dev *dev, struct mlx4_mtt *mtt, | |||
| 882 | for (i = 0; i < ARRAY_SIZE(states) - 1; i++) { | 882 | for (i = 0; i < ARRAY_SIZE(states) - 1; i++) { |
| 883 | context->flags &= cpu_to_be32(~(0xf << 28)); | 883 | context->flags &= cpu_to_be32(~(0xf << 28)); |
| 884 | context->flags |= cpu_to_be32(states[i + 1] << 28); | 884 | context->flags |= cpu_to_be32(states[i + 1] << 28); |
| 885 | if (states[i + 1] != MLX4_QP_STATE_RTR) | ||
| 886 | context->params2 &= ~MLX4_QP_BIT_FPP; | ||
| 885 | err = mlx4_qp_modify(dev, mtt, states[i], states[i + 1], | 887 | err = mlx4_qp_modify(dev, mtt, states[i], states[i + 1], |
| 886 | context, 0, 0, qp); | 888 | context, 0, 0, qp); |
| 887 | if (err) { | 889 | if (err) { |
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 79feeb6b0d87..c5f3dfca226b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
| @@ -2944,6 +2944,9 @@ static int verify_qp_parameters(struct mlx4_dev *dev, | |||
| 2944 | qp_type = (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff; | 2944 | qp_type = (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff; |
| 2945 | optpar = be32_to_cpu(*(__be32 *) inbox->buf); | 2945 | optpar = be32_to_cpu(*(__be32 *) inbox->buf); |
| 2946 | 2946 | ||
| 2947 | if (slave != mlx4_master_func_num(dev)) | ||
| 2948 | qp_ctx->params2 &= ~MLX4_QP_BIT_FPP; | ||
| 2949 | |||
| 2947 | switch (qp_type) { | 2950 | switch (qp_type) { |
| 2948 | case MLX4_QP_ST_RC: | 2951 | case MLX4_QP_ST_RC: |
| 2949 | case MLX4_QP_ST_XRC: | 2952 | case MLX4_QP_ST_XRC: |
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index d9afd99dde39..977b0b164431 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h | |||
| @@ -70,6 +70,7 @@ enum { | |||
| 70 | MLX4_FLAG_SLAVE = 1 << 3, | 70 | MLX4_FLAG_SLAVE = 1 << 3, |
| 71 | MLX4_FLAG_SRIOV = 1 << 4, | 71 | MLX4_FLAG_SRIOV = 1 << 4, |
| 72 | MLX4_FLAG_OLD_REG_MAC = 1 << 6, | 72 | MLX4_FLAG_OLD_REG_MAC = 1 << 6, |
| 73 | MLX4_FLAG_BONDED = 1 << 7 | ||
| 73 | }; | 74 | }; |
| 74 | 75 | ||
| 75 | enum { | 76 | enum { |
diff --git a/include/linux/mlx4/driver.h b/include/linux/mlx4/driver.h index 022055c8fb26..9553a73d2049 100644 --- a/include/linux/mlx4/driver.h +++ b/include/linux/mlx4/driver.h | |||
| @@ -49,6 +49,10 @@ enum mlx4_dev_event { | |||
| 49 | MLX4_DEV_EVENT_SLAVE_SHUTDOWN, | 49 | MLX4_DEV_EVENT_SLAVE_SHUTDOWN, |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | enum { | ||
| 53 | MLX4_INTFF_BONDING = 1 << 0 | ||
| 54 | }; | ||
| 55 | |||
| 52 | struct mlx4_interface { | 56 | struct mlx4_interface { |
| 53 | void * (*add) (struct mlx4_dev *dev); | 57 | void * (*add) (struct mlx4_dev *dev); |
| 54 | void (*remove)(struct mlx4_dev *dev, void *context); | 58 | void (*remove)(struct mlx4_dev *dev, void *context); |
| @@ -57,11 +61,26 @@ struct mlx4_interface { | |||
| 57 | void * (*get_dev)(struct mlx4_dev *dev, void *context, u8 port); | 61 | void * (*get_dev)(struct mlx4_dev *dev, void *context, u8 port); |
| 58 | struct list_head list; | 62 | struct list_head list; |
| 59 | enum mlx4_protocol protocol; | 63 | enum mlx4_protocol protocol; |
| 64 | int flags; | ||
| 60 | }; | 65 | }; |
| 61 | 66 | ||
| 62 | int mlx4_register_interface(struct mlx4_interface *intf); | 67 | int mlx4_register_interface(struct mlx4_interface *intf); |
| 63 | void mlx4_unregister_interface(struct mlx4_interface *intf); | 68 | void mlx4_unregister_interface(struct mlx4_interface *intf); |
| 64 | 69 | ||
| 70 | int mlx4_bond(struct mlx4_dev *dev); | ||
| 71 | int mlx4_unbond(struct mlx4_dev *dev); | ||
| 72 | static inline int mlx4_is_bonded(struct mlx4_dev *dev) | ||
| 73 | { | ||
| 74 | return !!(dev->flags & MLX4_FLAG_BONDED); | ||
| 75 | } | ||
| 76 | |||
| 77 | struct mlx4_port_map { | ||
| 78 | u8 port1; | ||
| 79 | u8 port2; | ||
| 80 | }; | ||
| 81 | |||
| 82 | int mlx4_port_map_set(struct mlx4_dev *dev, struct mlx4_port_map *v2p); | ||
| 83 | |||
| 65 | void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port); | 84 | void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port); |
| 66 | 85 | ||
| 67 | static inline u64 mlx4_mac_to_u64(u8 *addr) | 86 | static inline u64 mlx4_mac_to_u64(u8 *addr) |
