aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mlx4/main.c
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.co.il>2009-03-18 22:45:11 -0400
committerRoland Dreier <rolandd@cisco.com>2009-03-18 22:45:11 -0400
commit27bf91d6a0d5a9c7224e8687754249bba67dd4cf (patch)
tree55c253fa4438ea29d73f072a88dff5fb74e2ca4e /drivers/net/mlx4/main.c
parent793730bfb6711d6d14629e63845c25a3c14d205e (diff)
mlx4_core: Add link type autosensing
When a port's link is down (except to driver restart) and the port is configured for auto sensing, we try to sense port link type (Ethernet or InfiniBand) in order to determine how to initialize the port. If the port type needs to be changed, all mlx4 for the device interfaces are unregistered and then registered again with the new port types. Sensing is done with intervals of 3 seconds. Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/net/mlx4/main.c')
-rw-r--r--drivers/net/mlx4/main.c104
1 files changed, 77 insertions, 27 deletions
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 8480f0346844..a66f5b2fd288 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -51,6 +51,8 @@ MODULE_DESCRIPTION("Mellanox ConnectX HCA low-level driver");
51MODULE_LICENSE("Dual BSD/GPL"); 51MODULE_LICENSE("Dual BSD/GPL");
52MODULE_VERSION(DRV_VERSION); 52MODULE_VERSION(DRV_VERSION);
53 53
54struct workqueue_struct *mlx4_wq;
55
54#ifdef CONFIG_MLX4_DEBUG 56#ifdef CONFIG_MLX4_DEBUG
55 57
56int mlx4_debug_level = 0; 58int mlx4_debug_level = 0;
@@ -98,24 +100,23 @@ module_param_named(use_prio, use_prio, bool, 0444);
98MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports " 100MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports "
99 "(0/1, default 0)"); 101 "(0/1, default 0)");
100 102
101static int mlx4_check_port_params(struct mlx4_dev *dev, 103int mlx4_check_port_params(struct mlx4_dev *dev,
102 enum mlx4_port_type *port_type) 104 enum mlx4_port_type *port_type)
103{ 105{
104 int i; 106 int i;
105 107
106 for (i = 0; i < dev->caps.num_ports - 1; i++) { 108 for (i = 0; i < dev->caps.num_ports - 1; i++) {
107 if (port_type[i] != port_type[i+1] && 109 if (port_type[i] != port_type[i + 1]) {
108 !(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) { 110 if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) {
109 mlx4_err(dev, "Only same port types supported " 111 mlx4_err(dev, "Only same port types supported "
110 "on this HCA, aborting.\n"); 112 "on this HCA, aborting.\n");
111 return -EINVAL; 113 return -EINVAL;
114 }
115 if (port_type[i] == MLX4_PORT_TYPE_ETH &&
116 port_type[i + 1] == MLX4_PORT_TYPE_IB)
117 return -EINVAL;
112 } 118 }
113 } 119 }
114 if ((port_type[0] == MLX4_PORT_TYPE_ETH) &&
115 (port_type[1] == MLX4_PORT_TYPE_IB)) {
116 mlx4_err(dev, "eth-ib configuration is not supported.\n");
117 return -EINVAL;
118 }
119 120
120 for (i = 0; i < dev->caps.num_ports; i++) { 121 for (i = 0; i < dev->caps.num_ports; i++) {
121 if (!(port_type[i] & dev->caps.supported_type[i+1])) { 122 if (!(port_type[i] & dev->caps.supported_type[i+1])) {
@@ -225,6 +226,9 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
225 dev->caps.port_type[i] = MLX4_PORT_TYPE_IB; 226 dev->caps.port_type[i] = MLX4_PORT_TYPE_IB;
226 else 227 else
227 dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH; 228 dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH;
229 dev->caps.possible_type[i] = dev->caps.port_type[i];
230 mlx4_priv(dev)->sense.sense_allowed[i] =
231 dev->caps.supported_type[i] == MLX4_PORT_TYPE_AUTO;
228 232
229 if (dev->caps.log_num_macs > dev_cap->log_max_macs[i]) { 233 if (dev->caps.log_num_macs > dev_cap->log_max_macs[i]) {
230 dev->caps.log_num_macs = dev_cap->log_max_macs[i]; 234 dev->caps.log_num_macs = dev_cap->log_max_macs[i];
@@ -263,14 +267,16 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
263 * Change the port configuration of the device. 267 * Change the port configuration of the device.
264 * Every user of this function must hold the port mutex. 268 * Every user of this function must hold the port mutex.
265 */ 269 */
266static int mlx4_change_port_types(struct mlx4_dev *dev, 270int mlx4_change_port_types(struct mlx4_dev *dev,
267 enum mlx4_port_type *port_types) 271 enum mlx4_port_type *port_types)
268{ 272{
269 int err = 0; 273 int err = 0;
270 int change = 0; 274 int change = 0;
271 int port; 275 int port;
272 276
273 for (port = 0; port < dev->caps.num_ports; port++) { 277 for (port = 0; port < dev->caps.num_ports; port++) {
278 /* Change the port type only if the new type is different
279 * from the current, and not set to Auto */
274 if (port_types[port] != dev->caps.port_type[port + 1]) { 280 if (port_types[port] != dev->caps.port_type[port + 1]) {
275 change = 1; 281 change = 1;
276 dev->caps.port_type[port + 1] = port_types[port]; 282 dev->caps.port_type[port + 1] = port_types[port];
@@ -302,10 +308,17 @@ static ssize_t show_port_type(struct device *dev,
302 struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info, 308 struct mlx4_port_info *info = container_of(attr, struct mlx4_port_info,
303 port_attr); 309 port_attr);
304 struct mlx4_dev *mdev = info->dev; 310 struct mlx4_dev *mdev = info->dev;
311 char type[8];
312
313 sprintf(type, "%s",
314 (mdev->caps.port_type[info->port] == MLX4_PORT_TYPE_IB) ?
315 "ib" : "eth");
316 if (mdev->caps.possible_type[info->port] == MLX4_PORT_TYPE_AUTO)
317 sprintf(buf, "auto (%s)\n", type);
318 else
319 sprintf(buf, "%s\n", type);
305 320
306 return sprintf(buf, "%s\n", 321 return strlen(buf);
307 mdev->caps.port_type[info->port] == MLX4_PORT_TYPE_IB ?
308 "ib" : "eth");
309} 322}
310 323
311static ssize_t set_port_type(struct device *dev, 324static ssize_t set_port_type(struct device *dev,
@@ -317,6 +330,7 @@ static ssize_t set_port_type(struct device *dev,
317 struct mlx4_dev *mdev = info->dev; 330 struct mlx4_dev *mdev = info->dev;
318 struct mlx4_priv *priv = mlx4_priv(mdev); 331 struct mlx4_priv *priv = mlx4_priv(mdev);
319 enum mlx4_port_type types[MLX4_MAX_PORTS]; 332 enum mlx4_port_type types[MLX4_MAX_PORTS];
333 enum mlx4_port_type new_types[MLX4_MAX_PORTS];
320 int i; 334 int i;
321 int err = 0; 335 int err = 0;
322 336
@@ -324,26 +338,56 @@ static ssize_t set_port_type(struct device *dev,
324 info->tmp_type = MLX4_PORT_TYPE_IB; 338 info->tmp_type = MLX4_PORT_TYPE_IB;
325 else if (!strcmp(buf, "eth\n")) 339 else if (!strcmp(buf, "eth\n"))
326 info->tmp_type = MLX4_PORT_TYPE_ETH; 340 info->tmp_type = MLX4_PORT_TYPE_ETH;
341 else if (!strcmp(buf, "auto\n"))
342 info->tmp_type = MLX4_PORT_TYPE_AUTO;
327 else { 343 else {
328 mlx4_err(mdev, "%s is not supported port type\n", buf); 344 mlx4_err(mdev, "%s is not supported port type\n", buf);
329 return -EINVAL; 345 return -EINVAL;
330 } 346 }
331 347
348 mlx4_stop_sense(mdev);
332 mutex_lock(&priv->port_mutex); 349 mutex_lock(&priv->port_mutex);
333 for (i = 0; i < mdev->caps.num_ports; i++) 350 /* Possible type is always the one that was delivered */
351 mdev->caps.possible_type[info->port] = info->tmp_type;
352
353 for (i = 0; i < mdev->caps.num_ports; i++) {
334 types[i] = priv->port[i+1].tmp_type ? priv->port[i+1].tmp_type : 354 types[i] = priv->port[i+1].tmp_type ? priv->port[i+1].tmp_type :
335 mdev->caps.port_type[i+1]; 355 mdev->caps.possible_type[i+1];
356 if (types[i] == MLX4_PORT_TYPE_AUTO)
357 types[i] = mdev->caps.port_type[i+1];
358 }
336 359
337 err = mlx4_check_port_params(mdev, types); 360 if (!(mdev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) {
361 for (i = 1; i <= mdev->caps.num_ports; i++) {
362 if (mdev->caps.possible_type[i] == MLX4_PORT_TYPE_AUTO) {
363 mdev->caps.possible_type[i] = mdev->caps.port_type[i];
364 err = -EINVAL;
365 }
366 }
367 }
368 if (err) {
369 mlx4_err(mdev, "Auto sensing is not supported on this HCA. "
370 "Set only 'eth' or 'ib' for both ports "
371 "(should be the same)\n");
372 goto out;
373 }
374
375 mlx4_do_sense_ports(mdev, new_types, types);
376
377 err = mlx4_check_port_params(mdev, new_types);
338 if (err) 378 if (err)
339 goto out; 379 goto out;
340 380
341 for (i = 1; i <= mdev->caps.num_ports; i++) 381 /* We are about to apply the changes after the configuration
342 priv->port[i].tmp_type = 0; 382 * was verified, no need to remember the temporary types
383 * any more */
384 for (i = 0; i < mdev->caps.num_ports; i++)
385 priv->port[i + 1].tmp_type = 0;
343 386
344 err = mlx4_change_port_types(mdev, types); 387 err = mlx4_change_port_types(mdev, new_types);
345 388
346out: 389out:
390 mlx4_start_sense(mdev);
347 mutex_unlock(&priv->port_mutex); 391 mutex_unlock(&priv->port_mutex);
348 return err ? err : count; 392 return err ? err : count;
349} 393}
@@ -1117,6 +1161,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
1117 if (err) 1161 if (err)
1118 goto err_port; 1162 goto err_port;
1119 1163
1164 mlx4_sense_init(dev);
1165 mlx4_start_sense(dev);
1166
1120 pci_set_drvdata(pdev, dev); 1167 pci_set_drvdata(pdev, dev);
1121 1168
1122 return 0; 1169 return 0;
@@ -1182,6 +1229,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
1182 int p; 1229 int p;
1183 1230
1184 if (dev) { 1231 if (dev) {
1232 mlx4_stop_sense(dev);
1185 mlx4_unregister_device(dev); 1233 mlx4_unregister_device(dev);
1186 1234
1187 for (p = 1; p <= dev->caps.num_ports; p++) { 1235 for (p = 1; p <= dev->caps.num_ports; p++) {
@@ -1266,9 +1314,11 @@ static int __init mlx4_init(void)
1266 if (mlx4_verify_params()) 1314 if (mlx4_verify_params())
1267 return -EINVAL; 1315 return -EINVAL;
1268 1316
1269 ret = mlx4_catas_init(); 1317 mlx4_catas_init();
1270 if (ret) 1318
1271 return ret; 1319 mlx4_wq = create_singlethread_workqueue("mlx4");
1320 if (!mlx4_wq)
1321 return -ENOMEM;
1272 1322
1273 ret = pci_register_driver(&mlx4_driver); 1323 ret = pci_register_driver(&mlx4_driver);
1274 return ret < 0 ? ret : 0; 1324 return ret < 0 ? ret : 0;
@@ -1277,7 +1327,7 @@ static int __init mlx4_init(void)
1277static void __exit mlx4_cleanup(void) 1327static void __exit mlx4_cleanup(void)
1278{ 1328{
1279 pci_unregister_driver(&mlx4_driver); 1329 pci_unregister_driver(&mlx4_driver);
1280 mlx4_catas_cleanup(); 1330 destroy_workqueue(mlx4_wq);
1281} 1331}
1282 1332
1283module_init(mlx4_init); 1333module_init(mlx4_init);