aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mlx4/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/mlx4/main.c')
-rw-r--r--drivers/net/mlx4/main.c106
1 files changed, 79 insertions, 27 deletions
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 6ef2490d5c3e..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++) {
@@ -1230,6 +1278,8 @@ static struct pci_device_id mlx4_pci_table[] = {
1230 { PCI_VDEVICE(MELLANOX, 0x673c) }, /* MT25408 "Hermon" QDR PCIe gen2 */ 1278 { PCI_VDEVICE(MELLANOX, 0x673c) }, /* MT25408 "Hermon" QDR PCIe gen2 */
1231 { PCI_VDEVICE(MELLANOX, 0x6368) }, /* MT25408 "Hermon" EN 10GigE */ 1279 { PCI_VDEVICE(MELLANOX, 0x6368) }, /* MT25408 "Hermon" EN 10GigE */
1232 { PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */ 1280 { PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */
1281 { PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */
1282 { PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
1233 { 0, } 1283 { 0, }
1234}; 1284};
1235 1285
@@ -1264,9 +1314,11 @@ static int __init mlx4_init(void)
1264 if (mlx4_verify_params()) 1314 if (mlx4_verify_params())
1265 return -EINVAL; 1315 return -EINVAL;
1266 1316
1267 ret = mlx4_catas_init(); 1317 mlx4_catas_init();
1268 if (ret) 1318
1269 return ret; 1319 mlx4_wq = create_singlethread_workqueue("mlx4");
1320 if (!mlx4_wq)
1321 return -ENOMEM;
1270 1322
1271 ret = pci_register_driver(&mlx4_driver); 1323 ret = pci_register_driver(&mlx4_driver);
1272 return ret < 0 ? ret : 0; 1324 return ret < 0 ? ret : 0;
@@ -1275,7 +1327,7 @@ static int __init mlx4_init(void)
1275static void __exit mlx4_cleanup(void) 1327static void __exit mlx4_cleanup(void)
1276{ 1328{
1277 pci_unregister_driver(&mlx4_driver); 1329 pci_unregister_driver(&mlx4_driver);
1278 mlx4_catas_cleanup(); 1330 destroy_workqueue(mlx4_wq);
1279} 1331}
1280 1332
1281module_init(mlx4_init); 1333module_init(mlx4_init);